Compare commits

..

24 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
108 changed files with 2303 additions and 7577 deletions

3
.gitattributes vendored
View File

@@ -1,5 +1,4 @@
/.travis.yml export-ignore
/appveyor.yml export-ignore
/ci 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

@@ -26,8 +26,8 @@ Build Requirements
slashes rather than backslashes in the path (for example,
**c:/nasm/nasm.exe**).
* NASM and Yasm are located in the CRB (Code Ready Builder) repository on
Red Hat Enterprise Linux 8 and in the PowerTools repository on CentOS 8,
which is not enabled by default.
Red Hat Enterprise Linux 8 and in the PowerTools repository on RHEL
derivatives, which is not enabled by default.
### Un*x Platforms (including Linux, Mac, FreeBSD, Solaris, and Cygwin)
@@ -47,7 +47,8 @@ Build Requirements
If you don't already have Visual C++, then the easiest way to get it is by
installing
[Visual Studio Community Edition](https://visualstudio.microsoft.com).
[Visual Studio Community Edition](https://visualstudio.microsoft.com),
which includes everything necessary to build libjpeg-turbo.
* You can also download and install the standalone Windows SDK (for Windows 7
or later), which includes command-line versions of the 32-bit and 64-bit
@@ -61,28 +62,9 @@ Build Requirements
cannot be used with earlier versions of Visual C++, and vice versa.
* 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.
- Vcpkg
You need to download and install libpng using the [vcpkg](https://github.com/Microsoft/vcpkg) dependency manager:
git clone https://github.com/Microsoft/vcpkg.git
cd vcpkg
./bootstrap-vcpkg.sh
./vcpkg integrate install
vcpkg install libpng:x64-windows
vcpkg install libpng:x64-windows-static
Actually, you can just download and install MozJPEG using vcpkg dependency manager:
vcpkg install mozjpeg
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.
... OR ...
- MinGW
[MSYS2](http://msys2.github.io/) or [tdm-gcc](http://tdm-gcc.tdragon.net/)
@@ -97,6 +79,14 @@ Build Requirements
* If using JDK 11 or later, CMake 3.10.x or later must also be used.
Sub-Project Builds
------------------
The libjpeg-turbo build system does not support being included as a sub-project
using the CMake `add_subdirectory()` function. Use the CMake
`ExternalProject_Add()` function instead.
Out-of-Tree Builds
------------------

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

@@ -9,8 +9,9 @@ if(CMAKE_EXECUTABLE_SUFFIX)
set(CMAKE_EXECUTABLE_SUFFIX_TMP ${CMAKE_EXECUTABLE_SUFFIX})
endif()
project(mozjpeg C)
set(VERSION 4.1.1)
project(libjpeg-turbo C)
set(VERSION 2.1.4)
set(COPYRIGHT_YEAR "1991-2022")
string(REPLACE "." ";" VERSION_TRIPLET ${VERSION})
list(GET VERSION_TRIPLET 0 VERSION_MAJOR)
list(GET VERSION_TRIPLET 1 VERSION_MINOR)
@@ -186,13 +187,11 @@ option(ENABLE_STATIC "Build static libraries" TRUE)
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)
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)
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)
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)
if(CMAKE_C_COMPILER_ABI MATCHES "ELF X32")
set(WITH_JAVA 0)
@@ -539,7 +538,7 @@ if(CMAKE_EXECUTABLE_SUFFIX_TMP)
endif()
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
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
@@ -637,9 +636,6 @@ if(WITH_TURBOJPEG)
add_executable(tjunittest tjunittest.c tjutil.c md5/md5.c md5/md5hl.c)
target_link_libraries(tjunittest turbojpeg)
if(UNIX)
target_link_libraries(tjunittest m)
endif()
add_executable(tjbench tjbench.c tjutil.c)
target_link_libraries(tjbench turbojpeg)
@@ -649,9 +645,6 @@ if(WITH_TURBOJPEG)
add_executable(tjexample tjexample.c)
target_link_libraries(tjexample turbojpeg)
if(UNIX)
target_link_libraries(tjexample m)
endif()
endif()
if(ENABLE_STATIC)
@@ -667,9 +660,6 @@ if(WITH_TURBOJPEG)
add_executable(tjunittest-static tjunittest.c tjutil.c md5/md5.c
md5/md5hl.c)
target_link_libraries(tjunittest-static turbojpeg-static)
if(UNIX)
target_link_libraries(tjunittest-static m)
endif()
add_executable(tjbench-static tjbench.c tjutil.c)
target_link_libraries(tjbench-static turbojpeg-static)
@@ -688,58 +678,21 @@ else()
set(COMPILE_FLAGS "-DBMP_SUPPORTED -DGIF_SUPPORTED -DPPM_SUPPORTED -DTARGA_SUPPORTED ${USE_SETMODE}")
set(CJPEG_BMP_SOURCES rdbmp.c rdtarga.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()
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})
set_property(TARGET cjpeg-static PROPERTY COMPILE_FLAGS ${COMPILE_FLAGS})
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
wrppm.c ${DJPEG_BMP_SOURCES})
set_property(TARGET djpeg-static PROPERTY COMPILE_FLAGS ${COMPILE_FLAGS})
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)
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}")
endif()
@@ -813,9 +766,9 @@ if(WITH_12BIT)
set(MD5_PPM_420M_ISLOW_1_4 35fd59d866e44659edfa3c18db2a3edb)
set(MD5_PPM_420M_ISLOW_1_8 ccaed48ac0aedefda5d4abe4013f4ad7)
set(MD5_PPM_420_ISLOW_SKIP15_31 86664cd9dc956536409e44e244d20a97)
set(MD5_PPM_420_ISLOW_PROG_CROP62x62_71_71 b1fd2e6de6a6db2b3f5447a0b774a117)
set(MD5_PPM_444_ISLOW_SKIP1_6 4bfeeafcbaeb2ec4b32a71cc72f64fbc)
set(MD5_PPM_444_ISLOW_PROG_CROP98x98_13_13 e6d8226f43bb30afe927e8b96646b147)
set(MD5_PPM_420_ISLOW_PROG_CROP62x62_71_71 452a21656115a163029cfba5c04fa76a)
set(MD5_PPM_444_ISLOW_SKIP1_6 ef63901f71ef7a75cd78253fc0914f84)
set(MD5_PPM_444_ISLOW_PROG_CROP98x98_13_13 15b173fb5872d9575572fbcc1b05956f)
set(MD5_JPEG_CROP cdb35ff4b4519392690ea040c56ea99c)
else()
set(TESTORIG testorig.jpg)
@@ -826,8 +779,8 @@ else()
set(MD5_BMP_RGB_ISLOW_565D 4cfa0928ef3e6bb626d7728c924cfda4)
set(MD5_JPEG_422_IFAST_OPT 2540287b79d913f91665e660303ab2c8)
set(MD5_PPM_422_IFAST 35bd6b3f833bad23de82acea847129fa)
set(MD5_JPEG_440_ISLOW 368200a98a9d5041170a6232491522f9)
set(MD5_PPM_440_ISLOW 59d718725c83d37a0b59b7e4e355d2fb)
set(MD5_JPEG_440_ISLOW 538bc02bd4b4658fd85de6ece6cbeda6)
set(MD5_PPM_440_ISLOW 11e7eab7ef7ef3276934bb7e7b6bb377)
set(MD5_PPM_422M_IFAST 8dbc65323d62cca7c91ba02dd1cfa81d)
set(MD5_BMP_422M_IFAST_565 3294bd4d9a1f2b3d08ea6020d0db7065)
set(MD5_BMP_422M_IFAST_565D da98c9c7b6039511be4a79a878a9abc1)
@@ -878,10 +831,10 @@ else()
set(MD5_BMP_420M_ISLOW_565D ce034037d212bc403330df6f915c161b)
set(MD5_PPM_420_ISLOW_SKIP15_31 c4c65c1e43d7275cd50328a61e6534f0)
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_444_ISLOW_SKIP1_6 2f4d84e9832ce741f5f0666a84632a5a)
set(MD5_PPM_444_ISLOW_PROG_CROP98x98_13_13 d04ed9d1a2a059455b343bf07a2433a3)
set(MD5_PPM_444_ISLOW_SKIP1_6 5606f86874cf26b8fcee1117a0a436a6)
set(MD5_PPM_444_ISLOW_PROG_CROP98x98_13_13 db87dc7ce26bcdc7a6b56239ce2b9d6c)
set(MD5_PPM_444_ISLOW_ARI_CROP37x37_0_0 cb57b32bd6d03e35432362f7bf184b6d)
set(MD5_JPEG_CROP b4197f377e621c4e9b1d20471432610d)
endif()
@@ -956,10 +909,8 @@ if(CPU_TYPE STREQUAL "x86_64" OR CPU_TYPE STREQUAL "i386")
set(DEFAULT_FLOATTEST sse)
elseif(CPU_TYPE STREQUAL "x86_64")
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
# 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
# manually.
endif()
@@ -1013,22 +964,22 @@ foreach(libtype ${TEST_LIBTYPES})
add_test(tjunittest-${libtype}-bmp
${CMAKE_CROSSCOMPILING_EMULATOR} tjunittest${suffix} -bmp)
set(MD5_PPM_GRAY_TILE b8f5defbd8e76a1d557b860b457bcd05)
set(MD5_PPM_420_8x8_TILE cb8bb3f7de153b4cfbf6cc6f36b43bf0)
set(MD5_PPM_420_16x16_TILE a144f52396cba331bb85c6b43d1deedc)
set(MD5_PPM_420_32x32_TILE 5d6a7c35bb44adc89581466b253ef920)
set(MD5_PPM_GRAY_TILE 89d3ca21213d9d864b50b4e4e7de4ca6)
set(MD5_PPM_420_8x8_TILE 847fceab15c5b7b911cb986cf0f71de3)
set(MD5_PPM_420_16x16_TILE ca45552a93687e078f7137cc4126a7b0)
set(MD5_PPM_420_32x32_TILE d8676f1d6b68df358353bba9844f4a00)
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_TILE 391df0063a66d7656f18f3a5cb107357)
set(MD5_PPM_420M_TILE 75ffdf14602258c5c189522af57fa605)
set(MD5_PPM_422_8x8_TILE d83dacd9fc73b0a6f10c09acad64eb1e)
set(MD5_PPM_422_16x16_TILE 35077fb610d72dd743b1eb0cbcfe10fb)
set(MD5_PPM_422_32x32_TILE 06a45b730ffa26990af4930140c3233b)
set(MD5_PPM_422_64x64_TILE 007d991538e571e6e56c54b6224b060a)
set(MD5_PPM_422_32x32_TILE e6902ed8a449ecc0f0d6f2bf945f65f7)
set(MD5_PPM_422_64x64_TILE 2b4502a8f316cedbde1da7bce3d2231e)
set(MD5_PPM_422_128x128_TILE f0b5617d578f5e13c8eee215d64d4877)
set(MD5_PPM_422M_8x8_TILE 828941d7f41cd6283abd6beffb7fd51d)
set(MD5_PPM_422M_TILE df4b4c784feb513d250c2dd76d61fa1a)
set(MD5_PPM_444_TILE c757cfea44ac6439fea03ef57d04b7de)
set(MD5_PPM_422M_TILE e877ae1324c4a280b95376f7f018172f)
set(MD5_PPM_444_TILE 7964e41e67cfb8d0a587c0aa4798f9c3)
# Test compressing from/decompressing to an arbitrary subregion of a larger
# image buffer
@@ -1041,6 +992,25 @@ foreach(libtype ${TEST_LIBTYPES})
set_tests_properties(tjbench-${libtype}-tile
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
${CMAKE_COMMAND} -E copy_if_different ${TESTIMAGES}/testorig.ppm
testout_tilem.ppm)
@@ -1049,6 +1019,27 @@ foreach(libtype ${TEST_LIBTYPES})
-rgb -fastupsample -quiet -tile -benchtime 0.01 -warmup 0)
set_tests_properties(tjbench-${libtype}-tilem
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()
# These tests are carefully crafted to provide full coverage of as many of
@@ -1071,7 +1062,7 @@ foreach(libtype ${TEST_LIBTYPES})
endmacro()
# 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
${MD5_JPEG_RGB_ISLOW})
@@ -1086,7 +1077,7 @@ foreach(libtype ${TEST_LIBTYPES})
set_tests_properties(djpeg-${libtype}-rgb-islow-icc-cmp PROPERTIES
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
${MD5_JPEG_RGB_ISLOW2} cjpeg-${libtype}-rgb-islow)
@@ -1103,7 +1094,7 @@ foreach(libtype ${TEST_LIBTYPES})
endif()
# 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
${MD5_JPEG_422_IFAST_OPT})
@@ -1142,7 +1133,7 @@ foreach(libtype ${TEST_LIBTYPES})
# CC: RGB->YCC SAMP: fullsize/h2v2 FDCT: ifast ENT: prog huff
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
${MD5_JPEG_420_IFAST_Q100_PROG})
@@ -1157,7 +1148,7 @@ foreach(libtype ${TEST_LIBTYPES})
${MD5_PPM_420M_Q100_IFAST} cjpeg-${libtype}-420-q100-ifast-prog)
# 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
${MD5_JPEG_GRAY_ISLOW})
@@ -1185,13 +1176,13 @@ foreach(libtype ${TEST_LIBTYPES})
# CC: RGB->YCC SAMP: fullsize smooth/h2v2 smooth FDCT: islow
# 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
${MD5_JPEG_420S_IFAST_OPT})
if(FLOATTEST)
# 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
${MD5_JPEG_3x2_FLOAT_PROG_${FLOATTEST_UC}})
@@ -1202,7 +1193,7 @@ foreach(libtype ${TEST_LIBTYPES})
endif()
# 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
${MD5_JPEG_3x2_IFAST_PROG})
@@ -1213,17 +1204,17 @@ foreach(libtype ${TEST_LIBTYPES})
if(WITH_ARITH_ENC)
# 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
${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
${MD5_JPEG_420_ISLOW_ARI})
# CC: YCC->RGB SAMP: fullsize FDCT: islow ENT: prog arith
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
${MD5_JPEG_444_ISLOW_PROGARI})
endif()
@@ -1234,7 +1225,7 @@ foreach(libtype ${TEST_LIBTYPES})
testout_420m_ifast_ari.ppm ${TESTIMAGES}/testimgari.jpg
${MD5_PPM_420M_IFAST_ARI})
add_bittest(jpegtran 420-islow "-revert"
add_bittest(jpegtran 420-islow ""
testout_420_islow.jpg ${TESTIMAGES}/testimgari.jpg
${MD5_JPEG_420_ISLOW})
endif()
@@ -1357,7 +1348,7 @@ foreach(libtype ${TEST_LIBTYPES})
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}
${MD5_JPEG_CROP})
@@ -1510,8 +1501,11 @@ if(UNIX OR MINGW)
DESTINATION ${CMAKE_INSTALL_MANDIR}/man1)
endif()
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/pkgscripts/libjpeg.pc
${CMAKE_CURRENT_BINARY_DIR}/pkgscripts/libturbojpeg.pc
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

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,38 @@
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
=====

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: 0)
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.

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 with 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.
* Trellis quantization. When converting other formats to JPEG it maximizes quality/filesize ratio.
* 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.
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.
## Releases
* [Latest release](https://github.com/mozilla/mozjpeg/releases/latest)
* [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/)
Building libjpeg-turbo
======================
## 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 2019
configuration: Release
platform:
- Win32
- x64
install:
- if %PLATFORM% == Win32 (set ARCH=x86)
- if %PLATFORM% == x64 (set ARCH=x64)
## 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
- cmd: >-
if not exist c:\installers mkdir c:\installers
before_build:
- 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
mkdir c:\temp
build_script:
## 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
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
- cmake --build shared --config Release
7z x c:\installers\nasm-2.10.01-win32.zip -oc:\ > c:\installers\nasm.install.log
## Build static
- 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
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 --build static --config Release
md "c:\Program Files (x86)\mingw-w64\i686-6.4.0-posix-dwarf-rt_v5-rev0"
after_build:
- 7z a mozjpeg-%GIT_VERSION%-win-%ARCH%.zip shared/Release static/Release
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
artifacts:
- path: '*.zip'
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"
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:
- C:\ProgramData\chocolatey\bin
- C:\ProgramData\chocolatey\lib
- C:\Program Files\NASM
- C:\tools\vcpkg\installed
- c:\installers\nasm-2.10.01-win32.zip -> appveyor.yml
- c:\installers\i686-6.4.0-release-posix-dwarf-rt_v5-rev0.7z -> appveyor.yml
- c:\installers\x86_64-6.4.0-release-posix-seh-rt_v5-rev0.7z -> appveyor.yml
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:
description: 'Automated build using Appveyor'
provider: GitHub
auth_token:
secure: 2Jj47Q5HnaPob9U4yX2t4q4TYTw4JWU6cS56mM12aoRLgfYkZ4gRZPySIzfmTPqC
artifact: /.*\.zip/
on:
APPVEYOR_REPO_TAG: true # deploy on tag push only
provider: S3
access_key_id:
secure: Z74OYogQ6bNV/I+6b5ZEXig74+6MW2WLER0v/bPM/uk=
secret_access_key:
secure: cyGZhHVCFwZ9jgf5lXoW69mVtECmqwx3eLo61ha8ueWbMYlHho7lwDXwVvxOFiCa
bucket: libjpeg-turbo-pr
region:
secure: qSElYBgBRcEUf88M6Osthw==
folder: $(APPVEYOR_REPO_BRANCH)/windows
set_public: true
remove_files: true

View File

@@ -103,19 +103,14 @@ JMESSAGE(JERR_BAD_CMAP_FILE,
JMESSAGE(JERR_TOO_MANY_COLORS,
"Output file format cannot handle %d colormap entries")
JMESSAGE(JERR_UNGETC_FAILED, "ungetc failed")
#ifdef PNG_SUPPORTED
#ifdef TARGA_SUPPORTED
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
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
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
JMSG_LASTADDONCODE

View File

@@ -6,9 +6,8 @@
* Modified 2019 by Guido Vollbeding.
* libjpeg-turbo Modifications:
* Copyright (C) 2017, 2019, 2021, D. R. Commander.
* mozjpeg Modifications:
* Copyright (C) 2014, Mozilla Corporation.
* For conditions of distribution and use, see the accompanying README.ijg file.
* For conditions of distribution and use, see the accompanying README.ijg
* file.
*
* This file contains common declarations for the sample applications
* cjpeg and djpeg. It is NOT used by the core JPEG library.
@@ -21,7 +20,6 @@
#include "jerror.h" /* get library error codes too */
#include "cderror.h" /* get application-specific error codes */
#define JPEG_RAW_READER 0
/*
* Object interface for cjpeg's source file decoding modules
@@ -41,12 +39,6 @@ struct cjpeg_source_struct {
#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
JDIMENSION max_pixels;
#endif
#if JPEG_RAW_READER
// For reading JPEG
JSAMPARRAY plane_pointer[4];
#endif
jpeg_saved_marker_ptr marker_list;
};
@@ -111,8 +103,6 @@ typedef struct cdjpeg_progress_mgr *cd_progress_ptr;
/* 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,
boolean use_inversion_array);
EXTERN(djpeg_dest_ptr) jinit_write_bmp(j_decompress_ptr cinfo, boolean is_os2,

246
cjpeg.c
View File

@@ -6,9 +6,8 @@
* Modified 2003-2011 by Guido Vollbeding.
* libjpeg-turbo Modifications:
* Copyright (C) 2010, 2013-2014, 2017, 2019-2022, D. R. Commander.
* mozjpeg Modifications:
* Copyright (C) 2014, Mozilla Corporation.
* 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 a command-line user interface for the JPEG compressor.
* It should work on any system with Unix- or MS-DOS-style command lines.
@@ -39,16 +38,6 @@
#include "jversion.h" /* for version message */
#include "jconfigint.h"
#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. */
@@ -87,8 +76,7 @@ static const char * const cdjpeg_message_table[] = {
*/
static boolean is_targa; /* records user -targa switch */
static boolean is_jpeg;
static boolean copy_markers;
LOCAL(cjpeg_source_ptr)
select_file_type(j_compress_ptr cinfo, FILE *infile)
@@ -121,19 +109,10 @@ select_file_type(j_compress_ptr cinfo, FILE *infile)
case 'P':
return jinit_read_ppm(cinfo);
#endif
#ifdef PNG_SUPPORTED
case 0x89:
copy_markers = TRUE;
return jinit_read_png(cinfo);
#endif
#ifdef TARGA_SUPPORTED
case 0x00:
return jinit_read_targa(cinfo);
#endif
case 0xff:
is_jpeg = TRUE;
copy_markers = TRUE;
return jinit_read_jpeg(cinfo);
default:
ERREXIT(cinfo, JERR_UNKNOWN_FORMAT);
break;
@@ -216,32 +195,15 @@ usage(void)
fprintf(stderr, " -grayscale Create monochrome JPEG file\n");
fprintf(stderr, " -rgb Create RGB JPEG file\n");
#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
#ifdef C_PROGRESSIVE_SUPPORTED
fprintf(stderr, " -progressive Create progressive JPEG file (enabled by default)\n");
fprintf(stderr, " -progressive Create progressive JPEG file\n");
#endif
fprintf(stderr, " -baseline Create baseline JPEG file (disable progressive coding)\n");
#ifdef TARGA_SUPPORTED
fprintf(stderr, " -targa Input file is Targa format (usually not needed)\n");
#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, " -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
fprintf(stderr, " -arithmetic Use arithmetic coding\n");
#endif
@@ -257,17 +219,6 @@ usage(void)
fprintf(stderr, " -dct float Use floating-point DCT method [legacy feature]%s\n",
(JDCT_DEFAULT == JDCT_FLOAT ? " (default)" : ""));
#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 Tuned for MS-SSIM on Kodak image set\n");
fprintf(stderr, " - 3 ImageMagick table by N. Robidoux (default)\n");
fprintf(stderr, " - 4 Tuned for PSNR-HVS on Kodak image set\n");
fprintf(stderr, " - 5 Table from paper by Klein, Silverstein and Carney\n");
fprintf(stderr, " - 6 Table from paper by Watson, Taylor and Borthwick\n");
fprintf(stderr, " - 7 Table from paper by Ahumada, Watson, Peterson\n");
fprintf(stderr, " - 8 Table from paper by Peterson, Ahumada and Watson\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");
#ifdef INPUT_SMOOTHING_SUPPORTED
@@ -283,6 +234,7 @@ usage(void)
fprintf(stderr, " -verbose or -debug Emit debug output\n");
fprintf(stderr, " -version Print version information and exit\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, " -qslots N[,...] Set component quantization tables\n");
fprintf(stderr, " -sample HxV[,...] Set component sampling factors\n");
@@ -318,11 +270,7 @@ parse_switches(j_compress_ptr cinfo, int argc, char **argv,
/* Set up default JPEG parameters. */
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;
#endif
is_targa = FALSE;
icc_filename = NULL;
outfilename = NULL;
@@ -349,9 +297,6 @@ parse_switches(j_compress_ptr cinfo, int argc, char **argv,
/* Use arithmetic coding. */
#ifdef C_ARITH_CODING_SUPPORTED
cinfo->arith_code = TRUE;
/* No table optimization required for AC */
cinfo->optimize_coding = FALSE;
#else
fprintf(stderr, "%s: sorry, arithmetic coding not supported\n",
progname);
@@ -361,27 +306,19 @@ parse_switches(j_compress_ptr cinfo, int argc, char **argv,
} else if (keymatch(arg, "baseline", 1)) {
/* Force baseline-compatible output (8-bit quantizer values). */
force_baseline = TRUE;
/* Disable multiple scans */
simple_progressive = FALSE;
cinfo->num_scans = 0;
cinfo->scan_info = NULL;
} else if (keymatch(arg, "dct", 2)) {
/* Select DCT algorithm. */
if (++argn >= argc) { /* advance to next argument */
fprintf(stderr, "%s: missing argument for dct\n", progname);
if (++argn >= argc) /* advance to next argument */
usage();
}
if (keymatch(argv[argn], "int", 1)) {
cinfo->dct_method = JDCT_ISLOW;
} else if (keymatch(argv[argn], "fast", 2)) {
cinfo->dct_method = JDCT_IFAST;
} else if (keymatch(argv[argn], "float", 2)) {
cinfo->dct_method = JDCT_FLOAT;
} else {
fprintf(stderr, "%s: invalid argument for dct\n", progname);
} else
usage();
}
} else if (keymatch(arg, "debug", 1) || keymatch(arg, "verbose", 1)) {
/* Enable debug printouts. */
@@ -403,10 +340,8 @@ parse_switches(j_compress_ptr cinfo, int argc, char **argv,
PACKAGE_NAME, VERSION, BUILD);
exit(EXIT_SUCCESS);
} else if (keymatch(arg, "fastcrush", 4)) {
jpeg_c_set_bool_param(cinfo, JBOOLEAN_OPTIMIZE_SCANS, FALSE);
} else if (keymatch(arg, "grayscale", 2) || keymatch(arg, "greyscale",2)) {
} else if (keymatch(arg, "grayscale", 2) ||
keymatch(arg, "greyscale", 2)) {
/* Force a monochrome JPEG file to be generated. */
jpeg_set_colorspace(cinfo, JCS_GRAYSCALE);
@@ -414,18 +349,6 @@ parse_switches(j_compress_ptr cinfo, int argc, char **argv,
/* Force an RGB JPEG file to be generated. */
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)) {
/* Set ICC filename. */
if (++argn >= argc) /* advance to next argument */
@@ -445,13 +368,6 @@ parse_switches(j_compress_ptr cinfo, int argc, char **argv,
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)) {
/* Enable entropy parm optimization. */
#ifdef ENTROPY_OPT_SUPPORTED
@@ -464,10 +380,8 @@ parse_switches(j_compress_ptr cinfo, int argc, char **argv,
} else if (keymatch(arg, "outfile", 4)) {
/* Set output file name. */
if (++argn >= argc) { /* advance to next argument */
fprintf(stderr, "%s: missing argument for outfile\n", progname);
if (++argn >= argc) /* advance to next argument */
usage();
}
outfilename = argv[argn]; /* save it away for later use */
} else if (keymatch(arg, "progressive", 1)) {
@@ -493,10 +407,8 @@ parse_switches(j_compress_ptr cinfo, int argc, char **argv,
} else if (keymatch(arg, "quality", 1)) {
/* Quality ratings (quantization table scaling factors). */
if (++argn >= argc) { /* advance to next argument */
fprintf(stderr, "%s: missing argument for quality\n", progname);
if (++argn >= argc) /* advance to next argument */
usage();
}
qualityarg = argv[argn];
} else if (keymatch(arg, "qslots", 2)) {
@@ -518,21 +430,6 @@ parse_switches(j_compress_ptr cinfo, int argc, char **argv,
} else if (keymatch(arg, "report", 3)) {
report = TRUE;
} else if (keymatch(arg, "quant-table", 7)) {
int val;
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)) {
/* Restart interval in MCU rows (or in MCUs with 'b'). */
@@ -553,11 +450,6 @@ parse_switches(j_compress_ptr cinfo, int argc, char **argv,
/* 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)) {
/* Set sampling factors. */
if (++argn >= argc) /* advance to next argument */
@@ -600,60 +492,7 @@ parse_switches(j_compress_ptr cinfo, int argc, char **argv,
/* Input file is Targa format. */
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 {
fprintf(stderr, "%s: unknown option '%s'\n", progname, arg);
usage(); /* bogus switch */
}
}
@@ -665,28 +504,20 @@ parse_switches(j_compress_ptr cinfo, int argc, char **argv,
/* Set quantization tables for selected quality. */
/* Some or all may be overridden if -qtables is present. */
if (qualityarg != NULL) /* process -quality if it was present */
if (! set_quality_ratings(cinfo, qualityarg, force_baseline)) {
fprintf(stderr, "%s: can't set quality ratings\n", progname);
if (!set_quality_ratings(cinfo, qualityarg, force_baseline))
usage();
}
if (qtablefile != NULL) /* process -qtables if it was present */
if (! read_quant_tables(cinfo, qtablefile, force_baseline)) {
fprintf(stderr, "%s: can't read qtable file\n", progname);
if (!read_quant_tables(cinfo, qtablefile, force_baseline))
usage();
}
if (qslotsarg != NULL) /* process -qslots if it was present */
if (!set_quant_slots(cinfo, qslotsarg))
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 (! set_sample_factors(cinfo, samplearg)) {
fprintf(stderr, "%s: can't set sample factors\n", progname);
if (!set_sample_factors(cinfo, samplearg))
usage();
}
#ifdef C_PROGRESSIVE_SUPPORTED
if (simple_progressive) /* process -progressive; -scans can override */
@@ -743,11 +574,6 @@ main(int argc, char **argv)
unsigned long outsize = 0;
JDIMENSION num_scanlines;
/* On Mac, fetch a command line. */
#ifdef USE_CCOMMAND
argc = ccommand(&argv);
#endif
progname = argv[0];
if (progname == NULL || progname[0] == 0)
progname = "cjpeg"; /* in case C library doesn't provide it */
@@ -878,9 +704,6 @@ main(int argc, char **argv)
(*src_mgr->start_input) (&cinfo, src_mgr);
/* Now that we know input colorspace, fix colorspace-dependent defaults */
#if JPEG_RAW_READER
if (!is_jpeg)
#endif
jpeg_default_colorspace(&cinfo);
/* Adjust default compression parameters by re-parsing the options */
@@ -902,50 +725,13 @@ main(int argc, char **argv)
/* Start compressor */
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)
jpeg_write_icc_profile(&cinfo, icc_profile, (unsigned int)icc_len);
/* Process data */
while (cinfo.next_scanline < cinfo.image_height) {
num_scanlines = (*src_mgr->get_pixel_rows) (&cinfo, src_mgr);
#if JPEG_RAW_READER
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);
(void)jpeg_write_scanlines(&cinfo, src_mgr->buffer, num_scanlines);
}
/* Finish compression and release memory */

View File

@@ -109,10 +109,13 @@ configure_file(win/${INST_ID}/projectTargets-release.cmake.in
if(WITH_JAVA)
set(JAVA_DEPEND turbojpeg-java)
endif()
if(WITH_TURBOJPEG)
set(TURBOJPEG_DEPEND turbojpeg turbojpeg-static tjbench)
endif()
add_custom_target(installer
makensis -nocd ${INST_DEFS} installer.nsi
DEPENDS jpeg jpeg-static turbojpeg turbojpeg-static rdjpgcom wrjpgcom
cjpeg djpeg jpegtran tjbench ${JAVA_DEPEND}
DEPENDS jpeg jpeg-static rdjpgcom wrjpgcom cjpeg djpeg jpegtran
${JAVA_DEPEND} ${TURBOJPEG_DEPEND}
SOURCES installer.nsi)
endif() # WIN32
@@ -159,7 +162,9 @@ add_custom_target(tarball pkgscripts/maketarball
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(

15
djpeg.c
View File

@@ -38,16 +38,6 @@
#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. */
@@ -550,11 +540,6 @@ main(int argc, char **argv)
#endif
JDIMENSION num_scanlines;
/* On Mac, fetch a command line. */
#ifdef USE_CCOMMAND
argc = ccommand(&argv);
#endif
progname = argv[0];
if (progname == NULL || progname[0] == 0)
progname = "djpeg"; /* in case C library doesn't provide it */

View File

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

View File

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

View File

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

View File

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

View File

@@ -23,7 +23,7 @@
<tr style="height: 56px;">
<td id="projectalign" style="padding-left: 0.5em;">
<div id="projectname">TurboJPEG
&#160;<span id="projectnumber">2.1</span>
&#160;<span id="projectnumber">2.1.4</span>
</div>
</td>
</tr>
@@ -273,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="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="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="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>
@@ -1725,16 +1725,16 @@ If you choose option 1, <code>*jpegSize</code> should be set to the size of your
</table>
</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>
<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">jpegBuf</td><td>pointer to a buffer containing a JPEG image</td></tr>
<tr><td class="paramname">jpegSize</td><td>size of the JPEG image (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">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">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">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">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 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. 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. 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>.) 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>.) If <code>jpegBuf</code> points to a tables-only datastream, then <code>jpegColorspace</code> is ignored.</td></tr>
</table>
</dd>
</dl>

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -1,5 +1,5 @@
PROJECT_NAME = TurboJPEG
PROJECT_NUMBER = 2.1
PROJECT_NUMBER = 2.1.4
OUTPUT_DIRECTORY = doc/
USE_WINDOWS_ENCODING = NO
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
* the local non-volatile jpeg_decompress_struct instance below the setjmp()
* 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.
*/

View File

@@ -25,16 +25,20 @@ 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 cjpeg.cc ../cdjpeg.c ../rdbmp.c ../rdgif.c
../rdppm.c ../rdswitch.c ../rdtarga.c)
set_property(TARGET cjpeg_fuzzer PROPERTY COMPILE_FLAGS ${COMPILE_FLAGS})
target_link_libraries(cjpeg_fuzzer ${FUZZ_LIBRARY} jpeg-static)
install(TARGETS cjpeg_fuzzer RUNTIME DESTINATION ${FUZZ_BINDIR})
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 ${source_file})
target_link_libraries(${target}_fuzzer ${FUZZ_LIBRARY} turbojpeg-static)
install(TARGETS ${target}_fuzzer RUNTIME DESTINATION ${FUZZ_BINDIR})
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)

View File

@@ -3,16 +3,23 @@
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
-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_seed_corpus.zip
cp $SRC/compress_fuzzer_seed_corpus.zip $OUT/compress_fuzzer_seed_corpus.zip
cp $SRC/compress_fuzzer_seed_corpus.zip $OUT/compress_yuv_fuzzer_seed_corpus.zip
cp $SRC/decompress_fuzzer_seed_corpus.zip $OUT/libjpeg_turbo_fuzzer_seed_corpus.zip
cp $SRC/decompress_fuzzer_seed_corpus.zip $OUT/decompress_yuv_fuzzer_seed_corpus.zip
cp $SRC/decompress_fuzzer_seed_corpus.zip $OUT/transform_fuzzer_seed_corpus.zip
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

View File

@@ -37,7 +37,7 @@ if(WIN32)
${CMAKE_CURRENT_BINARY_DIR}/org/libjpegturbo/turbojpeg/TJLoader.java)
else()
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()
set(JAVA_SOURCES ${JAVA_SOURCES}
${CMAKE_CURRENT_BINARY_DIR}/org/libjpegturbo/turbojpeg/TJLoader.java)

View File

@@ -792,7 +792,8 @@
</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>
<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>
</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>

View File

@@ -418,7 +418,8 @@ implements java.io.Closeable</pre>
<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,
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>
</td>
</tr>
@@ -611,10 +612,19 @@ implements java.io.Closeable</pre>
<pre>public&nbsp;void&nbsp;setSourceImage(byte[]&nbsp;jpegImage,
int&nbsp;imageSize)
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
<code>jpegImage</code> with this decompressor instance. This image will
be used as the source image for subsequent decompress operations.</div>
<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>
<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. 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.</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>
<dd><code><a href="../../../org/libjpegturbo/turbojpeg/TJException.html" title="class in org.libjpegturbo.turbojpeg">TJException</a></code></dd></dl>
</li>

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.
*
* 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
* <code>jpegImage</code> with this decompressor instance. This image will
* be used as the source image for subsequent decompress operations.
* 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. 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)
*/

View File

@@ -23,8 +23,6 @@
#define JPEG_INTERNALS
#include "jinclude.h"
#include "jpeglib.h"
#include "jmemsys.h"
#include "jcmaster.h"
/*
@@ -94,16 +92,6 @@ jpeg_CreateCompress(j_compress_ptr cinfo, int version, size_t structsize)
/* OK, I'm ready */
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));
memset(cinfo->master, 0, sizeof(my_comp_master));
cinfo->master->compress_profile = JCP_MAX_COMPRESSION;
}

View File

@@ -3,9 +3,8 @@
*
* Copyright (C) 1994-1996, Thomas G. Lane.
* This file is part of the Independent JPEG Group's software.
* mozjpeg Modifications:
* Copyright (C) 2014, Mozilla Corporation.
* 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
* 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)
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 */
(*cinfo->err->reset_error_mgr) ((j_common_ptr)cinfo);
(*cinfo->dest->init_destination) (cinfo);

View File

@@ -22,7 +22,7 @@
#define JPEG_INTERNALS
#include "jinclude.h"
#include "jpeglib.h"
#include <math.h>
/* Expanded entropy encoder object for arithmetic encoding. */
@@ -66,8 +66,8 @@ typedef arith_entropy_encoder *arith_entropy_ptr;
* in the lower bits (mask 0x7F).
*/
#define DC_STAT_BINS 64
#define AC_STAT_BINS 256
#define DC_STAT_BINS 64
#define AC_STAT_BINS 256
/* NOTE: Uncomment the following #define if you want to use the
* 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
#define ISHIFT_TEMPS int ishift_temp;
#define IRIGHT_SHIFT(x, shft) \
((ishift_temp = (x)) < 0 ? \
((ishift_temp = (x)) < 0 ? \
(ishift_temp >> (shft)) | ((~0) << (16 - (shft))) : \
(ishift_temp >> (shft)))
(ishift_temp >> (shft)))
#else
#define ISHIFT_TEMPS
#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;
/* Do not emit bytes during trellis passes */
if (cinfo->master->trellis_passes)
return;
*dest->next_output_byte++ = (JOCTET) val;
*dest->next_output_byte++ = (JOCTET)val;
if (--dest->free_in_buffer == 0)
if (!(*dest->empty_output_buffer) (cinfo))
ERREXIT(cinfo, JERR_CANT_SUSPEND);
@@ -238,8 +234,8 @@ arith_encode(j_compress_ptr cinfo, unsigned char *st, int val)
*/
sv = *st;
qe = jpeg_aritab[sv & 0x7F]; /* => Qe_Value */
nl = qe & 0xFF; qe >>= 8; /* Next_Index_LPS + Switch_MPS */
nm = qe & 0xFF; qe >>= 8; /* Next_Index_MPS */
nl = qe & 0xFF; qe >>= 8; /* Next_Index_LPS + Switch_MPS */
nm = qe & 0xFF; qe >>= 8; /* Next_Index_MPS */
/* Encode & estimation procedures per sections D.1.4 & D.1.5 */
e->a -= qe;
@@ -517,7 +513,7 @@ encode_mcu_AC_first(j_compress_ptr cinfo, JBLOCKROW *MCU_data)
break;
}
}
arith_encode(cinfo, st + 1, 0); st += 3; k++;
arith_encode(cinfo, st + 1, 0); st += 3; k++;
}
st += 2;
/* 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;
}
}
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 */
@@ -777,7 +773,7 @@ encode_mcu(j_compress_ptr cinfo, JBLOCKROW *MCU_data)
st = entropy->ac_stats[tbl] + 3 * (k - 1);
arith_encode(cinfo, st, 0); /* EOB decision */
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);
/* Figure F.6: Encoding nonzero value v */
@@ -834,7 +830,6 @@ start_pass(j_compress_ptr cinfo, boolean gather_statistics)
arith_entropy_ptr entropy = (arith_entropy_ptr)cinfo->entropy;
int ci, tbl;
jpeg_component_info *compptr;
boolean progressive_mode;
if (gather_statistics)
/* Make sure to avoid that in the master control logic!
@@ -845,12 +840,8 @@ start_pass(j_compress_ptr cinfo, boolean gather_statistics)
/* 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 */
if (progressive_mode) {
if (cinfo->progressive_mode) {
if (cinfo->Ah == 0) {
if (cinfo->Ss == 0)
entropy->pub.encode_mcu = encode_mcu_DC_first;
@@ -869,7 +860,7 @@ start_pass(j_compress_ptr cinfo, boolean gather_statistics)
for (ci = 0; ci < cinfo->comps_in_scan; ci++) {
compptr = cinfo->cur_comp_info[ci];
/* 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;
if (tbl < 0 || tbl >= NUM_ARITH_TBLS)
ERREXIT1(cinfo, JERR_NO_ARITH_TABLE, tbl);
@@ -882,7 +873,7 @@ start_pass(j_compress_ptr cinfo, boolean gather_statistics)
entropy->dc_context[ci] = 0;
}
/* 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;
if (tbl < 0 || tbl >= NUM_ARITH_TBLS)
ERREXIT1(cinfo, JERR_NO_ARITH_TABLE, tbl);
@@ -891,7 +882,7 @@ start_pass(j_compress_ptr cinfo, boolean gather_statistics)
((j_common_ptr)cinfo, JPOOL_IMAGE, AC_STAT_BINS);
memset(entropy->ac_stats[tbl], 0, AC_STAT_BINS);
#ifdef CALCULATE_SPECTRAL_CONDITIONING
if (progressive_mode)
if (cinfo->progressive_mode)
/* Section G.1.3.2: Set appropriate arithmetic conditioning value Kx */
cinfo->arith_ac_K[tbl] = cinfo->Ss +
((8 + cinfo->Se - cinfo->Ss) >> 4);
@@ -939,34 +930,3 @@ jinit_arith_encoder(j_compress_ptr cinfo)
/* Initialize index for fixed probability estimation */
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.
* It was modified by The libjpeg-turbo Project to include only code and
* information relevant to libjpeg-turbo.
* mozjpeg Modifications:
* Copyright (C) 2014, Mozilla Corporation.
* 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 the coefficient buffer controller for compression.
* This controller is the top level of the JPEG compressor proper.
@@ -17,7 +16,7 @@
#define JPEG_INTERNALS
#include "jinclude.h"
#include "jpeglib.h"
#include "jchuff.h"
/* We use a full-image coefficient buffer when doing Huffman optimization,
* 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. */
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;
typedef my_coef_controller *my_coef_ptr;
@@ -69,8 +64,6 @@ METHODDEF(boolean) compress_first_pass(j_compress_ptr cinfo,
JSAMPIMAGE input_buf);
METHODDEF(boolean) compress_output(j_compress_ptr cinfo, JSAMPIMAGE input_buf);
#endif
METHODDEF(boolean) compress_trellis_pass
(j_compress_ptr cinfo, JSAMPIMAGE input_buf);
LOCAL(void)
@@ -127,12 +120,6 @@ start_pass_coef(j_compress_ptr cinfo, J_BUF_MODE pass_mode)
coef->pub.compress_data = compress_output;
break;
#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:
ERREXIT(cinfo, JERR_BAD_BUFFER_MODE);
break;
@@ -188,8 +175,7 @@ compress_data(j_compress_ptr cinfo, JSAMPIMAGE input_buf)
(*cinfo->fdct->forward_DCT) (cinfo, compptr,
input_buf[compptr->component_index],
coef->MCU_buffer[blkn],
ypos, xpos, (JDIMENSION) blockcnt,
NULL);
ypos, xpos, (JDIMENSION)blockcnt);
if (blockcnt < compptr->MCU_width) {
/* Create some dummy blocks at the right edge of the image. */
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;
JBLOCKARRAY buffer;
JBLOCKROW thisblockrow, lastblockrow;
JBLOCKARRAY buffer_dst;
for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
ci++, compptr++) {
@@ -274,13 +259,7 @@ compress_first_pass(j_compress_ptr cinfo, JSAMPIMAGE input_buf)
buffer = (*cinfo->mem->access_virt_barray)
((j_common_ptr)cinfo, coef->whole_image[ci],
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[ci],
coef->iMCU_row_num * compptr->v_samp_factor,
(JDIMENSION) compptr->v_samp_factor, TRUE);
(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;
@@ -302,9 +281,8 @@ compress_first_pass(j_compress_ptr cinfo, JSAMPIMAGE input_buf)
thisblockrow = buffer[block_row];
(*cinfo->fdct->forward_DCT) (cinfo, compptr,
input_buf[ci], thisblockrow,
(JDIMENSION) (block_row * DCTSIZE),
(JDIMENSION) 0, blocks_across,
buffer_dst[block_row]);
(JDIMENSION)(block_row * DCTSIZE),
(JDIMENSION)0, blocks_across);
if (ndummy > 0) {
/* Create dummy blocks at the right edge of the image. */
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);
}
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.
@@ -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;
ci++, compptr++) {
coef->whole_image[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);
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);
((j_common_ptr)cinfo, JPOOL_IMAGE, FALSE,
(JDIMENSION)jround_up((long)compptr->width_in_blocks,
(long)compptr->h_samp_factor),
(JDIMENSION)jround_up((long)compptr->height_in_blocks,
(long)compptr->v_samp_factor),
(JDIMENSION)compptr->v_samp_factor);
}
#else
ERREXIT(cinfo, JERR_BAD_BUFFER_MODE);

1172
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;
}

View File

@@ -5,9 +5,8 @@
* Copyright (C) 1991-1997, Thomas G. Lane.
* It was modified by The libjpeg-turbo Project to include only code relevant
* to libjpeg-turbo.
* mozjpeg Modifications:
* Copyright (C) 2014, Mozilla Corporation.
* 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 declarations for Huffman entropy encoding routines
* that are shared between the sequential encoder (jchuff.c) and the
@@ -21,9 +20,9 @@
*/
#if BITS_IN_JSAMPLE == 8
#define MAX_COEF_BITS 10
#define MAX_COEF_BITS 10
#else
#define MAX_COEF_BITS 14
#define MAX_COEF_BITS 14
#endif
/* 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);
/* Generate an optimal table definition given the specified counts */
EXTERN(void) jpeg_gen_optimal_table
(j_compress_ptr cinfo, JHUFF_TBL *htbl, 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);
EXTERN(void) jpeg_gen_optimal_table(j_compress_ptr cinfo, JHUFF_TBL *htbl,
long freq[]);

View File

@@ -5,9 +5,8 @@
* Copyright (C) 1991-1997, Thomas G. Lane.
* libjpeg-turbo Modifications:
* Copyright (C) 2020, D. R. Commander.
* mozjpeg Modifications:
* Copyright (C) 2014, Mozilla Corporation.
* 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 initialization logic for the JPEG compressor.
* This routine is in charge of selecting the modules to be executed and
@@ -32,13 +31,13 @@
*/
GLOBAL(void)
jinit_compress_master (j_compress_ptr cinfo)
jinit_compress_master(j_compress_ptr cinfo)
{
/* Initialize master control (includes parameter checking/processing) */
jinit_c_master_control(cinfo, FALSE /* full compression */);
/* Preprocessing */
if (! cinfo->raw_data_in) {
if (!cinfo->raw_data_in) {
jinit_color_converter(cinfo);
jinit_downsampler(cinfo);
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. */
jinit_c_coef_controller(cinfo,
(boolean) (cinfo->num_scans > 1 || cinfo->optimize_coding ||
cinfo->master->optimize_scans || cinfo->master->trellis_quant));
jinit_c_coef_controller(cinfo, (boolean)(cinfo->num_scans > 1 ||
cinfo->optimize_coding));
jinit_c_main_controller(cinfo, FALSE /* never need full buffer here */);
jinit_marker_writer(cinfo);
/* 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.
* Frame and scan headers are postponed till later.

View File

@@ -184,72 +184,6 @@ emit_dqt(j_compress_ptr cinfo, int index)
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)
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)
emit_dac(j_compress_ptr cinfo)
@@ -679,14 +504,11 @@ write_frame_header(j_compress_ptr cinfo)
/* Emit DQT for each quantization table.
* Note that emit_dqt() suppresses any duplicate tables.
*/
prec = emit_multi_dqt(cinfo);
if (prec == -1) {
prec = 0;
for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
ci++, compptr++) {
prec += emit_dqt(cinfo, compptr->quant_tbl_no);
}
}
/* now prec is nonzero iff there are any 16-bit quant tables. */
/* Check for a non-baseline specification.
@@ -749,7 +571,6 @@ write_scan_header(j_compress_ptr cinfo)
/* Emit Huffman tables.
* Note that emit_dht() suppresses any duplicate tables.
*/
if (!emit_multi_dht(cinfo)) {
for (i = 0; i < cinfo->comps_in_scan; i++) {
compptr = cinfo->cur_comp_info[i];
/* 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 DRI if required --- note that DRI value could change for each scan.
* We avoid wasting space with unnecessary DRIs, however.

View File

@@ -6,9 +6,8 @@
* Modified 2003-2010 by Guido Vollbeding.
* libjpeg-turbo Modifications:
* Copyright (C) 2010, 2016, 2018, D. R. Commander.
* mozjpeg Modifications:
* Copyright (C) 2014, Mozilla Corporation.
* 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 master control logic for the JPEG compressor.
* These routines are concerned with parameter validation, initial setup,
@@ -21,11 +20,41 @@
#include "jpeglib.h"
#include "jpegcomp.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.
*/
@@ -37,7 +66,7 @@
*/
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 */
{
/* Hardwire it to "no scaling" */
@@ -50,7 +79,7 @@ jpeg_calc_jpeg_dimensions (j_compress_ptr cinfo)
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 */
{
int ci;
@@ -71,14 +100,14 @@ initial_setup (j_compress_ptr cinfo, boolean transcode_only)
ERREXIT(cinfo, JERR_EMPTY_IMAGE);
/* Make sure image isn't bigger than I can handle */
if ((long) cinfo->_jpeg_height > (long) JPEG_MAX_DIMENSION ||
(long) cinfo->_jpeg_width > (long) JPEG_MAX_DIMENSION)
ERREXIT1(cinfo, JERR_IMAGE_TOO_BIG, (unsigned int) JPEG_MAX_DIMENSION);
if ((long)cinfo->_jpeg_height > (long)JPEG_MAX_DIMENSION ||
(long)cinfo->_jpeg_width > (long)JPEG_MAX_DIMENSION)
ERREXIT1(cinfo, JERR_IMAGE_TOO_BIG, (unsigned int)JPEG_MAX_DIMENSION);
/* Width of an input scanline must be representable as JDIMENSION. */
samplesperrow = (long) cinfo->image_width * (long) cinfo->input_components;
jd_samplesperrow = (JDIMENSION) samplesperrow;
if ((long) jd_samplesperrow != samplesperrow)
samplesperrow = (long)cinfo->image_width * (long)cinfo->input_components;
jd_samplesperrow = (JDIMENSION)samplesperrow;
if ((long)jd_samplesperrow != samplesperrow)
ERREXIT(cinfo, JERR_WIDTH_OVERFLOW);
/* For now, precision must match compiled-in value... */
@@ -119,18 +148,18 @@ initial_setup (j_compress_ptr cinfo, boolean transcode_only)
#endif
/* Size in DCT blocks */
compptr->width_in_blocks = (JDIMENSION)
jdiv_round_up((long) cinfo->_jpeg_width * (long) compptr->h_samp_factor,
(long) (cinfo->max_h_samp_factor * DCTSIZE));
jdiv_round_up((long)cinfo->_jpeg_width * (long)compptr->h_samp_factor,
(long)(cinfo->max_h_samp_factor * DCTSIZE));
compptr->height_in_blocks = (JDIMENSION)
jdiv_round_up((long) cinfo->_jpeg_height * (long) compptr->v_samp_factor,
(long) (cinfo->max_v_samp_factor * DCTSIZE));
jdiv_round_up((long)cinfo->_jpeg_height * (long)compptr->v_samp_factor,
(long)(cinfo->max_v_samp_factor * DCTSIZE));
/* Size in samples */
compptr->downsampled_width = (JDIMENSION)
jdiv_round_up((long) cinfo->_jpeg_width * (long) compptr->h_samp_factor,
(long) cinfo->max_h_samp_factor);
jdiv_round_up((long)cinfo->_jpeg_width * (long)compptr->h_samp_factor,
(long)cinfo->max_h_samp_factor);
compptr->downsampled_height = (JDIMENSION)
jdiv_round_up((long) cinfo->_jpeg_height * (long) compptr->v_samp_factor,
(long) cinfo->max_v_samp_factor);
jdiv_round_up((long)cinfo->_jpeg_height * (long)compptr->v_samp_factor,
(long)cinfo->max_v_samp_factor);
/* Mark component needed (this flag isn't actually used for compression) */
compptr->component_needed = TRUE;
}
@@ -139,15 +168,15 @@ initial_setup (j_compress_ptr cinfo, boolean transcode_only)
* main controller will call coefficient controller).
*/
cinfo->total_iMCU_rows = (JDIMENSION)
jdiv_round_up((long) cinfo->_jpeg_height,
(long) (cinfo->max_v_samp_factor*DCTSIZE));
jdiv_round_up((long)cinfo->_jpeg_height,
(long)(cinfo->max_v_samp_factor * DCTSIZE));
}
#ifdef C_MULTISCAN_FILES_SUPPORTED
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
* 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 */
#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)
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.
*/
scanptr = cinfo->scan_info;
if (scanptr->Ss != 0 || scanptr->Se != DCTSIZE2-1) {
if (scanptr->Ss != 0 || scanptr->Se != DCTSIZE2 - 1) {
#ifdef C_PROGRESSIVE_SUPPORTED
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 (coefi = 0; coefi < DCTSIZE2; coefi++)
*last_bitpos_ptr++ = -1;
@@ -203,7 +224,7 @@ validate_script (j_compress_ptr cinfo)
if (thisi < 0 || thisi >= cinfo->num_components)
ERREXIT1(cinfo, JERR_BAD_SCAN_SCRIPT, scanno);
/* 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);
}
/* Validate progression parameters */
@@ -221,9 +242,9 @@ validate_script (j_compress_ptr cinfo)
* which might cause problems for some decoders.
*/
#if BITS_IN_JSAMPLE == 8
#define MAX_AH_AL 10
#define MAX_AH_AL 10
#else
#define MAX_AH_AL 13
#define MAX_AH_AL 13
#endif
if (Ss < 0 || Ss >= DCTSIZE2 || Se < Ss || Se >= DCTSIZE2 ||
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);
}
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 */
ERREXIT1(cinfo, JERR_BAD_PROG_SCRIPT, scanno);
for (coefi = Ss; coefi <= Se; coefi++) {
@@ -246,7 +267,7 @@ validate_script (j_compress_ptr cinfo)
ERREXIT1(cinfo, JERR_BAD_PROG_SCRIPT, scanno);
} else {
/* 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);
}
last_bitpos_ptr[coefi] = Al;
@@ -255,7 +276,7 @@ validate_script (j_compress_ptr cinfo)
#endif
} else {
/* 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);
/* Make sure components are not sent twice */
for (ci = 0; ci < ncomps; ci++) {
@@ -282,7 +303,7 @@ validate_script (j_compress_ptr cinfo)
#endif
} else {
for (ci = 0; ci < cinfo->num_components; ci++) {
if (! component_sent[ci])
if (!component_sent[ci])
ERREXIT(cinfo, JERR_MISSING_DATA);
}
}
@@ -292,33 +313,15 @@ validate_script (j_compress_ptr cinfo)
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 */
{
int ci;
#ifdef C_MULTISCAN_FILES_SUPPORTED
my_master_ptr master = (my_master_ptr) cinfo->master;
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) {
if (cinfo->scan_info != NULL) {
/* 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;
cinfo->comps_in_scan = scanptr->comps_in_scan;
@@ -330,23 +333,7 @@ select_scan_parameters (j_compress_ptr cinfo)
cinfo->Se = scanptr->Se;
cinfo->Ah = scanptr->Ah;
cinfo->Al = scanptr->Al;
if (cinfo->master->optimize_scans) {
/* 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
} else
#endif
{
/* 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->Ss = 0;
cinfo->Se = DCTSIZE2-1;
cinfo->Se = DCTSIZE2 - 1;
cinfo->Ah = 0;
cinfo->Al = 0;
}
@@ -366,7 +353,7 @@ select_scan_parameters (j_compress_ptr cinfo)
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 */
/* 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
* 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;
compptr->last_row_height = tmp;
@@ -408,11 +395,11 @@ per_scan_setup (j_compress_ptr cinfo)
/* Overall image size in MCUs */
cinfo->MCUs_per_row = (JDIMENSION)
jdiv_round_up((long) cinfo->_jpeg_width,
(long) (cinfo->max_h_samp_factor*DCTSIZE));
jdiv_round_up((long)cinfo->_jpeg_width,
(long)(cinfo->max_h_samp_factor * DCTSIZE));
cinfo->MCU_rows_in_scan = (JDIMENSION)
jdiv_round_up((long) cinfo->_jpeg_height,
(long) (cinfo->max_v_samp_factor*DCTSIZE));
jdiv_round_up((long)cinfo->_jpeg_height,
(long)(cinfo->max_v_samp_factor * DCTSIZE));
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_sample_width = compptr->MCU_width * DCTSIZE;
/* 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;
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;
compptr->last_row_height = tmp;
/* 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. */
/* Note that count must fit in 16 bits, so we provide limiting. */
if (cinfo->restart_in_rows > 0) {
long nominal = (long) cinfo->restart_in_rows * (long) cinfo->MCUs_per_row;
cinfo->restart_interval = (unsigned int) MIN(nominal, 65535L);
long nominal = (long)cinfo->restart_in_rows * (long)cinfo->MCUs_per_row;
cinfo->restart_interval = (unsigned int)MIN(nominal, 65535L);
}
}
@@ -459,11 +446,9 @@ per_scan_setup (j_compress_ptr cinfo)
*/
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;
cinfo->master->trellis_passes =
master->pass_number < master->pass_number_scan_opt_base;
my_master_ptr master = (my_master_ptr)cinfo->master;
switch (master->pass_type) {
case main_pass:
@@ -472,18 +457,18 @@ prepare_for_pass (j_compress_ptr cinfo)
*/
select_scan_parameters(cinfo);
per_scan_setup(cinfo);
if (! cinfo->raw_data_in) {
if (!cinfo->raw_data_in) {
(*cinfo->cconvert->start_pass) (cinfo);
(*cinfo->downsample->start_pass) (cinfo);
(*cinfo->prep->start_pass) (cinfo, JBUF_PASS_THRU);
}
(*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,
(master->total_passes > 1 ?
JBUF_SAVE_AND_PASS : 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 */
master->pub.call_pass_startup = FALSE;
} else {
@@ -512,17 +497,10 @@ prepare_for_pass (j_compress_ptr cinfo)
case output_pass:
/* Do a data-output pass. */
/* 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);
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->coef->start_pass) (cinfo, JBUF_CRANK_DEST);
/* We emit frame/scan headers now */
@@ -531,29 +509,11 @@ prepare_for_pass (j_compress_ptr cinfo)
(*cinfo->marker->write_scan_header) (cinfo);
master->pub.call_pass_startup = FALSE;
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:
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 */
if (cinfo->progress != NULL) {
@@ -574,7 +534,7 @@ prepare_for_pass (j_compress_ptr cinfo)
*/
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 */
@@ -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)
{
memcpy(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);
}
memcpy(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.
*/
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,
* 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)
* or output of scan 1 (if no optimization).
*/
if (cinfo->master->trellis_quant)
master->pass_type = trellis_pass;
else {
master->pass_type = output_pass;
if (! cinfo->optimize_coding)
if (!cinfo->optimize_coding)
master->scan_number++;
}
break;
case huff_opt_pass:
/* 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;
case output_pass:
/* next pass is either optimization or output of next scan */
if (cinfo->optimize_coding)
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++;
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++;
@@ -888,15 +588,18 @@ finish_pass_master (j_compress_ptr cinfo)
*/
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.pass_startup = pass_startup;
master->pub.finish_pass = finish_pass_master;
master->pub.is_last_pass = FALSE;
master->pub.call_pass_startup = FALSE;
/* Validate parameters, determine derived values */
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->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

@@ -65,7 +65,6 @@ typedef unsigned char boolean;
/* 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 GIF_SUPPORTED /* GIF image file format */
#define PPM_SUPPORTED /* PBMPLUS PPM/PGM image file format */

554
jcparam.c
View File

@@ -6,9 +6,8 @@
* Modified 2003-2008 by Guido Vollbeding.
* libjpeg-turbo Modifications:
* Copyright (C) 2009-2011, 2018, D. R. Commander.
* mozjpeg Modifications:
* Copyright (C) 2014, Mozilla Corporation.
* 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 optional default-setting code for the JPEG compressor.
* Applications do not have to use this file, but those that don't use it
@@ -26,7 +25,7 @@
*/
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,
boolean force_baseline)
/* 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)
ERREXIT1(cinfo, JERR_DQT_INDEX, which_tbl);
qtblptr = & cinfo->quant_tbl_ptrs[which_tbl];
qtblptr = &cinfo->quant_tbl_ptrs[which_tbl];
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++) {
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 */
if (temp <= 0L) temp = 1L;
if (temp > 32767L) temp = 32767L; /* max quantizer needed for 12 bits */
if (force_baseline && temp > 255L)
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. */
@@ -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
* when divided by 2, "very good" quality.
*/
static const unsigned int std_luminance_quant_tbl[9][DCTSIZE2] = {
{
/* JPEG Annex K
*/
static const unsigned int std_luminance_quant_tbl[DCTSIZE2] = {
16, 11, 10, 16, 24, 40, 51, 61,
12, 12, 14, 19, 26, 58, 60, 55,
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,
49, 64, 78, 87, 103, 121, 120, 101,
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[9][DCTSIZE2] = {
{
/* JPEG Annex K
*/
static const unsigned int std_chrominance_quant_tbl[DCTSIZE2] = {
17, 18, 24, 47, 99, 99, 99, 99,
18, 21, 26, 66, 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
},
{
/* 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
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
* and straight percentage-scaling quality scales.
* This entry point allows different scalings for luminance and chrominance.
*/
{
/* 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);
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);
}
#endif
GLOBAL(void)
jpeg_set_linear_quality (j_compress_ptr cinfo, int scale_factor,
boolean force_baseline)
jpeg_set_linear_quality(j_compress_ptr cinfo, int scale_factor,
boolean force_baseline)
/* Set or change the 'quality' (quantization) setting, using default tables
* 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
@@ -316,29 +119,23 @@ jpeg_set_linear_quality (j_compress_ptr cinfo, int scale_factor,
*/
{
/* 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);
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);
}
GLOBAL(int)
jpeg_quality_scaling (int quality)
{
return jpeg_float_quality_scaling(quality);
}
GLOBAL(float)
jpeg_float_quality_scaling(float quality)
jpeg_quality_scaling(int quality)
/* Convert a user-specified quality rating to a percentage scaling factor
* for an underlying quantization table, using our recommended scaling curve.
* 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. */
if (quality <= 0.f) quality = 1.f;
if (quality > 100.f) quality = 100.f;
if (quality <= 0) quality = 1;
if (quality > 100) quality = 100;
/* 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;
@@ -346,17 +143,17 @@ jpeg_float_quality_scaling(float quality)
* to make all the table entries 1 (hence, minimum quantization loss).
* Qualities 1..50 are converted to scaling percentage 5000/Q.
*/
if (quality < 50.f)
quality = 5000.f / quality;
if (quality < 50)
quality = 5000 / quality;
else
quality = 200.f - quality*2.f;
quality = 200 - quality * 2;
return quality;
}
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.
* This is the standard quality-adjusting entry point for typical user
* 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)
jpeg_set_defaults (j_compress_ptr cinfo)
jpeg_set_defaults(j_compress_ptr cinfo)
{
int i;
@@ -396,7 +193,7 @@ jpeg_set_defaults (j_compress_ptr cinfo)
*/
if (cinfo->comp_info == NULL)
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));
/* 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 */
jpeg_set_quality(cinfo, 75, TRUE);
/* Set up two Huffman tables */
std_huff_tables((j_common_ptr) cinfo);
std_huff_tables((j_common_ptr)cinfo);
/* Initialize default arithmetic coding conditioning */
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 */
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 */
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.
* If the precision is higher, force optimization on so that usable
* 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;
#endif
cinfo->master->overshoot_deringing =
cinfo->master->compress_profile == JCP_MAX_COMPRESSION;
/* No input smoothing */
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 */
jpeg_default_colorspace(cinfo);
cinfo->master->dc_scan_opt_mode = 0;
#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)
jpeg_default_colorspace (j_compress_ptr cinfo)
jpeg_default_colorspace(j_compress_ptr cinfo)
{
switch (cinfo->in_color_space) {
case JCS_GRAYSCALE:
@@ -562,12 +321,12 @@ jpeg_default_colorspace (j_compress_ptr cinfo)
*/
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;
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->component_id = (id), \
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->num_components = 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;
case JCS_RGB:
cinfo->write_Adobe_marker = TRUE; /* write Adobe marker to flag RGB */
cinfo->num_components = 3;
SET_COMP(0, 0x52 /* 'R' */, 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(0, 0x52 /* 'R' */, 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);
break;
case JCS_YCbCr:
cinfo->write_JFIF_header = TRUE; /* Write a JFIF marker */
cinfo->num_components = 3;
/* JFIF specifies component IDs 1,2,3 */
/* We default to 2x2 subsamples of chrominance */
SET_COMP(0, 1, 2,2, 0, 0,0);
SET_COMP(1, 2, 1,1, 1, 1,1);
SET_COMP(2, 3, 1,1, 1, 1,1);
SET_COMP(0, 1, 2, 2, 0, 0, 0);
SET_COMP(1, 2, 1, 1, 1, 1, 1);
SET_COMP(2, 3, 1, 1, 1, 1, 1);
break;
case JCS_CMYK:
cinfo->write_Adobe_marker = TRUE; /* write Adobe marker to flag CMYK */
cinfo->num_components = 4;
SET_COMP(0, 0x43 /* 'C' */, 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(3, 0x4B /* 'K' */, 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(2, 0x59 /* 'Y' */, 1, 1, 0, 0, 0);
SET_COMP(3, 0x4B /* 'K' */, 1, 1, 0, 0, 0);
break;
case JCS_YCCK:
cinfo->write_Adobe_marker = TRUE; /* write Adobe marker to flag YCCK */
cinfo->num_components = 4;
SET_COMP(0, 1, 2,2, 0, 0,0);
SET_COMP(1, 2, 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(0, 1, 2, 2, 0, 0, 0);
SET_COMP(1, 2, 1, 1, 1, 1, 1);
SET_COMP(2, 3, 1, 1, 1, 1, 1);
SET_COMP(3, 4, 2, 2, 0, 0, 0);
break;
case JCS_UNKNOWN:
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,
MAX_COMPONENTS);
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;
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 *)
fill_a_scan_pair (jpeg_scan_info * scanptr, int ci,
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)
fill_scans(jpeg_scan_info *scanptr, int ncomps, int Ss, int Se, int Ah, int Al)
/* Support routine: generate one scan for each component */
{
int ci;
@@ -695,7 +437,7 @@ fill_scans (jpeg_scan_info *scanptr, int ncomps,
}
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 */
{
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.
* cinfo->num_components and cinfo->jpeg_color_space must be correct.
*/
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;
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. */
if (cinfo->global_state != CSTATE_START)
ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state);
/* Figure space needed for script. Calculation must match code below! */
ncomps = cinfo->num_components;
if (ncomps == 3 && cinfo->jpeg_color_space == JCS_YCbCr) {
/* Custom script for YCbCr color images. */
if (cinfo->master->compress_profile == JCP_MAX_COMPRESSION) {
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 */
}
nscans = 10;
} else {
/* All-purpose script for other color spaces. */
if (cinfo->master->compress_profile == JCP_MAX_COMPRESSION) {
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 */
else
nscans = 2 + 4 * ncomps; /* 2 DC scans; 4 AC scans per component */
}
}
/* Allocate space for script.
* 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) {
cinfo->script_space_size = MAX(nscans, 10);
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));
}
scanptr = cinfo->script_space;
@@ -913,35 +506,6 @@ jpeg_simple_progression (j_compress_ptr cinfo)
if (ncomps == 3 && cinfo->jpeg_color_space == JCS_YCbCr) {
/* 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 */
scanptr = fill_dc_scans(scanptr, ncomps, 0, 1);
/* 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);
/* Luma bottom bit comes last since it's usually largest scan */
scanptr = fill_a_scan(scanptr, 0, 1, 63, 1, 0);
}
} else {
/* 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 */
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_scans(scanptr, ncomps, 1, 5, 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);
}
}
}
#endif /* C_PROGRESSIVE_SUPPORTED */

110
jcphuff.c
View File

@@ -8,7 +8,6 @@
* Copyright (C) 2016, 2018, Matthieu Darbois.
* Copyright (C) 2020, Arm Limited.
* Copyright (C) 2021, Alex Richardson.
* Copyright (C) 2014, Mozilla Corporation.
* For conditions of distribution and use, see the accompanying README.ijg
* file.
*
@@ -142,34 +141,34 @@ typedef phuff_entropy_encoder *phuff_entropy_ptr;
#ifdef RIGHT_SHIFT_IS_UNSIGNED
#define ISHIFT_TEMPS int ishift_temp;
#define IRIGHT_SHIFT(x,shft) \
#define IRIGHT_SHIFT(x, shft) \
((ishift_temp = (x)) < 0 ? \
(ishift_temp >> (shft)) | ((~0) << (16-(shft))) : \
(ishift_temp >> (shft)) | ((~0) << (16 - (shft))) : \
(ishift_temp >> (shft)))
#else
#define ISHIFT_TEMPS
#define IRIGHT_SHIFT(x,shft) ((x) >> (shft))
#define IRIGHT_SHIFT(x, shft) ((x) >> (shft))
#endif
#define PAD(v, p) ((v + (p) - 1) & (~((p) - 1)))
/* 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);
METHODDEF(void) encode_mcu_AC_first_prepare
(const JCOEF *block, const int *jpeg_natural_order_start, int Sl, int Al,
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,
METHODDEF(boolean) encode_mcu_DC_refine(j_compress_ptr cinfo,
JBLOCKROW *MCU_data);
METHODDEF(int) encode_mcu_AC_refine_prepare
(const JCOEF *block, const int *jpeg_natural_order_start, int Sl, int Al,
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);
METHODDEF(void) finish_pass_phuff (j_compress_ptr cinfo);
METHODDEF(void) finish_pass_gather_phuff (j_compress_ptr cinfo);
METHODDEF(void) finish_pass_phuff(j_compress_ptr cinfo);
METHODDEF(void) finish_pass_gather_phuff(j_compress_ptr cinfo);
/* Count bit loop zeroes */
@@ -205,9 +204,9 @@ count_zeroes(size_t *x)
*/
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;
int ci, tbl;
jpeg_component_info *compptr;
@@ -241,7 +240,7 @@ start_pass_phuff (j_compress_ptr cinfo, boolean gather_statistics)
/* AC refinement needs a correction bit buffer */
if (entropy->bit_buffer == NULL)
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));
}
}
@@ -274,23 +273,14 @@ start_pass_phuff (j_compress_ptr cinfo, boolean gather_statistics)
/* Note that jpeg_gen_optimal_table expects 257 entries in each table! */
if (entropy->count_ptrs[tbl] == NULL)
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));
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 {
/* Compute derived values for Huffman table */
/* 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,
& entropy->derived_tbls[tbl]);
&entropy->derived_tbls[tbl]);
}
}
@@ -322,12 +312,12 @@ start_pass_phuff (j_compress_ptr cinfo, boolean gather_statistics)
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. */
{
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);
/* After a successful buffer dump, must reset buffer pointers */
entropy->next_output_byte = dest->next_output_byte;
@@ -344,11 +334,11 @@ dump_buffer (phuff_entropy_ptr entropy)
*/
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 */
{
/* 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;
/* if size is 0, caller used an invalid Huffman table entry */
@@ -358,7 +348,7 @@ emit_bits (phuff_entropy_ptr entropy, unsigned int code, int size)
if (entropy->gather_statistics)
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 */
@@ -367,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 */
while (put_bits >= 8) {
int c = (int) ((put_buffer >> 16) & 0xFF);
int c = (int)((put_buffer >> 16) & 0xFF);
emit_byte(entropy, c);
if (c == 0xFF) { /* need to stuff a zero byte? */
@@ -383,7 +373,7 @@ emit_bits (phuff_entropy_ptr entropy, unsigned int code, int size)
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 */
entropy->put_buffer = 0; /* and reset bit-buffer to empty */
@@ -396,7 +386,7 @@ flush_bits (phuff_entropy_ptr entropy)
*/
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)
entropy->count_ptrs[tbl_no][symbol]++;
@@ -412,14 +402,14 @@ emit_symbol (phuff_entropy_ptr entropy, int tbl_no, int symbol)
*/
LOCAL(void)
emit_buffered_bits (phuff_entropy_ptr entropy, char *bufstart,
emit_buffered_bits(phuff_entropy_ptr entropy, char *bufstart,
unsigned int nbits)
{
if (entropy->gather_statistics)
return; /* no real work */
while (nbits > 0) {
emit_bits(entropy, (unsigned int) (*bufstart), 1);
emit_bits(entropy, (unsigned int)(*bufstart), 1);
bufstart++;
nbits--;
}
@@ -431,7 +421,7 @@ emit_buffered_bits (phuff_entropy_ptr entropy, char *bufstart,
*/
LOCAL(void)
emit_eobrun (phuff_entropy_ptr entropy)
emit_eobrun(phuff_entropy_ptr entropy)
{
register int temp, nbits;
@@ -460,13 +450,13 @@ emit_eobrun (phuff_entropy_ptr entropy)
*/
LOCAL(void)
emit_restart (phuff_entropy_ptr entropy, int restart_num)
emit_restart(phuff_entropy_ptr entropy, int restart_num)
{
int ci;
emit_eobrun(entropy);
if (! entropy->gather_statistics) {
if (!entropy->gather_statistics) {
flush_bits(entropy);
emit_byte(entropy, 0xFF);
emit_byte(entropy, JPEG_RST0 + restart_num);
@@ -490,9 +480,9 @@ emit_restart (phuff_entropy_ptr entropy, int restart_num)
*/
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 nbits;
int blkn, ci;
@@ -518,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.
* 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. */
temp = temp2 - entropy->last_dc_val[ci];
@@ -542,7 +532,7 @@ encode_mcu_DC_first (j_compress_ptr cinfo, JBLOCKROW *MCU_data)
/* Check for out-of-range coefficient values.
* 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);
/* Count/emit the Huffman-coded symbol for the number of bits */
@@ -551,7 +541,7 @@ encode_mcu_DC_first (j_compress_ptr cinfo, JBLOCKROW *MCU_data)
/* Emit that number of bits of the value, if positive, */
/* or the complement of its magnitude, if negative. */
if (nbits) /* emit_bits rejects calls with size 0 */
emit_bits(entropy, (unsigned int) temp2, nbits);
emit_bits(entropy, (unsigned int)temp2, nbits);
}
cinfo->dest->next_output_byte = entropy->next_output_byte;
@@ -669,9 +659,9 @@ label \
}
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 nbits, r;
int Sl = cinfo->Se - cinfo->Ss + 1;
@@ -761,9 +751,9 @@ encode_mcu_AC_first (j_compress_ptr cinfo, JBLOCKROW *MCU_data)
*/
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;
int blkn;
int Al = cinfo->Al;
@@ -783,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. */
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;
@@ -933,9 +923,9 @@ label \
}
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, idx;
char *BR_buffer;
unsigned int BR;
@@ -1034,9 +1024,9 @@ encode_mcu_AC_refine (j_compress_ptr cinfo, JBLOCKROW *MCU_data)
*/
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->free_in_buffer = cinfo->dest->free_in_buffer;
@@ -1055,9 +1045,9 @@ finish_pass_phuff (j_compress_ptr cinfo)
*/
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;
int ci, tbl;
jpeg_component_info *compptr;
@@ -1083,13 +1073,13 @@ finish_pass_gather_phuff (j_compress_ptr cinfo)
} else {
tbl = compptr->ac_tbl_no;
}
if (! did[tbl]) {
if (!did[tbl]) {
if (is_DC_band)
htblptr = & cinfo->dc_huff_tbl_ptrs[tbl];
htblptr = &cinfo->dc_huff_tbl_ptrs[tbl];
else
htblptr = & cinfo->ac_huff_tbl_ptrs[tbl];
htblptr = &cinfo->ac_huff_tbl_ptrs[tbl];
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]);
did[tbl] = TRUE;
}
@@ -1102,15 +1092,15 @@ finish_pass_gather_phuff (j_compress_ptr cinfo)
*/
GLOBAL(void)
jinit_phuff_encoder (j_compress_ptr cinfo)
jinit_phuff_encoder(j_compress_ptr cinfo)
{
phuff_entropy_ptr entropy;
int i;
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));
cinfo->entropy = (struct jpeg_entropy_encoder *) entropy;
cinfo->entropy = (struct jpeg_entropy_encoder *)entropy;
entropy->pub.start_pass = start_pass_phuff;
/* Mark tables unallocated */

View File

@@ -6,9 +6,8 @@
* Modified 2000-2009 by Guido Vollbeding.
* libjpeg-turbo Modifications:
* Copyright (C) 2020, 2022, D. R. Commander.
* mozjpeg Modifications:
* Copyright (C) 2014, Mozilla Corporation.
* 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 library routines for transcoding compression,
* that is, writing raw DCT coefficient arrays to an output JPEG file.
@@ -41,18 +40,14 @@ LOCAL(void) transencode_coef_controller(j_compress_ptr cinfo,
*/
GLOBAL(void)
jpeg_write_coefficients (j_compress_ptr cinfo, jvirt_barray_ptr *coef_arrays)
jpeg_write_coefficients(j_compress_ptr cinfo, jvirt_barray_ptr *coef_arrays)
{
/* setting up scan optimisation pattern failed, disable scan optimisation */
if (cinfo->master->num_scans_luma == 0)
cinfo->master->optimize_scans = FALSE;
if (cinfo->global_state != CSTATE_START)
ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state);
/* Mark all tables to be written */
jpeg_suppress_tables(cinfo, FALSE);
/* (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);
/* Perform master selection of active modules */
transencode_master_selection(cinfo, coef_arrays);
@@ -70,7 +65,7 @@ jpeg_write_coefficients (j_compress_ptr cinfo, jvirt_barray_ptr *coef_arrays)
*/
GLOBAL(void)
jpeg_copy_critical_parameters (const j_decompress_ptr srcinfo, j_compress_ptr dstinfo)
jpeg_copy_critical_parameters(j_decompress_ptr srcinfo, j_compress_ptr dstinfo)
{
JQUANT_TBL **qtblptr;
jpeg_component_info *incomp, *outcomp;
@@ -93,8 +88,6 @@ jpeg_copy_critical_parameters (const j_decompress_ptr srcinfo, j_compress_ptr ds
#endif
/* Initialize all parameters to default values */
jpeg_set_defaults(dstinfo);
dstinfo->master->trellis_quant = FALSE;
/* jpeg_set_defaults may choose wrong colorspace, eg YCbCr if input is RGB.
* Fix it to get the right header markers for the image colorspace.
*/
@@ -104,11 +97,11 @@ jpeg_copy_critical_parameters (const j_decompress_ptr srcinfo, j_compress_ptr ds
/* Copy the source's quantization tables. */
for (tblno = 0; tblno < NUM_QUANT_TBLS; tblno++) {
if (srcinfo->quant_tbl_ptrs[tblno] != NULL) {
qtblptr = & dstinfo->quant_tbl_ptrs[tblno];
qtblptr = &dstinfo->quant_tbl_ptrs[tblno];
if (*qtblptr == NULL)
*qtblptr = jpeg_alloc_quant_table((j_common_ptr) dstinfo);
*qtblptr = jpeg_alloc_quant_table((j_common_ptr)dstinfo);
memcpy((*qtblptr)->quantval, srcinfo->quant_tbl_ptrs[tblno]->quantval,
sizeof((*qtblptr)->quantval));
sizeof((*qtblptr)->quantval));
(*qtblptr)->sent_table = FALSE;
}
}
@@ -171,7 +164,7 @@ jpeg_copy_critical_parameters (const j_decompress_ptr srcinfo, j_compress_ptr ds
*/
LOCAL(void)
transencode_master_selection (j_compress_ptr cinfo,
transencode_master_selection(j_compress_ptr cinfo,
jvirt_barray_ptr *coef_arrays)
{
/* Although we don't actually use input_components for transcoding,
@@ -205,7 +198,7 @@ transencode_master_selection (j_compress_ptr cinfo,
jinit_marker_writer(cinfo);
/* 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, JFIF) immediately.
* Frame and scan headers are postponed till later.
@@ -244,10 +237,10 @@ typedef my_coef_controller *my_coef_ptr;
LOCAL(void)
start_iMCU_row (j_compress_ptr cinfo)
start_iMCU_row(j_compress_ptr cinfo)
/* Reset within-iMCU-row counters for a new row */
{
my_coef_ptr coef = (my_coef_ptr) cinfo->coef;
my_coef_ptr coef = (my_coef_ptr)cinfo->coef;
/* In an interleaved scan, an MCU row is the same as an iMCU row.
* In a noninterleaved scan, an iMCU row has v_samp_factor MCU rows.
@@ -256,7 +249,7 @@ start_iMCU_row (j_compress_ptr cinfo)
if (cinfo->comps_in_scan > 1) {
coef->MCU_rows_per_iMCU_row = 1;
} else {
if (coef->iMCU_row_num < (cinfo->total_iMCU_rows-1))
if (coef->iMCU_row_num < (cinfo->total_iMCU_rows - 1))
coef->MCU_rows_per_iMCU_row = cinfo->cur_comp_info[0]->v_samp_factor;
else
coef->MCU_rows_per_iMCU_row = cinfo->cur_comp_info[0]->last_row_height;
@@ -272,9 +265,9 @@ start_iMCU_row (j_compress_ptr cinfo)
*/
METHODDEF(void)
start_pass_coef (j_compress_ptr cinfo, J_BUF_MODE pass_mode)
start_pass_coef(j_compress_ptr cinfo, J_BUF_MODE pass_mode)
{
my_coef_ptr coef = (my_coef_ptr) cinfo->coef;
my_coef_ptr coef = (my_coef_ptr)cinfo->coef;
if (pass_mode != JBUF_CRANK_DEST)
ERREXIT(cinfo, JERR_BAD_BUFFER_MODE);
@@ -295,9 +288,9 @@ start_pass_coef (j_compress_ptr cinfo, J_BUF_MODE pass_mode)
*/
METHODDEF(boolean)
compress_output (j_compress_ptr cinfo, JSAMPIMAGE input_buf)
compress_output(j_compress_ptr cinfo, JSAMPIMAGE input_buf)
{
my_coef_ptr coef = (my_coef_ptr) cinfo->coef;
my_coef_ptr coef = (my_coef_ptr)cinfo->coef;
JDIMENSION MCU_col_num; /* index of current MCU within row */
JDIMENSION last_MCU_col = cinfo->MCUs_per_row - 1;
JDIMENSION last_iMCU_row = cinfo->total_iMCU_rows - 1;
@@ -312,9 +305,9 @@ compress_output (j_compress_ptr cinfo, JSAMPIMAGE input_buf)
for (ci = 0; ci < cinfo->comps_in_scan; ci++) {
compptr = cinfo->cur_comp_info[ci];
buffer[ci] = (*cinfo->mem->access_virt_barray)
((j_common_ptr) cinfo, coef->whole_image[compptr->component_index],
((j_common_ptr)cinfo, coef->whole_image[compptr->component_index],
coef->iMCU_row_num * compptr->v_samp_factor,
(JDIMENSION) compptr->v_samp_factor, FALSE);
(JDIMENSION)compptr->v_samp_factor, FALSE);
}
/* Loop to process one whole iMCU row */
@@ -331,9 +324,9 @@ compress_output (j_compress_ptr cinfo, JSAMPIMAGE input_buf)
compptr->last_col_width;
for (yindex = 0; yindex < compptr->MCU_height; yindex++) {
if (coef->iMCU_row_num < last_iMCU_row ||
yindex+yoffset < compptr->last_row_height) {
yindex + yoffset < compptr->last_row_height) {
/* Fill in pointers to real blocks in this row */
buffer_ptr = buffer[ci][yindex+yoffset] + start_col;
buffer_ptr = buffer[ci][yindex + yoffset] + start_col;
for (xindex = 0; xindex < blockcnt; xindex++)
MCU_buffer[blkn++] = buffer_ptr++;
} else {
@@ -348,13 +341,13 @@ compress_output (j_compress_ptr cinfo, JSAMPIMAGE input_buf)
*/
for (; xindex < compptr->MCU_width; xindex++) {
MCU_buffer[blkn] = coef->dummy_buffer[blkn];
MCU_buffer[blkn][0][0] = MCU_buffer[blkn-1][0][0];
MCU_buffer[blkn][0][0] = MCU_buffer[blkn - 1][0][0];
blkn++;
}
}
}
/* Try to write the MCU. */
if (! (*cinfo->entropy->encode_mcu) (cinfo, MCU_buffer)) {
if (!(*cinfo->entropy->encode_mcu) (cinfo, MCU_buffer)) {
/* Suspension forced; update state counters and exit */
coef->MCU_vert_offset = yoffset;
coef->mcu_ctr = MCU_col_num;
@@ -380,7 +373,7 @@ compress_output (j_compress_ptr cinfo, JSAMPIMAGE input_buf)
*/
LOCAL(void)
transencode_coef_controller (j_compress_ptr cinfo,
transencode_coef_controller(j_compress_ptr cinfo,
jvirt_barray_ptr *coef_arrays)
{
my_coef_ptr coef;
@@ -388,9 +381,9 @@ transencode_coef_controller (j_compress_ptr cinfo,
int i;
coef = (my_coef_ptr)
(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
(*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_IMAGE,
sizeof(my_coef_controller));
cinfo->coef = (struct jpeg_c_coef_controller *) coef;
cinfo->coef = (struct jpeg_c_coef_controller *)coef;
coef->pub.start_pass = start_pass_coef;
coef->pub.compress_data = compress_output;
@@ -399,9 +392,9 @@ transencode_coef_controller (j_compress_ptr cinfo,
/* Allocate and pre-zero space for dummy DCT blocks. */
buffer = (JBLOCKROW)
(*cinfo->mem->alloc_large) ((j_common_ptr) cinfo, JPOOL_IMAGE,
(*cinfo->mem->alloc_large) ((j_common_ptr)cinfo, JPOOL_IMAGE,
C_MAX_BLOCKS_IN_MCU * sizeof(JBLOCK));
jzero_far((void *) buffer, C_MAX_BLOCKS_IN_MCU * sizeof(JBLOCK));
jzero_far((void *)buffer, C_MAX_BLOCKS_IN_MCU * sizeof(JBLOCK));
for (i = 0; i < C_MAX_BLOCKS_IN_MCU; i++) {
coef->dummy_buffer[i] = buffer + i;
}

View File

@@ -32,7 +32,7 @@
*/
GLOBAL(void)
jpeg_CreateDecompress (j_decompress_ptr cinfo, int version, size_t structsize)
jpeg_CreateDecompress(j_decompress_ptr cinfo, int version, size_t structsize)
{
int i;
@@ -42,7 +42,7 @@ jpeg_CreateDecompress (j_decompress_ptr cinfo, int version, size_t structsize)
ERREXIT2(cinfo, JERR_BAD_LIB_VERSION, JPEG_LIB_VERSION, version);
if (structsize != sizeof(struct jpeg_decompress_struct))
ERREXIT2(cinfo, JERR_BAD_STRUCT_SIZE,
(int) sizeof(struct jpeg_decompress_struct), (int) structsize);
(int)sizeof(struct jpeg_decompress_struct), (int)structsize);
/* For debugging purposes, we zero the whole master structure.
* But the application has already set the err pointer, and may have set
@@ -51,8 +51,8 @@ jpeg_CreateDecompress (j_decompress_ptr cinfo, int version, size_t structsize)
* complain here.
*/
{
struct jpeg_error_mgr * err = cinfo->err;
void * client_data = cinfo->client_data; /* ignore Purify complaint here */
struct jpeg_error_mgr *err = cinfo->err;
void *client_data = cinfo->client_data; /* ignore Purify complaint here */
memset(cinfo, 0, sizeof(struct jpeg_decompress_struct));
cinfo->err = err;
cinfo->client_data = client_data;
@@ -60,7 +60,7 @@ jpeg_CreateDecompress (j_decompress_ptr cinfo, int version, size_t structsize)
cinfo->is_decompressor = TRUE;
/* Initialize a memory manager instance for this object */
jinit_memory_mgr((j_common_ptr) cinfo);
jinit_memory_mgr((j_common_ptr)cinfo);
/* Zero out pointers to permanent structures. */
cinfo->progress = NULL;
@@ -90,7 +90,7 @@ jpeg_CreateDecompress (j_decompress_ptr cinfo, int version, size_t structsize)
* here.
*/
cinfo->master = (struct jpeg_decomp_master *)
(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
(*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_PERMANENT,
sizeof(my_decomp_master));
memset(cinfo->master, 0, sizeof(my_decomp_master));
}
@@ -101,9 +101,9 @@ jpeg_CreateDecompress (j_decompress_ptr cinfo, int version, size_t structsize)
*/
GLOBAL(void)
jpeg_destroy_decompress (j_decompress_ptr cinfo)
jpeg_destroy_decompress(j_decompress_ptr cinfo)
{
jpeg_destroy((j_common_ptr) cinfo); /* use common routine */
jpeg_destroy((j_common_ptr)cinfo); /* use common routine */
}
@@ -113,9 +113,9 @@ jpeg_destroy_decompress (j_decompress_ptr cinfo)
*/
GLOBAL(void)
jpeg_abort_decompress (j_decompress_ptr cinfo)
jpeg_abort_decompress(j_decompress_ptr cinfo)
{
jpeg_abort((j_common_ptr) cinfo); /* use common routine */
jpeg_abort((j_common_ptr)cinfo); /* use common routine */
}
@@ -124,7 +124,7 @@ jpeg_abort_decompress (j_decompress_ptr cinfo)
*/
LOCAL(void)
default_decompress_parms (j_decompress_ptr cinfo)
default_decompress_parms(j_decompress_ptr cinfo)
{
/* Guess the input colorspace, and set output colorspace accordingly. */
/* (Wish JPEG committee had provided a real way to specify this...) */
@@ -251,7 +251,7 @@ default_decompress_parms (j_decompress_ptr cinfo)
*/
GLOBAL(int)
jpeg_read_header (j_decompress_ptr cinfo, boolean require_image)
jpeg_read_header(j_decompress_ptr cinfo, boolean require_image)
{
int retcode;
@@ -272,7 +272,7 @@ jpeg_read_header (j_decompress_ptr cinfo, boolean require_image)
* call jpeg_abort, but we can't change it now for compatibility reasons.
* A side effect is to free any temporary memory (there shouldn't be any).
*/
jpeg_abort((j_common_ptr) cinfo); /* sets state = DSTATE_START */
jpeg_abort((j_common_ptr)cinfo); /* sets state = DSTATE_START */
retcode = JPEG_HEADER_TABLES_ONLY;
break;
case JPEG_SUSPENDED:
@@ -297,7 +297,7 @@ jpeg_read_header (j_decompress_ptr cinfo, boolean require_image)
*/
GLOBAL(int)
jpeg_consume_input (j_decompress_ptr cinfo)
jpeg_consume_input(j_decompress_ptr cinfo)
{
int retcode = JPEG_SUSPENDED;
@@ -344,7 +344,7 @@ jpeg_consume_input (j_decompress_ptr cinfo)
*/
GLOBAL(boolean)
jpeg_input_complete (const j_decompress_ptr cinfo)
jpeg_input_complete(j_decompress_ptr cinfo)
{
/* Check for valid jpeg object */
if (cinfo->global_state < DSTATE_START ||
@@ -359,7 +359,7 @@ jpeg_input_complete (const j_decompress_ptr cinfo)
*/
GLOBAL(boolean)
jpeg_has_multiple_scans (const j_decompress_ptr cinfo)
jpeg_has_multiple_scans(j_decompress_ptr cinfo)
{
/* Only valid after jpeg_read_header completes */
if (cinfo->global_state < DSTATE_READY ||
@@ -379,10 +379,10 @@ jpeg_has_multiple_scans (const j_decompress_ptr cinfo)
*/
GLOBAL(boolean)
jpeg_finish_decompress (j_decompress_ptr cinfo)
jpeg_finish_decompress(j_decompress_ptr cinfo)
{
if ((cinfo->global_state == DSTATE_SCANNING ||
cinfo->global_state == DSTATE_RAW_OK) && ! cinfo->buffered_image) {
cinfo->global_state == DSTATE_RAW_OK) && !cinfo->buffered_image) {
/* Terminate final pass of non-buffered mode */
if (cinfo->output_scanline < cinfo->output_height)
ERREXIT(cinfo, JERR_TOO_LITTLE_DATA);
@@ -396,13 +396,13 @@ jpeg_finish_decompress (j_decompress_ptr cinfo)
ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state);
}
/* Read until EOI */
while (! cinfo->inputctl->eoi_reached) {
while (!cinfo->inputctl->eoi_reached) {
if ((*cinfo->inputctl->consume_input) (cinfo) == JPEG_SUSPENDED)
return FALSE; /* Suspend, come back later */
}
/* Do final cleanup */
(*cinfo->src->term_source) (cinfo);
/* We can use jpeg_abort to release memory and reset global_state */
jpeg_abort((j_common_ptr) cinfo);
jpeg_abort((j_common_ptr)cinfo);
return TRUE;
}

View File

@@ -159,9 +159,12 @@ jpeg_crop_scanline(j_decompress_ptr cinfo, JDIMENSION *xoffset,
JDIMENSION input_xoffset;
boolean reinit_upsampler = FALSE;
jpeg_component_info *compptr;
#ifdef UPSAMPLE_MERGING_SUPPORTED
my_master_ptr master = (my_master_ptr)cinfo->master;
#endif
if (cinfo->global_state != DSTATE_SCANNING || cinfo->output_scanline != 0)
if ((cinfo->global_state != DSTATE_SCANNING &&
cinfo->global_state != DSTATE_BUFIMAGE) || cinfo->output_scanline != 0)
ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state);
if (!xoffset || !width)
@@ -209,11 +212,13 @@ jpeg_crop_scanline(j_decompress_ptr cinfo, JDIMENSION *xoffset,
*/
*width = *width + input_xoffset - *xoffset;
cinfo->output_width = *width;
#ifdef UPSAMPLE_MERGING_SUPPORTED
if (master->using_merged_upsample && cinfo->max_v_samp_factor == 2) {
my_merged_upsample_ptr upsample = (my_merged_upsample_ptr)cinfo->upsample;
upsample->out_row_width =
cinfo->output_width * cinfo->out_color_components;
}
#endif
/* Set the first and last iMCU columns that we must decompress. These values
* will be used in single-scan decompressions.
@@ -324,7 +329,9 @@ LOCAL(void)
read_and_discard_scanlines(j_decompress_ptr cinfo, JDIMENSION num_lines)
{
JDIMENSION n;
#ifdef UPSAMPLE_MERGING_SUPPORTED
my_master_ptr master = (my_master_ptr)cinfo->master;
#endif
JSAMPLE dummy_sample[1] = { 0 };
JSAMPROW dummy_row = dummy_sample;
JSAMPARRAY scanlines = NULL;
@@ -348,10 +355,12 @@ read_and_discard_scanlines(j_decompress_ptr cinfo, JDIMENSION num_lines)
cinfo->cquantize->color_quantize = noop_quantize;
}
#ifdef UPSAMPLE_MERGING_SUPPORTED
if (master->using_merged_upsample && cinfo->max_v_samp_factor == 2) {
my_merged_upsample_ptr upsample = (my_merged_upsample_ptr)cinfo->upsample;
scanlines = &upsample->spare_row;
}
#endif
for (n = 0; n < num_lines; n++)
jpeg_read_scanlines(cinfo, scanlines, 1);
@@ -517,7 +526,7 @@ jpeg_skip_scanlines(j_decompress_ptr cinfo, JDIMENSION num_lines)
* all of the entropy decoding occurs in jpeg_start_decompress(), assuming
* that the input data source is non-suspending. This makes skipping easy.
*/
if (cinfo->inputctl->has_multiple_scans) {
if (cinfo->inputctl->has_multiple_scans || cinfo->buffered_image) {
if (cinfo->upsample->need_context_rows) {
cinfo->output_scanline += lines_to_skip;
cinfo->output_iMCU_row += lines_to_skip / lines_per_iMCU_row;

View File

@@ -22,7 +22,6 @@
#include "jinclude.h"
#include "jpeglib.h"
#include "jerror.h"
#include "jpegint.h"
/* Expanded data destination object for stdio output */
@@ -62,13 +61,13 @@ typedef my_mem_destination_mgr *my_mem_dest_ptr;
*/
METHODDEF(void)
init_destination (j_compress_ptr cinfo)
init_destination(j_compress_ptr cinfo)
{
my_dest_ptr dest = (my_dest_ptr) cinfo->dest;
my_dest_ptr dest = (my_dest_ptr)cinfo->dest;
/* Allocate the output buffer --- it will be released when done with image */
dest->buffer = (JOCTET *)
(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
(*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_IMAGE,
OUTPUT_BUF_SIZE * sizeof(JOCTET));
dest->pub.next_output_byte = dest->buffer;
@@ -77,7 +76,7 @@ init_destination (j_compress_ptr cinfo)
#if JPEG_LIB_VERSION >= 80 || defined(MEM_SRCDST_SUPPORTED)
METHODDEF(void)
init_mem_destination (j_compress_ptr cinfo)
init_mem_destination(j_compress_ptr cinfo)
{
/* no work necessary here */
}
@@ -108,12 +107,12 @@ init_mem_destination (j_compress_ptr cinfo)
*/
METHODDEF(boolean)
empty_output_buffer (j_compress_ptr cinfo)
empty_output_buffer(j_compress_ptr cinfo)
{
my_dest_ptr dest = (my_dest_ptr) cinfo->dest;
my_dest_ptr dest = (my_dest_ptr)cinfo->dest;
if (fwrite(dest->buffer, 1, OUTPUT_BUF_SIZE, dest->outfile) !=
(size_t) OUTPUT_BUF_SIZE)
(size_t)OUTPUT_BUF_SIZE)
ERREXIT(cinfo, JERR_FILE_WRITE);
dest->pub.next_output_byte = dest->buffer;
@@ -124,15 +123,15 @@ empty_output_buffer (j_compress_ptr cinfo)
#if JPEG_LIB_VERSION >= 80 || defined(MEM_SRCDST_SUPPORTED)
METHODDEF(boolean)
empty_mem_output_buffer (j_compress_ptr cinfo)
empty_mem_output_buffer(j_compress_ptr cinfo)
{
size_t nextsize;
JOCTET *nextbuffer;
my_mem_dest_ptr dest = (my_mem_dest_ptr) cinfo->dest;
my_mem_dest_ptr dest = (my_mem_dest_ptr)cinfo->dest;
/* Try to allocate new buffer with double size */
nextsize = dest->bufsize * 2;
nextbuffer = (JOCTET *) malloc(nextsize);
nextbuffer = (JOCTET *)malloc(nextsize);
if (nextbuffer == NULL)
ERREXIT1(cinfo, JERR_OUT_OF_MEMORY, 10);
@@ -164,9 +163,9 @@ empty_mem_output_buffer (j_compress_ptr cinfo)
*/
METHODDEF(void)
term_destination (j_compress_ptr cinfo)
term_destination(j_compress_ptr cinfo)
{
my_dest_ptr dest = (my_dest_ptr) cinfo->dest;
my_dest_ptr dest = (my_dest_ptr)cinfo->dest;
size_t datacount = OUTPUT_BUF_SIZE - dest->pub.free_in_buffer;
/* Write any data remaining in the buffer */
@@ -182,9 +181,9 @@ term_destination (j_compress_ptr cinfo)
#if JPEG_LIB_VERSION >= 80 || defined(MEM_SRCDST_SUPPORTED)
METHODDEF(void)
term_mem_destination (j_compress_ptr cinfo)
term_mem_destination(j_compress_ptr cinfo)
{
my_mem_dest_ptr dest = (my_mem_dest_ptr) cinfo->dest;
my_mem_dest_ptr dest = (my_mem_dest_ptr)cinfo->dest;
*dest->outbuffer = dest->buffer;
*dest->outsize = (unsigned long)(dest->bufsize - dest->pub.free_in_buffer);
@@ -199,7 +198,7 @@ term_mem_destination (j_compress_ptr cinfo)
*/
GLOBAL(void)
jpeg_stdio_dest (j_compress_ptr cinfo, FILE *outfile)
jpeg_stdio_dest(j_compress_ptr cinfo, FILE *outfile)
{
my_dest_ptr dest;
@@ -208,7 +207,7 @@ jpeg_stdio_dest (j_compress_ptr cinfo, FILE *outfile)
*/
if (cinfo->dest == NULL) { /* first time for this JPEG object? */
cinfo->dest = (struct jpeg_destination_mgr *)
(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
(*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_PERMANENT,
sizeof(my_destination_mgr));
} else if (cinfo->dest->init_destination != init_destination) {
/* It is unsafe to reuse the existing destination manager unless it was
@@ -220,7 +219,7 @@ jpeg_stdio_dest (j_compress_ptr cinfo, FILE *outfile)
ERREXIT(cinfo, JERR_BUFFER_SIZE);
}
dest = (my_dest_ptr) cinfo->dest;
dest = (my_dest_ptr)cinfo->dest;
dest->pub.init_destination = init_destination;
dest->pub.empty_output_buffer = empty_output_buffer;
dest->pub.term_destination = term_destination;
@@ -244,8 +243,8 @@ jpeg_stdio_dest (j_compress_ptr cinfo, FILE *outfile)
*/
GLOBAL(void)
jpeg_mem_dest_internal (j_compress_ptr cinfo,
unsigned char **outbuffer, unsigned long *outsize, int pool_id)
jpeg_mem_dest(j_compress_ptr cinfo, unsigned char **outbuffer,
unsigned long *outsize)
{
my_mem_dest_ptr dest;
@@ -257,7 +256,7 @@ jpeg_mem_dest_internal (j_compress_ptr cinfo,
*/
if (cinfo->dest == NULL) { /* first time for this JPEG object? */
cinfo->dest = (struct jpeg_destination_mgr *)
(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, pool_id,
(*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_PERMANENT,
sizeof(my_mem_destination_mgr));
} else if (cinfo->dest->init_destination != init_mem_destination) {
/* It is unsafe to reuse the existing destination manager unless it was
@@ -266,7 +265,7 @@ jpeg_mem_dest_internal (j_compress_ptr cinfo,
ERREXIT(cinfo, JERR_BUFFER_SIZE);
}
dest = (my_mem_dest_ptr) cinfo->dest;
dest = (my_mem_dest_ptr)cinfo->dest;
dest->pub.init_destination = init_mem_destination;
dest->pub.empty_output_buffer = empty_mem_output_buffer;
dest->pub.term_destination = term_mem_destination;
@@ -276,7 +275,7 @@ jpeg_mem_dest_internal (j_compress_ptr cinfo,
if (*outbuffer == NULL || *outsize == 0) {
/* Allocate initial buffer */
dest->newbuffer = *outbuffer = (unsigned char *) malloc(OUTPUT_BUF_SIZE);
dest->newbuffer = *outbuffer = (unsigned char *)malloc(OUTPUT_BUF_SIZE);
if (dest->newbuffer == NULL)
ERREXIT1(cinfo, JERR_OUT_OF_MEMORY, 10);
*outsize = OUTPUT_BUF_SIZE;
@@ -285,15 +284,4 @@ jpeg_mem_dest_internal (j_compress_ptr cinfo,
dest->pub.next_output_byte = dest->buffer = *outbuffer;
dest->pub.free_in_buffer = dest->bufsize = *outsize;
}
GLOBAL(void)
jpeg_mem_dest (j_compress_ptr cinfo,
unsigned char **outbuffer, unsigned long *outsize)
{
/* The destination object is made permanent so that multiple JPEG images
* can be written to the same file without re-executing jpeg_stdio_dest.
*/
jpeg_mem_dest_internal(cinfo, outbuffer, outsize, JPOOL_PERMANENT);
}
#endif

View File

@@ -5,7 +5,7 @@
* Copyright (C) 1994-1997, Thomas G. Lane.
* libjpeg-turbo Modifications:
* Copyright 2009 Pierre Ossman <ossman@cendio.se> for Cendio AB
* Copyright (C) 2010, 2015-2016, 2019-2020, D. R. Commander.
* Copyright (C) 2010, 2015-2016, 2019-2020, 2022, D. R. Commander.
* Copyright (C) 2015, 2020, Google, Inc.
* For conditions of distribution and use, see the accompanying README.ijg
* file.
@@ -475,7 +475,7 @@ decompress_smooth_data(j_decompress_ptr cinfo, JSAMPIMAGE output_buf)
if (!compptr->component_needed)
continue;
/* Count non-dummy DCT block rows in this iMCU row. */
if (cinfo->output_iMCU_row < last_iMCU_row - 1) {
if (cinfo->output_iMCU_row + 1 < last_iMCU_row) {
block_rows = compptr->v_samp_factor;
access_rows = block_rows * 3; /* this and next two iMCU rows */
} else if (cinfo->output_iMCU_row < last_iMCU_row) {
@@ -560,7 +560,7 @@ decompress_smooth_data(j_decompress_ptr cinfo, JSAMPIMAGE output_buf)
next_block_row = buffer_ptr;
if (block_row < block_rows - 2 ||
cinfo->output_iMCU_row < last_iMCU_row - 1)
cinfo->output_iMCU_row + 1 < last_iMCU_row)
next_next_block_row =
buffer[block_row + 2] + cinfo->master->first_MCU_col[ci];
else

View File

@@ -27,7 +27,6 @@
#include "jdct.h" /* Private declarations for DCT subsystem */
#include "jsimddct.h"
#include "jpegcomp.h"
#include "jdmaster.h"
/*
@@ -87,11 +86,6 @@ typedef union {
#endif
#endif
EXTERN(void) jpeg_set_idct_method_selector (j_decompress_ptr cinfo, jpeg_idct_method_selector selector){
my_master_ptr master = (my_master_ptr) cinfo->master;
master->custom_idct_selector = selector;
}
/*
* Prepare for an output pass.
@@ -108,7 +102,6 @@ start_pass(j_decompress_ptr cinfo)
int method = 0;
inverse_DCT_method_ptr method_ptr = NULL;
JQUANT_TBL *qtbl;
my_master_ptr master;
for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
ci++, compptr++) {
@@ -232,14 +225,6 @@ start_pass(j_decompress_ptr cinfo)
ERREXIT1(cinfo, JERR_BAD_DCTSIZE, compptr->_DCT_scaled_size);
break;
}
// Allow custom idct function to be set dynamically
master = (my_master_ptr) cinfo->master;
if (master->custom_idct_selector != NULL) {
master->custom_idct_selector(cinfo, compptr, &method_ptr, &method);
}
idct->pub.inverse_DCT[ci] = method_ptr;
/* Create multiplier table from quant table.
* However, we can skip this if the component is uninteresting

View File

@@ -23,11 +23,6 @@ typedef struct {
*/
struct jpeg_color_quantizer *quantizer_1pass;
struct jpeg_color_quantizer *quantizer_2pass;
/*
* Permit users to replace the IDCT method
*/
jpeg_idct_method_selector custom_idct_selector;
} my_decomp_master;
typedef my_decomp_master *my_master_ptr;

View File

@@ -189,9 +189,9 @@ format_message(j_common_ptr cinfo, char *buffer)
/* Format the message into the passed buffer */
if (isstring)
snprintf(buffer, JMSG_LENGTH_MAX, msgtext, err->msg_parm.s);
SNPRINTF(buffer, JMSG_LENGTH_MAX, msgtext, err->msg_parm.s);
else
snprintf(buffer, JMSG_LENGTH_MAX, msgtext,
SNPRINTF(buffer, JMSG_LENGTH_MAX, msgtext,
err->msg_parm.i[0], err->msg_parm.i[1],
err->msg_parm.i[2], err->msg_parm.i[3],
err->msg_parm.i[4], err->msg_parm.i[5],

View File

@@ -28,7 +28,7 @@
#define JMAKE_ENUM_LIST
#else
/* Repeated inclusions of this file are no-ops unless JMESSAGE is defined */
#define JMESSAGE(code,string)
#define JMESSAGE(code, string)
#endif /* JERROR_H */
#endif /* JMESSAGE */
@@ -36,7 +36,7 @@
typedef enum {
#define JMESSAGE(code,string) code ,
#define JMESSAGE(code, string) code,
#endif /* JMAKE_ENUM_LIST */
@@ -206,10 +206,6 @@ JMESSAGE(JERR_NO_ARITH_TABLE, "Arithmetic table 0x%02x was not defined")
JMESSAGE(JWRN_ARITH_BAD_CODE, "Corrupt JPEG data: bad arithmetic code")
#endif
#endif
JMESSAGE(JERR_BAD_PARAM, "Bogus parameter")
JMESSAGE(JERR_BAD_PARAM_VALUE, "Bogus parameter value")
JMESSAGE(JERR_UNSUPPORTED_SUSPEND, "I/O suspension not supported in scan optimization")
JMESSAGE(JWRN_BOGUS_ICC, "Corrupt JPEG data: bad ICC marker")
#if JPEG_LIB_VERSION < 70
JMESSAGE(JERR_BAD_DROP_SAMPLING,
@@ -235,25 +231,25 @@ JMESSAGE(JERR_BAD_DROP_SAMPLING,
/* The first parameter is either type of cinfo pointer */
/* Fatal errors (print message and exit) */
#define ERREXIT(cinfo,code) \
#define ERREXIT(cinfo, code) \
((cinfo)->err->msg_code = (code), \
(*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo)))
#define ERREXIT1(cinfo,code,p1) \
(*(cinfo)->err->error_exit) ((j_common_ptr)(cinfo)))
#define ERREXIT1(cinfo, code, p1) \
((cinfo)->err->msg_code = (code), \
(cinfo)->err->msg_parm.i[0] = (p1), \
(*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo)))
#define ERREXIT2(cinfo,code,p1,p2) \
(*(cinfo)->err->error_exit) ((j_common_ptr)(cinfo)))
#define ERREXIT2(cinfo, code, p1, p2) \
((cinfo)->err->msg_code = (code), \
(cinfo)->err->msg_parm.i[0] = (p1), \
(cinfo)->err->msg_parm.i[1] = (p2), \
(*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo)))
#define ERREXIT3(cinfo,code,p1,p2,p3) \
(*(cinfo)->err->error_exit) ((j_common_ptr)(cinfo)))
#define ERREXIT3(cinfo, code, p1, p2, p3) \
((cinfo)->err->msg_code = (code), \
(cinfo)->err->msg_parm.i[0] = (p1), \
(cinfo)->err->msg_parm.i[1] = (p2), \
(cinfo)->err->msg_parm.i[2] = (p3), \
(*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo)))
#define ERREXIT4(cinfo,code,p1,p2,p3,p4) \
(*(cinfo)->err->error_exit) ((j_common_ptr)(cinfo)))
#define ERREXIT4(cinfo, code, p1, p2, p3, p4) \
((cinfo)->err->msg_code = (code), \
(cinfo)->err->msg_parm.i[0] = (p1), \
(cinfo)->err->msg_parm.i[1] = (p2), \
@@ -278,55 +274,55 @@ JMESSAGE(JERR_BAD_DROP_SAMPLING,
#define MAKESTMT(stuff) do { stuff } while (0)
/* Nonfatal errors (we can keep going, but the data is probably corrupt) */
#define WARNMS(cinfo,code) \
#define WARNMS(cinfo, code) \
((cinfo)->err->msg_code = (code), \
(*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), -1))
#define WARNMS1(cinfo,code,p1) \
(*(cinfo)->err->emit_message) ((j_common_ptr)(cinfo), -1))
#define WARNMS1(cinfo, code, p1) \
((cinfo)->err->msg_code = (code), \
(cinfo)->err->msg_parm.i[0] = (p1), \
(*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), -1))
#define WARNMS2(cinfo,code,p1,p2) \
(*(cinfo)->err->emit_message) ((j_common_ptr)(cinfo), -1))
#define WARNMS2(cinfo, code, p1, p2) \
((cinfo)->err->msg_code = (code), \
(cinfo)->err->msg_parm.i[0] = (p1), \
(cinfo)->err->msg_parm.i[1] = (p2), \
(*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), -1))
(*(cinfo)->err->emit_message) ((j_common_ptr)(cinfo), -1))
/* Informational/debugging messages */
#define TRACEMS(cinfo,lvl,code) \
#define TRACEMS(cinfo, lvl, code) \
((cinfo)->err->msg_code = (code), \
(*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl)))
#define TRACEMS1(cinfo,lvl,code,p1) \
(*(cinfo)->err->emit_message) ((j_common_ptr)(cinfo), (lvl)))
#define TRACEMS1(cinfo, lvl, code, p1) \
((cinfo)->err->msg_code = (code), \
(cinfo)->err->msg_parm.i[0] = (p1), \
(*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl)))
#define TRACEMS2(cinfo,lvl,code,p1,p2) \
(*(cinfo)->err->emit_message) ((j_common_ptr)(cinfo), (lvl)))
#define TRACEMS2(cinfo, lvl, code, p1, p2) \
((cinfo)->err->msg_code = (code), \
(cinfo)->err->msg_parm.i[0] = (p1), \
(cinfo)->err->msg_parm.i[1] = (p2), \
(*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl)))
#define TRACEMS3(cinfo,lvl,code,p1,p2,p3) \
MAKESTMT(int * _mp = (cinfo)->err->msg_parm.i; \
(*(cinfo)->err->emit_message) ((j_common_ptr)(cinfo), (lvl)))
#define TRACEMS3(cinfo, lvl, code, p1, p2, p3) \
MAKESTMT(int *_mp = (cinfo)->err->msg_parm.i; \
_mp[0] = (p1); _mp[1] = (p2); _mp[2] = (p3); \
(cinfo)->err->msg_code = (code); \
(*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl)); )
#define TRACEMS4(cinfo,lvl,code,p1,p2,p3,p4) \
MAKESTMT(int * _mp = (cinfo)->err->msg_parm.i; \
(*(cinfo)->err->emit_message) ((j_common_ptr)(cinfo), (lvl)); )
#define TRACEMS4(cinfo, lvl, code, p1, p2, p3, p4) \
MAKESTMT(int *_mp = (cinfo)->err->msg_parm.i; \
_mp[0] = (p1); _mp[1] = (p2); _mp[2] = (p3); _mp[3] = (p4); \
(cinfo)->err->msg_code = (code); \
(*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl)); )
#define TRACEMS5(cinfo,lvl,code,p1,p2,p3,p4,p5) \
MAKESTMT(int * _mp = (cinfo)->err->msg_parm.i; \
(*(cinfo)->err->emit_message) ((j_common_ptr)(cinfo), (lvl)); )
#define TRACEMS5(cinfo, lvl, code, p1, p2, p3, p4, p5) \
MAKESTMT(int *_mp = (cinfo)->err->msg_parm.i; \
_mp[0] = (p1); _mp[1] = (p2); _mp[2] = (p3); _mp[3] = (p4); \
_mp[4] = (p5); \
(cinfo)->err->msg_code = (code); \
(*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl)); )
#define TRACEMS8(cinfo,lvl,code,p1,p2,p3,p4,p5,p6,p7,p8) \
MAKESTMT(int * _mp = (cinfo)->err->msg_parm.i; \
(*(cinfo)->err->emit_message) ((j_common_ptr)(cinfo), (lvl)); )
#define TRACEMS8(cinfo, lvl, code, p1, p2, p3, p4, p5, p6, p7, p8) \
MAKESTMT(int *_mp = (cinfo)->err->msg_parm.i; \
_mp[0] = (p1); _mp[1] = (p2); _mp[2] = (p3); _mp[3] = (p4); \
_mp[4] = (p5); _mp[5] = (p6); _mp[6] = (p7); _mp[7] = (p8); \
(cinfo)->err->msg_code = (code); \
(*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl)); )
#define TRACEMSS(cinfo,lvl,code,str) \
(*(cinfo)->err->emit_message) ((j_common_ptr)(cinfo), (lvl)); )
#define TRACEMSS(cinfo, lvl, code, str) \
((cinfo)->err->msg_code = (code), \
strncpy((cinfo)->err->msg_parm.s, (str), JMSG_STR_PARM_MAX), \
(cinfo)->err->msg_parm.s[JMSG_STR_PARM_MAX - 1] = '\0', \

View File

@@ -45,6 +45,18 @@
*/
#ifdef _MSC_VER
#define SNPRINTF(str, n, format, ...) \
_snprintf_s(str, n, _TRUNCATE, format, ##__VA_ARGS__)
#else
#define SNPRINTF snprintf
#endif
#ifndef NO_GETENV
#ifdef _MSC_VER

View File

@@ -68,10 +68,13 @@ round_up_pow2(size_t a, size_t b)
* There isn't any really portable way to determine the worst-case alignment
* requirement. This module assumes that the alignment requirement is
* multiples of ALIGN_SIZE.
* By default, we define ALIGN_SIZE as sizeof(double). This is necessary on
* some workstations (where doubles really do need 8-byte alignment) and will
* work fine on nearly everything. If your machine has lesser alignment needs,
* you can save a few bytes by making ALIGN_SIZE smaller.
* By default, we define ALIGN_SIZE as the maximum of sizeof(double) and
* sizeof(void *). This is necessary on some workstations (where doubles
* really do need 8-byte alignment) and will work fine on nearly everything.
* We use the maximum of sizeof(double) and sizeof(void *) since sizeof(double)
* may be insufficient, for example, on CHERI-enabled platforms with 16-byte
* pointers and a 16-byte alignment requirement. If your machine has lesser
* alignment needs, you can save a few bytes by making ALIGN_SIZE smaller.
* The only place I know of where this will NOT work is certain Macintosh
* 680x0 compilers that define double as a 10-byte IEEE extended float.
* Doing 10-byte alignment is counterproductive because longwords won't be
@@ -81,7 +84,7 @@ round_up_pow2(size_t a, size_t b)
#ifndef ALIGN_SIZE /* so can override from jconfig.h */
#ifndef WITH_SIMD
#define ALIGN_SIZE sizeof(double)
#define ALIGN_SIZE MAX(sizeof(void *), sizeof(double))
#else
#define ALIGN_SIZE 32 /* Most of the SIMD instructions we support require
16-byte (128-bit) alignment, but AVX2 requires

158
jpegint.h
View File

@@ -8,8 +8,6 @@
* Copyright (C) 2015-2016, 2019, 2021, D. R. Commander.
* Copyright (C) 2015, Google, Inc.
* Copyright (C) 2021, Alex Richardson.
* mozjpeg Modifications:
* Copyright (C) 2014, Mozilla Corporation.
* For conditions of distribution and use, see the accompanying README.ijg
* file.
*
@@ -26,8 +24,7 @@ typedef enum { /* Operating modes for buffer controllers */
/* Remaining modes require a full-image buffer to have been created */
JBUF_SAVE_SOURCE, /* Run source subobject only, save output */
JBUF_CRANK_DEST, /* Run dest subobject only, using saved data */
JBUF_SAVE_AND_PASS, /* Run both subobjects, save output */
JBUF_REQUANT /* Requantize */
JBUF_SAVE_AND_PASS /* Run both subobjects, save output */
} J_BUF_MODE;
/* Values of global_state field (jdapi.c has some dependencies on ordering!) */
@@ -83,67 +80,8 @@ struct jpeg_comp_master {
/* State variables made visible to other modules */
boolean call_pass_startup; /* True if pass_startup must be called */
boolean is_last_pass; /* True during last pass */
/* Extension parameters */
boolean optimize_scans; /* TRUE=optimize progressive coding scans */
boolean trellis_quant; /* TRUE=use trellis quantization */
boolean trellis_quant_dc; /* TRUE=use trellis quant for DC coefficient */
boolean trellis_eob_opt; /* TRUE=optimize for sequences of EOB */
boolean use_lambda_weight_tbl; /* TRUE=use lambda weighting table */
boolean use_scans_in_trellis; /* TRUE=use scans in trellis optimization */
boolean trellis_passes; /* TRUE=currently doing trellis-related passes [not exposed] */
boolean trellis_q_opt; /* TRUE=optimize quant table in trellis loop */
boolean overshoot_deringing; /* TRUE=preprocess input to reduce ringing of edges on white background */
double norm_src[NUM_QUANT_TBLS][DCTSIZE2];
double norm_coef[NUM_QUANT_TBLS][DCTSIZE2];
int compress_profile; /* compression profile */
int dc_scan_opt_mode; /* DC scan optimization mode */
int quant_tbl_master_idx; /* Quantization table master index */
int trellis_freq_split; /* splitting point for frequency in trellis quantization */
int trellis_num_loops; /* number of trellis loops */
int num_scans_luma; /* # of entries in scan_info array pertaining to luma (used when optimize_scans is TRUE */
int num_scans_luma_dc;
int num_scans_chroma_dc;
int num_frequency_splits;
int Al_max_luma; /* maximum value of Al tested when optimizing scans (luma) */
int Al_max_chroma; /* maximum value of Al tested when optimizing scans (chroma) */
float lambda_log_scale1;
float lambda_log_scale2;
float trellis_delta_dc_weight;
};
#ifdef C_ARITH_CODING_SUPPORTED
/* The following two definitions specify the allocation chunk size
* for the statistics area.
* According to sections F.1.4.4.1.3 and F.1.4.4.2, we need at least
* 49 statistics bins for DC, and 245 statistics bins for AC coding.
*
* We use a compact representation with 1 byte per statistics bin,
* thus the numbers directly represent byte sizes.
* This 1 byte per statistics bin contains the meaning of the MPS
* (more probable symbol) in the highest bit (mask 0x80), and the
* index into the probability estimation state machine table
* in the lower bits (mask 0x7F).
*/
#define DC_STAT_BINS 64
#define AC_STAT_BINS 256
typedef struct {
float rate_dc[DC_STAT_BINS][2];
float rate_ac[AC_STAT_BINS][2];
int arith_dc_L;
int arith_dc_U;
int arith_ac_K;
} arith_rates;
#endif
/* Main buffer control (downsampled-data buffer) */
struct jpeg_c_main_controller {
void (*start_pass) (j_compress_ptr cinfo, J_BUF_MODE pass_mode);
@@ -192,7 +130,7 @@ struct jpeg_forward_dct {
void (*forward_DCT) (j_compress_ptr cinfo, jpeg_component_info *compptr,
JSAMPARRAY sample_data, JBLOCKROW coef_blocks,
JDIMENSION start_row, JDIMENSION start_col,
JDIMENSION num_blocks, JBLOCKROW dst);
JDIMENSION num_blocks);
};
/* Entropy encoding */
@@ -352,9 +290,9 @@ struct jpeg_color_quantizer {
/* Miscellaneous useful macros */
#undef MAX
#define MAX(a,b) ((a) > (b) ? (a) : (b))
#define MAX(a, b) ((a) > (b) ? (a) : (b))
#undef MIN
#define MIN(a,b) ((a) < (b) ? (a) : (b))
#define MIN(a, b) ((a) < (b) ? (a) : (b))
/* We assume that right shift corresponds to signed division by 2 with
@@ -369,80 +307,64 @@ struct jpeg_color_quantizer {
#ifdef RIGHT_SHIFT_IS_UNSIGNED
#define SHIFT_TEMPS JLONG shift_temp;
#define RIGHT_SHIFT(x,shft) \
#define RIGHT_SHIFT(x, shft) \
((shift_temp = (x)) < 0 ? \
(shift_temp >> (shft)) | ((~((JLONG) 0)) << (32-(shft))) : \
(shift_temp >> (shft)) | ((~((JLONG)0)) << (32 - (shft))) : \
(shift_temp >> (shft)))
#else
#define SHIFT_TEMPS
#define RIGHT_SHIFT(x,shft) ((x) >> (shft))
#define RIGHT_SHIFT(x, shft) ((x) >> (shft))
#endif
/* Compression module initialization routines */
EXTERN(void) jinit_compress_master (j_compress_ptr cinfo);
EXTERN(void) jinit_c_master_control (j_compress_ptr cinfo,
EXTERN(void) jinit_compress_master(j_compress_ptr cinfo);
EXTERN(void) jinit_c_master_control(j_compress_ptr cinfo,
boolean transcode_only);
EXTERN(void) jinit_c_main_controller (j_compress_ptr cinfo,
EXTERN(void) jinit_c_main_controller(j_compress_ptr cinfo,
boolean need_full_buffer);
EXTERN(void) jinit_c_prep_controller (j_compress_ptr cinfo,
EXTERN(void) jinit_c_prep_controller(j_compress_ptr cinfo,
boolean need_full_buffer);
EXTERN(void) jinit_c_coef_controller (j_compress_ptr cinfo,
EXTERN(void) jinit_c_coef_controller(j_compress_ptr cinfo,
boolean need_full_buffer);
EXTERN(void) jinit_color_converter (j_compress_ptr cinfo);
EXTERN(void) jinit_downsampler (j_compress_ptr cinfo);
EXTERN(void) jinit_forward_dct (j_compress_ptr cinfo);
EXTERN(void) jinit_huff_encoder (j_compress_ptr cinfo);
EXTERN(void) jinit_phuff_encoder (j_compress_ptr cinfo);
EXTERN(void) jinit_arith_encoder (j_compress_ptr cinfo);
EXTERN(void) jinit_marker_writer (j_compress_ptr cinfo);
EXTERN(void) jinit_color_converter(j_compress_ptr cinfo);
EXTERN(void) jinit_downsampler(j_compress_ptr cinfo);
EXTERN(void) jinit_forward_dct(j_compress_ptr cinfo);
EXTERN(void) jinit_huff_encoder(j_compress_ptr cinfo);
EXTERN(void) jinit_phuff_encoder(j_compress_ptr cinfo);
EXTERN(void) jinit_arith_encoder(j_compress_ptr cinfo);
EXTERN(void) jinit_marker_writer(j_compress_ptr cinfo);
/* Decompression module initialization routines */
EXTERN(void) jinit_master_decompress (j_decompress_ptr cinfo);
EXTERN(void) jinit_d_main_controller (j_decompress_ptr cinfo,
EXTERN(void) jinit_master_decompress(j_decompress_ptr cinfo);
EXTERN(void) jinit_d_main_controller(j_decompress_ptr cinfo,
boolean need_full_buffer);
EXTERN(void) jinit_d_coef_controller (j_decompress_ptr cinfo,
EXTERN(void) jinit_d_coef_controller(j_decompress_ptr cinfo,
boolean need_full_buffer);
EXTERN(void) jinit_d_post_controller (j_decompress_ptr cinfo,
EXTERN(void) jinit_d_post_controller(j_decompress_ptr cinfo,
boolean need_full_buffer);
EXTERN(void) jinit_input_controller (j_decompress_ptr cinfo);
EXTERN(void) jinit_marker_reader (j_decompress_ptr cinfo);
EXTERN(void) jinit_huff_decoder (j_decompress_ptr cinfo);
EXTERN(void) jinit_phuff_decoder (j_decompress_ptr cinfo);
EXTERN(void) jinit_arith_decoder (j_decompress_ptr cinfo);
EXTERN(void) jinit_inverse_dct (j_decompress_ptr cinfo);
EXTERN(void) jinit_upsampler (j_decompress_ptr cinfo);
EXTERN(void) jinit_color_deconverter (j_decompress_ptr cinfo);
EXTERN(void) jinit_1pass_quantizer (j_decompress_ptr cinfo);
EXTERN(void) jinit_2pass_quantizer (j_decompress_ptr cinfo);
EXTERN(void) jinit_merged_upsampler (j_decompress_ptr cinfo);
EXTERN(void) jinit_input_controller(j_decompress_ptr cinfo);
EXTERN(void) jinit_marker_reader(j_decompress_ptr cinfo);
EXTERN(void) jinit_huff_decoder(j_decompress_ptr cinfo);
EXTERN(void) jinit_phuff_decoder(j_decompress_ptr cinfo);
EXTERN(void) jinit_arith_decoder(j_decompress_ptr cinfo);
EXTERN(void) jinit_inverse_dct(j_decompress_ptr cinfo);
EXTERN(void) jinit_upsampler(j_decompress_ptr cinfo);
EXTERN(void) jinit_color_deconverter(j_decompress_ptr cinfo);
EXTERN(void) jinit_1pass_quantizer(j_decompress_ptr cinfo);
EXTERN(void) jinit_2pass_quantizer(j_decompress_ptr cinfo);
EXTERN(void) jinit_merged_upsampler(j_decompress_ptr cinfo);
/* Memory manager initialization */
EXTERN(void) jinit_memory_mgr (j_common_ptr cinfo);
#if JPEG_LIB_VERSION >= 80 || defined(MEM_SRCDST_SUPPORTED)
EXTERN(void)
jpeg_mem_dest_internal (j_compress_ptr cinfo,
unsigned char **outbuffer, unsigned long *outsize, int pool_id);
#endif
EXTERN(void) jinit_memory_mgr(j_common_ptr cinfo);
/* Utility routines in jutils.c */
EXTERN(long) jdiv_round_up (long a, long b);
EXTERN(long) jround_up (long a, long b);
EXTERN(void) jcopy_sample_rows (JSAMPARRAY input_array, int source_row,
EXTERN(long) jdiv_round_up(long a, long b);
EXTERN(long) jround_up(long a, long b);
EXTERN(void) jcopy_sample_rows(JSAMPARRAY input_array, int source_row,
JSAMPARRAY output_array, int dest_row,
int num_rows, JDIMENSION num_cols);
EXTERN(void) jcopy_block_row (JBLOCKROW input_row, JBLOCKROW output_row,
EXTERN(void) jcopy_block_row(JBLOCKROW input_row, JBLOCKROW output_row,
JDIMENSION num_blocks);
EXTERN(void) jzero_far (void *target, size_t bytestozero);
#ifdef C_ARITH_CODING_SUPPORTED
EXTERN(void) jget_arith_rates (j_compress_ptr cinfo, int dc_tbl_no, int ac_tbl_no, arith_rates *r);
EXTERN(void) quantize_trellis_arith
(j_compress_ptr cinfo, arith_rates *r, 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);
#endif
EXTERN(void) jzero_far(void *target, size_t bytestozero);
/* Constant tables in jutils.c */
#if 0 /* This table is not actually needed in v6a */
extern const int jpeg_zigzag_order[]; /* natural coef order to zigzag order */

272
jpeglib.h
View File

@@ -7,8 +7,6 @@
* libjpeg-turbo Modifications:
* Copyright (C) 2009-2011, 2013-2014, 2016-2017, 2020, D. R. Commander.
* Copyright (C) 2015, Google, Inc.
* mozjpeg Modifications:
* Copyright (C) 2014, Mozilla Corporation.
* For conditions of distribution and use, see the accompanying README.ijg
* file.
*
@@ -213,8 +211,8 @@ struct jpeg_marker_struct {
/* Known color spaces. */
#define JCS_EXTENSIONS 1
#define JCS_ALPHA_EXTENSIONS 1
#define JCS_EXTENSIONS 1
#define JCS_ALPHA_EXTENSIONS 1
typedef enum {
JCS_UNKNOWN, /* error/unspecified */
@@ -267,60 +265,14 @@ typedef enum {
} J_DITHER_MODE;
/* These 32-bit GUIDs and the corresponding jpeg_*_get_*_param()/
* jpeg_*_set_*_param() functions allow for extending the libjpeg API without
* breaking backward ABI compatibility. The actual parameters are stored in
* the opaque jpeg_comp_master and jpeg_decomp_master structs.
*/
/* Boolean extension parameters */
typedef enum {
JBOOLEAN_OPTIMIZE_SCANS = 0x680C061E, /* TRUE=optimize progressive coding scans */
JBOOLEAN_TRELLIS_QUANT = 0xC5122033, /* TRUE=use trellis quantization */
JBOOLEAN_TRELLIS_QUANT_DC = 0x339D4C0C, /* TRUE=use trellis quant for DC coefficient */
JBOOLEAN_TRELLIS_EOB_OPT = 0xD7F73780, /* TRUE=optimize for sequences of EOB */
JBOOLEAN_USE_LAMBDA_WEIGHT_TBL = 0x339DB65F, /* TRUE=use lambda weighting table */
JBOOLEAN_USE_SCANS_IN_TRELLIS = 0xFD841435, /* TRUE=use scans in trellis optimization */
JBOOLEAN_TRELLIS_Q_OPT = 0xE12AE269, /* TRUE=optimize quant table in trellis loop */
JBOOLEAN_OVERSHOOT_DERINGING = 0x3F4BBBF9 /* TRUE=preprocess input to reduce ringing of edges on white background */
} J_BOOLEAN_PARAM;
/* Floating point parameters */
typedef enum {
JFLOAT_LAMBDA_LOG_SCALE1 = 0x5B61A599,
JFLOAT_LAMBDA_LOG_SCALE2 = 0xB9BBAE03,
JFLOAT_TRELLIS_DELTA_DC_WEIGHT = 0x13775453
} J_FLOAT_PARAM;
/* Integer parameters */
typedef enum {
JINT_COMPRESS_PROFILE = 0xE9918625, /* compression profile */
JINT_TRELLIS_FREQ_SPLIT = 0x6FAFF127, /* splitting point for frequency in trellis quantization */
JINT_TRELLIS_NUM_LOOPS = 0xB63EBF39, /* number of trellis loops */
JINT_BASE_QUANT_TBL_IDX = 0x44492AB1, /* base quantization table index */
JINT_DC_SCAN_OPT_MODE = 0x0BE7AD3C /* DC scan optimization mode */
} J_INT_PARAM;
/* Values for the JINT_COMPRESS_PROFILE parameter (32-bit GUIDs) */
enum {
JCP_MAX_COMPRESSION = 0x5D083AAD, /* best compression ratio (progressive, all mozjpeg extensions) */
JCP_FASTEST = 0x2AEA5CB4 /* libjpeg[-turbo] defaults (baseline, no mozjpeg extensions) */
};
/* Common fields between JPEG compression and decompression master structs. */
#define jpeg_common_fields \
struct jpeg_error_mgr *err; /* Error handler module */\
struct jpeg_memory_mgr *mem; /* Memory manager module */\
struct jpeg_progress_mgr *progress; /* Progress monitor, or NULL if none */\
void *client_data; /* Available for use by application */\
boolean is_decompressor; /* So common code can tell which is which */\
struct jpeg_error_mgr *err; /* Error handler module */ \
struct jpeg_memory_mgr *mem; /* Memory manager module */ \
struct jpeg_progress_mgr *progress; /* Progress monitor, or NULL if none */ \
void *client_data; /* Available for use by application */ \
boolean is_decompressor; /* So common code can tell which is which */ \
int global_state /* For checking call sequence validity */
/* Routines that are to be used by both halves of the library are declared
@@ -514,8 +466,6 @@ struct jpeg_compress_struct {
int script_space_size;
};
typedef void (*jpeg_idct_method) (j_decompress_ptr cinfo, jpeg_component_info *compptr, JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col);
typedef void (*jpeg_idct_method_selector) (j_decompress_ptr cinfo, jpeg_component_info *compptr, jpeg_idct_method * set_idct_method, int * set_idct_category);
/* Master record for a decompression instance */
@@ -872,9 +822,9 @@ struct jpeg_source_mgr {
* successful.
*/
#define JPOOL_PERMANENT 0 /* lasts until master record is destroyed */
#define JPOOL_IMAGE 1 /* lasts until done with image/datastream */
#define JPOOL_NUMPOOLS 2
#define JPOOL_PERMANENT 0 /* lasts until master record is destroyed */
#define JPOOL_IMAGE 1 /* lasts until done with image/datastream */
#define JPOOL_NUMPOOLS 2
typedef struct jvirt_sarray_control *jvirt_sarray_ptr;
typedef struct jvirt_barray_control *jvirt_barray_ptr;
@@ -938,7 +888,7 @@ typedef boolean (*jpeg_marker_parser_method) (j_decompress_ptr cinfo);
/* Default error-management setup */
EXTERN(struct jpeg_error_mgr *) jpeg_std_error (struct jpeg_error_mgr *err);
EXTERN(struct jpeg_error_mgr *) jpeg_std_error(struct jpeg_error_mgr *err);
/* Initialization of JPEG compression objects.
* jpeg_create_compress() and jpeg_create_decompress() are the exported
@@ -948,83 +898,82 @@ EXTERN(struct jpeg_error_mgr *) jpeg_std_error (struct jpeg_error_mgr *err);
* NB: you must set up the error-manager BEFORE calling jpeg_create_xxx.
*/
#define jpeg_create_compress(cinfo) \
jpeg_CreateCompress((cinfo), JPEG_LIB_VERSION, \
(size_t) sizeof(struct jpeg_compress_struct))
jpeg_CreateCompress((cinfo), JPEG_LIB_VERSION, \
(size_t)sizeof(struct jpeg_compress_struct))
#define jpeg_create_decompress(cinfo) \
jpeg_CreateDecompress((cinfo), JPEG_LIB_VERSION, \
(size_t) sizeof(struct jpeg_decompress_struct))
EXTERN(void) jpeg_CreateCompress (j_compress_ptr cinfo, int version,
size_t structsize);
EXTERN(void) jpeg_CreateDecompress (j_decompress_ptr cinfo, int version,
size_t structsize);
jpeg_CreateDecompress((cinfo), JPEG_LIB_VERSION, \
(size_t)sizeof(struct jpeg_decompress_struct))
EXTERN(void) jpeg_CreateCompress(j_compress_ptr cinfo, int version,
size_t structsize);
EXTERN(void) jpeg_CreateDecompress(j_decompress_ptr cinfo, int version,
size_t structsize);
/* Destruction of JPEG compression objects */
EXTERN(void) jpeg_destroy_compress (j_compress_ptr cinfo);
EXTERN(void) jpeg_destroy_decompress (j_decompress_ptr cinfo);
EXTERN(void) jpeg_destroy_compress(j_compress_ptr cinfo);
EXTERN(void) jpeg_destroy_decompress(j_decompress_ptr cinfo);
/* Standard data source and destination managers: stdio streams. */
/* Caller is responsible for opening the file before and closing after. */
EXTERN(void) jpeg_stdio_dest (j_compress_ptr cinfo, FILE *outfile);
EXTERN(void) jpeg_stdio_src (j_decompress_ptr cinfo, FILE *infile);
EXTERN(void) jpeg_stdio_dest(j_compress_ptr cinfo, FILE *outfile);
EXTERN(void) jpeg_stdio_src(j_decompress_ptr cinfo, FILE *infile);
#if JPEG_LIB_VERSION >= 80 || defined(MEM_SRCDST_SUPPORTED)
/* Data source and destination managers: memory buffers. */
EXTERN(void) jpeg_mem_dest (j_compress_ptr cinfo, unsigned char **outbuffer,
unsigned long *outsize);
EXTERN(void) jpeg_mem_src (j_decompress_ptr cinfo,
EXTERN(void) jpeg_mem_dest(j_compress_ptr cinfo, unsigned char **outbuffer,
unsigned long *outsize);
EXTERN(void) jpeg_mem_src(j_decompress_ptr cinfo,
const unsigned char *inbuffer, unsigned long insize);
#endif
/* Default parameter setup for compression */
EXTERN(void) jpeg_set_defaults (j_compress_ptr cinfo);
EXTERN(void) jpeg_set_defaults(j_compress_ptr cinfo);
/* Compression parameter setup aids */
EXTERN(void) jpeg_set_colorspace (j_compress_ptr cinfo,
J_COLOR_SPACE colorspace);
EXTERN(void) jpeg_default_colorspace (j_compress_ptr cinfo);
EXTERN(void) jpeg_set_quality (j_compress_ptr cinfo, int quality,
boolean force_baseline);
EXTERN(void) jpeg_set_linear_quality (j_compress_ptr cinfo, int scale_factor,
boolean force_baseline);
EXTERN(void) jpeg_set_colorspace(j_compress_ptr cinfo,
J_COLOR_SPACE colorspace);
EXTERN(void) jpeg_default_colorspace(j_compress_ptr cinfo);
EXTERN(void) jpeg_set_quality(j_compress_ptr cinfo, int quality,
boolean force_baseline);
EXTERN(void) jpeg_set_linear_quality(j_compress_ptr cinfo, int scale_factor,
boolean force_baseline);
#if JPEG_LIB_VERSION >= 70
EXTERN(void) jpeg_default_qtables (j_compress_ptr cinfo,
boolean force_baseline);
EXTERN(void) jpeg_default_qtables(j_compress_ptr cinfo,
boolean force_baseline);
#endif
EXTERN(void) jpeg_add_quant_table (j_compress_ptr cinfo, int which_tbl,
const unsigned int *basic_table,
int scale_factor, boolean force_baseline);
EXTERN(int) jpeg_quality_scaling (int quality);
EXTERN(float) jpeg_float_quality_scaling (float quality);
EXTERN(void) jpeg_simple_progression (j_compress_ptr cinfo);
EXTERN(void) jpeg_suppress_tables (j_compress_ptr cinfo, boolean suppress);
EXTERN(JQUANT_TBL *) jpeg_alloc_quant_table (j_common_ptr cinfo);
EXTERN(JHUFF_TBL *) jpeg_alloc_huff_table (j_common_ptr cinfo);
EXTERN(void) jpeg_add_quant_table(j_compress_ptr cinfo, int which_tbl,
const unsigned int *basic_table,
int scale_factor, boolean force_baseline);
EXTERN(int) jpeg_quality_scaling(int quality);
EXTERN(void) jpeg_simple_progression(j_compress_ptr cinfo);
EXTERN(void) jpeg_suppress_tables(j_compress_ptr cinfo, boolean suppress);
EXTERN(JQUANT_TBL *) jpeg_alloc_quant_table(j_common_ptr cinfo);
EXTERN(JHUFF_TBL *) jpeg_alloc_huff_table(j_common_ptr cinfo);
/* Main entry points for compression */
EXTERN(void) jpeg_start_compress (j_compress_ptr cinfo,
boolean write_all_tables);
EXTERN(JDIMENSION) jpeg_write_scanlines (j_compress_ptr cinfo,
JSAMPARRAY scanlines,
JDIMENSION num_lines);
EXTERN(void) jpeg_finish_compress (j_compress_ptr cinfo);
EXTERN(void) jpeg_start_compress(j_compress_ptr cinfo,
boolean write_all_tables);
EXTERN(JDIMENSION) jpeg_write_scanlines(j_compress_ptr cinfo,
JSAMPARRAY scanlines,
JDIMENSION num_lines);
EXTERN(void) jpeg_finish_compress(j_compress_ptr cinfo);
#if JPEG_LIB_VERSION >= 70
/* Precalculate JPEG dimensions for current compression parameters. */
EXTERN(void) jpeg_calc_jpeg_dimensions (j_compress_ptr cinfo);
EXTERN(void) jpeg_calc_jpeg_dimensions(j_compress_ptr cinfo);
#endif
/* Replaces jpeg_write_scanlines when writing raw downsampled data. */
EXTERN(JDIMENSION) jpeg_write_raw_data (j_compress_ptr cinfo, JSAMPIMAGE data,
JDIMENSION num_lines);
EXTERN(JDIMENSION) jpeg_write_raw_data(j_compress_ptr cinfo, JSAMPIMAGE data,
JDIMENSION num_lines);
/* Write a special marker. See libjpeg.txt concerning safe usage. */
EXTERN(void) jpeg_write_marker (j_compress_ptr cinfo, int marker,
const JOCTET *dataptr, unsigned int datalen);
EXTERN(void) jpeg_write_marker(j_compress_ptr cinfo, int marker,
const JOCTET *dataptr, unsigned int datalen);
/* Same, but piecemeal. */
EXTERN(void) jpeg_write_m_header (j_compress_ptr cinfo, int marker,
unsigned int datalen);
EXTERN(void) jpeg_write_m_byte (j_compress_ptr cinfo, int val);
EXTERN(void) jpeg_write_m_header(j_compress_ptr cinfo, int marker,
unsigned int datalen);
EXTERN(void) jpeg_write_m_byte(j_compress_ptr cinfo, int val);
/* Alternate compression function: just write an abbreviated table file */
EXTERN(void) jpeg_write_tables (j_compress_ptr cinfo);
EXTERN(void) jpeg_write_tables(j_compress_ptr cinfo);
/* Write ICC profile. See libjpeg.txt for usage information. */
EXTERN(void) jpeg_write_icc_profile(j_compress_ptr cinfo,
@@ -1033,11 +982,11 @@ EXTERN(void) jpeg_write_icc_profile(j_compress_ptr cinfo,
/* Decompression startup: read start of JPEG datastream to see what's there */
EXTERN(int) jpeg_read_header (j_decompress_ptr cinfo, boolean require_image);
EXTERN(int) jpeg_read_header(j_decompress_ptr cinfo, boolean require_image);
/* Return value is one of: */
#define JPEG_SUSPENDED 0 /* Suspended due to lack of input data */
#define JPEG_HEADER_OK 1 /* Found valid image datastream */
#define JPEG_HEADER_TABLES_ONLY 2 /* Found valid table-specs-only datastream */
#define JPEG_SUSPENDED 0 /* Suspended due to lack of input data */
#define JPEG_HEADER_OK 1 /* Found valid image datastream */
#define JPEG_HEADER_TABLES_ONLY 2 /* Found valid table-specs-only datastream */
/* If you pass require_image = TRUE (normal case), you need not check for
* a TABLES_ONLY return code; an abbreviated file will cause an error exit.
* JPEG_SUSPENDED is only possible if you use a data source module that can
@@ -1045,27 +994,27 @@ EXTERN(int) jpeg_read_header (j_decompress_ptr cinfo, boolean require_image);
*/
/* Main entry points for decompression */
EXTERN(boolean) jpeg_start_decompress (j_decompress_ptr cinfo);
EXTERN(JDIMENSION) jpeg_read_scanlines (j_decompress_ptr cinfo,
JSAMPARRAY scanlines,
JDIMENSION max_lines);
EXTERN(JDIMENSION) jpeg_skip_scanlines (j_decompress_ptr cinfo,
JDIMENSION num_lines);
EXTERN(void) jpeg_crop_scanline (j_decompress_ptr cinfo, JDIMENSION *xoffset,
JDIMENSION *width);
EXTERN(boolean) jpeg_finish_decompress (j_decompress_ptr cinfo);
EXTERN(boolean) jpeg_start_decompress(j_decompress_ptr cinfo);
EXTERN(JDIMENSION) jpeg_read_scanlines(j_decompress_ptr cinfo,
JSAMPARRAY scanlines,
JDIMENSION max_lines);
EXTERN(JDIMENSION) jpeg_skip_scanlines(j_decompress_ptr cinfo,
JDIMENSION num_lines);
EXTERN(void) jpeg_crop_scanline(j_decompress_ptr cinfo, JDIMENSION *xoffset,
JDIMENSION *width);
EXTERN(boolean) jpeg_finish_decompress(j_decompress_ptr cinfo);
/* Replaces jpeg_read_scanlines when reading raw downsampled data. */
EXTERN(JDIMENSION) jpeg_read_raw_data (j_decompress_ptr cinfo, JSAMPIMAGE data,
JDIMENSION max_lines);
EXTERN(JDIMENSION) jpeg_read_raw_data(j_decompress_ptr cinfo, JSAMPIMAGE data,
JDIMENSION max_lines);
/* Additional entry points for buffered-image mode. */
EXTERN(boolean) jpeg_has_multiple_scans (const j_decompress_ptr cinfo);
EXTERN(boolean) jpeg_start_output (j_decompress_ptr cinfo, int scan_number);
EXTERN(boolean) jpeg_finish_output (j_decompress_ptr cinfo);
EXTERN(boolean) jpeg_input_complete (const j_decompress_ptr cinfo);
EXTERN(void) jpeg_new_colormap (j_decompress_ptr cinfo);
EXTERN(int) jpeg_consume_input (j_decompress_ptr cinfo);
EXTERN(boolean) jpeg_has_multiple_scans(j_decompress_ptr cinfo);
EXTERN(boolean) jpeg_start_output(j_decompress_ptr cinfo, int scan_number);
EXTERN(boolean) jpeg_finish_output(j_decompress_ptr cinfo);
EXTERN(boolean) jpeg_input_complete(j_decompress_ptr cinfo);
EXTERN(void) jpeg_new_colormap(j_decompress_ptr cinfo);
EXTERN(int) jpeg_consume_input(j_decompress_ptr cinfo);
/* Return value is one of: */
/* #define JPEG_SUSPENDED 0 Suspended due to lack of input data */
#define JPEG_REACHED_SOS 1 /* Reached start of new scan */
@@ -1075,25 +1024,25 @@ EXTERN(int) jpeg_consume_input (j_decompress_ptr cinfo);
/* Precalculate output dimensions for current decompression parameters. */
#if JPEG_LIB_VERSION >= 80
EXTERN(void) jpeg_core_output_dimensions (j_decompress_ptr cinfo);
EXTERN(void) jpeg_core_output_dimensions(j_decompress_ptr cinfo);
#endif
EXTERN(void) jpeg_calc_output_dimensions (j_decompress_ptr cinfo);
EXTERN(void) jpeg_calc_output_dimensions(j_decompress_ptr cinfo);
/* Control saving of COM and APPn markers into marker_list. */
EXTERN(void) jpeg_save_markers (j_decompress_ptr cinfo, int marker_code,
unsigned int length_limit);
EXTERN(void) jpeg_save_markers(j_decompress_ptr cinfo, int marker_code,
unsigned int length_limit);
/* Install a special processing method for COM or APPn markers. */
EXTERN(void) jpeg_set_marker_processor (j_decompress_ptr cinfo,
int marker_code,
jpeg_marker_parser_method routine);
EXTERN(void) jpeg_set_marker_processor(j_decompress_ptr cinfo,
int marker_code,
jpeg_marker_parser_method routine);
/* Read or write raw DCT coefficients --- useful for lossless transcoding. */
EXTERN(jvirt_barray_ptr *) jpeg_read_coefficients (j_decompress_ptr cinfo);
EXTERN(void) jpeg_write_coefficients (j_compress_ptr cinfo,
jvirt_barray_ptr *coef_arrays);
EXTERN(void) jpeg_copy_critical_parameters (const j_decompress_ptr srcinfo,
j_compress_ptr dstinfo);
EXTERN(jvirt_barray_ptr *) jpeg_read_coefficients(j_decompress_ptr cinfo);
EXTERN(void) jpeg_write_coefficients(j_compress_ptr cinfo,
jvirt_barray_ptr *coef_arrays);
EXTERN(void) jpeg_copy_critical_parameters(j_decompress_ptr srcinfo,
j_compress_ptr dstinfo);
/* If you choose to abort compression or decompression before completing
* jpeg_finish_(de)compress, then you need to clean up to release memory,
@@ -1101,50 +1050,23 @@ EXTERN(void) jpeg_copy_critical_parameters (const j_decompress_ptr srcinfo,
* if you're done with the JPEG object, but if you want to clean it up and
* reuse it, call this:
*/
EXTERN(void) jpeg_abort_compress (j_compress_ptr cinfo);
EXTERN(void) jpeg_abort_decompress (j_decompress_ptr cinfo);
EXTERN(void) jpeg_abort_compress(j_compress_ptr cinfo);
EXTERN(void) jpeg_abort_decompress(j_decompress_ptr cinfo);
/* Generic versions of jpeg_abort and jpeg_destroy that work on either
* flavor of JPEG object. These may be more convenient in some places.
*/
EXTERN(void) jpeg_abort (j_common_ptr cinfo);
EXTERN(void) jpeg_destroy (j_common_ptr cinfo);
EXTERN(void) jpeg_abort(j_common_ptr cinfo);
EXTERN(void) jpeg_destroy(j_common_ptr cinfo);
/* Default restart-marker-resync procedure for use by data source modules */
EXTERN(boolean) jpeg_resync_to_restart (j_decompress_ptr cinfo, int desired);
EXTERN(boolean) jpeg_resync_to_restart(j_decompress_ptr cinfo, int desired);
/* Accessor functions for extension parameters */
#define JPEG_C_PARAM_SUPPORTED 1
EXTERN(boolean) jpeg_c_bool_param_supported (const j_compress_ptr cinfo,
J_BOOLEAN_PARAM param);
EXTERN(void) jpeg_c_set_bool_param (j_compress_ptr cinfo,
J_BOOLEAN_PARAM param, boolean value);
EXTERN(boolean) jpeg_c_get_bool_param (const j_compress_ptr cinfo,
J_BOOLEAN_PARAM param);
EXTERN(boolean) jpeg_c_float_param_supported (const j_compress_ptr cinfo,
J_FLOAT_PARAM param);
EXTERN(void) jpeg_c_set_float_param (j_compress_ptr cinfo, J_FLOAT_PARAM param,
float value);
EXTERN(float) jpeg_c_get_float_param (const j_compress_ptr cinfo,
J_FLOAT_PARAM param);
EXTERN(boolean) jpeg_c_int_param_supported (const j_compress_ptr cinfo,
J_INT_PARAM param);
EXTERN(void) jpeg_c_set_int_param (j_compress_ptr cinfo, J_INT_PARAM param,
int value);
EXTERN(int) jpeg_c_get_int_param (const j_compress_ptr cinfo, J_INT_PARAM param);
/* Read ICC profile. See libjpeg.txt for usage information. */
EXTERN(boolean) jpeg_read_icc_profile(j_decompress_ptr cinfo,
JOCTET **icc_data_ptr,
unsigned int *icc_data_len);
/*
* Permit users to replace the IDCT method dynamically.
* The selector callback is called after the default idct implementation was choosen,
* and is able to override it.
*/
EXTERN(void) jpeg_set_idct_method_selector (j_decompress_ptr cinfo, jpeg_idct_method_selector selector);
/* These marker codes are exported since applications and data source modules
* are likely to want to use them.

View File

@@ -5,9 +5,8 @@
* Copyright (C) 1995-2019, Thomas G. Lane, Guido Vollbeding.
* libjpeg-turbo Modifications:
* Copyright (C) 2010, 2014, 2017, 2019-2022, D. R. Commander.
* mozjpeg Modifications:
* Copyright (C) 2014, Mozilla Corporation.
* 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 a command-line user interface for JPEG transcoding.
* It is very similar to cjpeg.c, and partly to djpeg.c, but provides
@@ -24,16 +23,6 @@
#include "jversion.h" /* for version message */
#include "jconfigint.h"
#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
/*
* Argument-parsing code.
@@ -51,11 +40,8 @@ static char *outfilename; /* for -outfile switch */
static char *dropfilename; /* for -drop switch */
boolean report; /* for -report switch */
boolean strict; /* for -strict switch */
static boolean prefer_smallest; /* use smallest of input or result file (if no image-changing options supplied) */
static JCOPY_OPTION copyoption; /* -copy switch */
static jpeg_transform_info transformoption; /* image transformation options */
boolean memsrc = FALSE; /* for -memsrc switch */
#define INPUT_BUF_SIZE 4096
LOCAL(void)
@@ -75,13 +61,11 @@ usage(void)
fprintf(stderr, " -copy icc Copy only ICC profile markers\n");
fprintf(stderr, " -copy all Copy all extra markers\n");
#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
#ifdef C_PROGRESSIVE_SUPPORTED
fprintf(stderr, " -progressive Create progressive JPEG file (enabled by default)\n");
fprintf(stderr, " -progressive Create progressive JPEG file\n");
#endif
fprintf(stderr, " -revert Revert to standard defaults (instead of mozjpeg defaults)\n");
fprintf(stderr, " -fastcrush Disable progressive scan optimization\n");
fprintf(stderr, "Switches for modifying the image:\n");
#if TRANSFORMS_SUPPORTED
fprintf(stderr, " -crop WxH+X+Y Crop to a rectangular region\n");
@@ -160,11 +144,7 @@ parse_switches(j_compress_ptr cinfo, int argc, char **argv,
char *scansarg = NULL; /* saves -scans parm if any */
/* Set up default JPEG parameters. */
#ifdef C_PROGRESSIVE_SUPPORTED
simple_progressive = cinfo->num_scans == 0 ? FALSE : TRUE;
#else
simple_progressive = FALSE;
#endif
icc_filename = NULL;
max_scans = 0;
outfilename = NULL;
@@ -178,7 +158,6 @@ parse_switches(j_compress_ptr cinfo, int argc, char **argv,
transformoption.crop = FALSE;
transformoption.slow_hflip = FALSE;
cinfo->err->trace_level = 0;
prefer_smallest = TRUE;
/* Scan command line options, adjust parameters */
@@ -198,10 +177,6 @@ parse_switches(j_compress_ptr cinfo, int argc, char **argv,
/* Use arithmetic coding. */
#ifdef C_ARITH_CODING_SUPPORTED
cinfo->arith_code = TRUE;
/* No table optimization required for AC */
cinfo->optimize_coding = FALSE;
prefer_smallest = FALSE;
#else
fprintf(stderr, "%s: sorry, arithmetic coding not supported\n",
progname);
@@ -234,7 +209,6 @@ parse_switches(j_compress_ptr cinfo, int argc, char **argv,
progname, argv[argn]);
exit(EXIT_FAILURE);
}
prefer_smallest = FALSE;
#else
select_transform(JXFORM_NONE); /* force an error */
#endif
@@ -290,16 +264,11 @@ parse_switches(j_compress_ptr cinfo, int argc, char **argv,
else
usage();
prefer_smallest = FALSE;
} else if (keymatch(arg, "fastcrush", 4)) {
jpeg_c_set_bool_param(cinfo, JBOOLEAN_OPTIMIZE_SCANS, FALSE);
} else if (keymatch(arg, "grayscale", 1) || keymatch(arg, "greyscale",1)) {
} else if (keymatch(arg, "grayscale", 1) ||
keymatch(arg, "greyscale", 1)) {
/* Force to grayscale. */
#if TRANSFORMS_SUPPORTED
transformoption.force_grayscale = TRUE;
prefer_smallest = FALSE;
#else
select_transform(JXFORM_NONE); /* force an error */
#endif
@@ -354,7 +323,6 @@ parse_switches(j_compress_ptr cinfo, int argc, char **argv,
/* Select simple progressive mode. */
#ifdef C_PROGRESSIVE_SUPPORTED
simple_progressive = TRUE;
prefer_smallest = FALSE;
/* We must postpone execution until num_components is known. */
#else
fprintf(stderr, "%s: sorry, progressive output was not compiled\n",
@@ -384,11 +352,6 @@ parse_switches(j_compress_ptr cinfo, int argc, char **argv,
/* 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);
prefer_smallest = FALSE;
} else if (keymatch(arg, "rotate", 2)) {
/* Rotate 90, 180, or 270 degrees (measured clockwise). */
if (++argn >= argc) /* advance to next argument */
@@ -402,14 +365,11 @@ parse_switches(j_compress_ptr cinfo, int argc, char **argv,
else
usage();
prefer_smallest = FALSE;
} else if (keymatch(arg, "scans", 1)) {
/* Set scan script. */
#ifdef C_MULTISCAN_FILES_SUPPORTED
if (++argn >= argc) /* advance to next argument */
usage();
prefer_smallest = FALSE;
scansarg = argv[argn];
/* We must postpone reading the file in case -progressive appears. */
#else
@@ -424,17 +384,14 @@ parse_switches(j_compress_ptr cinfo, int argc, char **argv,
} else if (keymatch(arg, "transpose", 1)) {
/* Transpose (across UL-to-LR axis). */
select_transform(JXFORM_TRANSPOSE);
prefer_smallest = FALSE;
} else if (keymatch(arg, "transverse", 6)) {
/* Transverse transpose (across UR-to-LL axis). */
select_transform(JXFORM_TRANSVERSE);
prefer_smallest = FALSE;
} else if (keymatch(arg, "trim", 3)) {
/* Trim off any partial edge MCUs that the transform can't handle. */
transformoption.trim = TRUE;
prefer_smallest = FALSE;
} else if (keymatch(arg, "wipe", 1)) {
#if TRANSFORMS_SUPPORTED
@@ -512,19 +469,10 @@ main(int argc, char **argv)
* single file pointer for sequential input and output operation.
*/
FILE *fp;
unsigned char *inbuffer = NULL;
unsigned long insize = 0;
unsigned char *outbuffer = NULL;
unsigned long outsize = 0;
FILE *icc_file;
JOCTET *icc_profile = NULL;
long icc_len = 0;
/* On Mac, fetch a command line. */
#ifdef USE_CCOMMAND
argc = ccommand(&argv);
#endif
progname = argv[0];
if (progname == NULL || progname[0] == 0)
progname = "jpegtran"; /* in case C library doesn't provide it */
@@ -644,32 +592,6 @@ main(int argc, char **argv)
#endif
/* Specify data source for decompression */
if (jpeg_c_int_param_supported(&dstinfo, JINT_COMPRESS_PROFILE) &&
jpeg_c_get_int_param(&dstinfo, JINT_COMPRESS_PROFILE)
== JCP_MAX_COMPRESSION)
memsrc = TRUE; /* needed to revert to original */
#if JPEG_LIB_VERSION >= 80 || defined(MEM_SRCDST_SUPPORTED)
if (memsrc) {
size_t nbytes;
do {
inbuffer = (unsigned char *)realloc(inbuffer, insize + INPUT_BUF_SIZE);
if (inbuffer == NULL) {
fprintf(stderr, "%s: memory allocation failure\n", progname);
exit(EXIT_FAILURE);
}
nbytes = fread(&inbuffer[insize], 1, INPUT_BUF_SIZE, fp);
if (nbytes < INPUT_BUF_SIZE && ferror(fp)) {
if (file_index < argc)
fprintf(stderr, "%s: can't read from %s\n", progname,
argv[file_index]);
else
fprintf(stderr, "%s: can't read from stdin\n", progname);
}
insize += (unsigned long)nbytes;
} while (nbytes == INPUT_BUF_SIZE);
jpeg_mem_src(&srcinfo, inbuffer, insize);
} else
#endif
jpeg_stdio_src(&srcinfo, fp);
/* Enable saving of extra markers that we want to copy */
@@ -750,13 +672,6 @@ main(int argc, char **argv)
file_index = parse_switches(&dstinfo, argc, argv, 0, TRUE);
/* Specify data destination for compression */
#if JPEG_LIB_VERSION >= 80 || defined(MEM_SRCDST_SUPPORTED)
if (jpeg_c_int_param_supported(&dstinfo, JINT_COMPRESS_PROFILE) &&
jpeg_c_get_int_param(&dstinfo, JINT_COMPRESS_PROFILE)
== JCP_MAX_COMPRESSION)
jpeg_mem_dest(&dstinfo, &outbuffer, &outsize);
else
#endif
jpeg_stdio_dest(&dstinfo, fp);
/* Start compressor (note no image data is actually written here) */
@@ -776,41 +691,15 @@ main(int argc, char **argv)
/* Finish compression and release memory */
jpeg_finish_compress(&dstinfo);
#if JPEG_LIB_VERSION >= 80 || defined(MEM_SRCDST_SUPPORTED)
if (jpeg_c_int_param_supported(&dstinfo, JINT_COMPRESS_PROFILE) &&
jpeg_c_get_int_param(&dstinfo, JINT_COMPRESS_PROFILE)
== JCP_MAX_COMPRESSION) {
size_t nbytes;
unsigned char *buffer = outbuffer;
unsigned long size = outsize;
if (prefer_smallest && insize < size) {
size = insize;
buffer = inbuffer;
}
nbytes = fwrite(buffer, 1, size, fp);
if (nbytes < size && ferror(fp)) {
if (file_index < argc)
fprintf(stderr, "%s: can't write to %s\n", progname,
argv[file_index]);
else
fprintf(stderr, "%s: can't write to stdout\n", progname);
}
}
#endif
jpeg_destroy_compress(&dstinfo);
(void)jpeg_finish_decompress(&srcinfo);
jpeg_destroy_decompress(&srcinfo);
#if TRANSFORMS_SUPPORTED
if (dropfilename != NULL) {
(void)jpeg_finish_decompress(&dropinfo);
jpeg_destroy_decompress(&dropinfo);
}
#endif
(void)jpeg_finish_decompress(&srcinfo);
jpeg_destroy_decompress(&srcinfo);
/* Close output file, if we opened it */
if (fp != stdout)
@@ -825,9 +714,6 @@ main(int argc, char **argv)
if (report || max_scans != 0)
end_progress_monitor((j_common_ptr)&srcinfo);
free(inbuffer);
free(outbuffer);
free(icc_profile);
/* All done. */

172
jpegyuv.c
View File

@@ -1,172 +0,0 @@
/*
* Written by Josh Aas and Tim Terriberry
* Copyright (c) 2013, Mozilla Corporation
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. 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.
* 3. Neither the name of the Mozilla Corporation 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 HOLDER 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.
*/
/* Input: JPEG YUV 4:2:0 */
/* Output: YUV 4:2:0 */
/* gcc -std=c99 jpegyuv.c -I/opt/local/include/ -L/opt/local/lib/ -ljpeg -o jpegyuv */
#include <stdio.h>
#include <stdlib.h>
#include "jpeglib.h"
int main(int argc, char *argv[]) {
const char *jpg_path;
const char *yuv_path;
struct jpeg_decompress_struct cinfo;
struct jpeg_error_mgr jerr;
FILE *jpg_fd;
int luma_width;
int luma_height;
int chroma_width;
int chroma_height;
int frame_width;
int yuv_size;
JSAMPLE *jpg_buffer;
JSAMPROW yrow_pointer[16];
JSAMPROW cbrow_pointer[8];
JSAMPROW crrow_pointer[8];
JSAMPROW *plane_pointer[3];
unsigned char *yuv_buffer;
int x;
int y;
FILE *yuv_fd;
if (argc != 3) {
fprintf(stderr, "Required arguments:\n");
fprintf(stderr, "1. Path to JPG input file\n");
fprintf(stderr, "2. Path to YUV output file\n");
return 1;
}
/* Will check these for validity when opening via 'fopen'. */
jpg_path = argv[1];
yuv_path = argv[2];
cinfo.err = jpeg_std_error(&jerr);
jpeg_create_decompress(&cinfo);
jpg_fd = fopen(jpg_path, "rb");
if (!jpg_fd) {
fprintf(stderr, "Invalid path to JPEG file!\n");
return 1;
}
jpeg_stdio_src(&cinfo, jpg_fd);
jpeg_read_header(&cinfo, TRUE);
cinfo.raw_data_out = TRUE;
cinfo.do_fancy_upsampling = FALSE;
jpeg_start_decompress(&cinfo);
luma_width = cinfo.output_width;
luma_height = cinfo.output_height;
chroma_width = (luma_width + 1) >> 1;
chroma_height = (luma_height + 1) >> 1;
yuv_size = luma_width*luma_height + 2*chroma_width*chroma_height;
yuv_buffer = malloc(yuv_size);
if (!yuv_buffer) {
fclose(jpg_fd);
fprintf(stderr, "Memory allocation failure!\n");
return 1;
}
frame_width = (cinfo.output_width + (16 - 1)) & ~(16 - 1);
jpg_buffer = malloc(frame_width*16 + 2*(frame_width/2)*8);
if (!jpg_buffer) {
fclose(jpg_fd);
free(yuv_buffer);
fprintf(stderr, "Memory allocation failure!\n");
return 1;
}
plane_pointer[0] = yrow_pointer;
plane_pointer[1] = cbrow_pointer;
plane_pointer[2] = crrow_pointer;
for (y = 0; y < 16; y++) {
yrow_pointer[y] = &jpg_buffer[frame_width*y];
}
for (y = 0; y < 8; y++) {
cbrow_pointer[y] = &jpg_buffer[frame_width*16 + (frame_width/2)*y];
crrow_pointer[y] = &jpg_buffer[frame_width*16 + (frame_width/2)*(8 + y)];
}
while (cinfo.output_scanline < cinfo.output_height) {
int luma_scanline;
int chroma_scanline;
luma_scanline = cinfo.output_scanline;
chroma_scanline = (luma_scanline + 1) >> 1;
jpeg_read_raw_data(&cinfo, plane_pointer, 16);
for (y = 0; y < 16 && luma_scanline + y < luma_height; y++) {
for (x = 0; x < luma_width; x++) {
yuv_buffer[luma_width*(luma_scanline + y) + x] = yrow_pointer[y][x];
}
}
for (y = 0; y < 8 && chroma_scanline + y < chroma_height; y++) {
for (x = 0; x < chroma_width; x++) {
yuv_buffer[luma_width*luma_height +
chroma_width*(chroma_scanline + y) + x] = cbrow_pointer[y][x];
yuv_buffer[luma_width*luma_height + chroma_width*chroma_height +
chroma_width*(chroma_scanline + y) + x] = crrow_pointer[y][x];
}
}
}
jpeg_finish_decompress(&cinfo);
jpeg_destroy_decompress(&cinfo);
fclose(jpg_fd);
free(jpg_buffer);
yuv_fd = fopen(yuv_path, "wb");
if (!yuv_fd) {
fprintf(stderr, "Invalid path to YUV file!");
free(yuv_buffer);
return 1;
}
if (fwrite(yuv_buffer, yuv_size, 1, yuv_fd) != 1) {
fprintf(stderr, "Error writing yuv file\n");
}
fclose(yuv_fd);
free(yuv_buffer);
return 0;
}

View File

@@ -5,9 +5,8 @@
* Copyright (C) 1991-2020, Thomas G. Lane, Guido Vollbeding.
* libjpeg-turbo Modifications:
* Copyright (C) 2010, 2012-2022, D. R. Commander.
* mozjpeg Modifications:
* Copyright (C) 2014, Mozilla Corporation.
* 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 software version identification.
*/

View File

@@ -3,7 +3,7 @@ USING THE IJG JPEG LIBRARY
This file was part of the Independent JPEG Group's software:
Copyright (C) 1994-2013, Thomas G. Lane, Guido Vollbeding.
libjpeg-turbo Modifications:
Copyright (C) 2010, 2014-2018, 2020, D. R. Commander.
Copyright (C) 2010, 2014-2018, 2020, 2022, D. R. Commander.
Copyright (C) 2015, Google, Inc.
For conditions of distribution and use, see the accompanying README.ijg file.
@@ -840,18 +840,7 @@ is to prepare a library file ("libjpeg.a", or a corresponding name on non-Unix
machines) and reference it at your link step. If you use only half of the
library (only compression or only decompression), only that much code will be
included from the library, unless your linker is hopelessly brain-damaged.
The supplied makefiles build libjpeg.a automatically (see install.txt).
While you can build the JPEG library as a shared library if the whim strikes
you, we don't really recommend it. The trouble with shared libraries is that
at some point you'll probably try to substitute a new version of the library
without recompiling the calling applications. That generally doesn't work
because the parameter struct declarations usually change with each new
version. In other words, the library's API is *not* guaranteed binary
compatible across versions; we only try to ensure source-code compatibility.
(In hindsight, it might have been smarter to hide the parameter structs from
applications and introduce a ton of access functions instead. Too late now,
however.)
The supplied build system builds libjpeg.a automatically.
It may be worth pointing out that the core JPEG library does not actually
require the stdio library: only the default source/destination managers and
@@ -3075,9 +3064,8 @@ BITS_IN_JSAMPLE as 12 rather than 8. Note that this causes JSAMPLE to be
larger than a char, so it affects the surrounding application's image data.
The sample applications cjpeg and djpeg can support 12-bit mode only for PPM
and GIF file formats; you must disable the other file formats to compile a
12-bit cjpeg or djpeg. (install.txt has more information about that.)
At present, a 12-bit library can handle *only* 12-bit images, not both
precisions.
12-bit cjpeg or djpeg. At present, a 12-bit library can handle *only* 12-bit
images, not both precisions.
Note that a 12-bit library always compresses in Huffman optimization mode,
in order to generate valid Huffman tables. This is necessary because our

View File

@@ -1,158 +0,0 @@
Pod::Spec.new do |spec|
spec.name = "mozjpeg"
spec.version = "3.3.1"
spec.license = { :type => "BSD" }
spec.homepage = "https://github.com/mozilla/mozjpeg"
spec.summary = "Improved JPEG encoder."
spec.authors = "Mozilla"
spec.source = { :git => "https://github.com/mozilla/mozjpeg.git", :tag => "v#{spec.version}" }
spec.module_name = "mozjpeg"
spec.header_dir = "mozjpeg"
spec.platforms = { :ios => "8.0" }
spec.prepare_command = <<-CMD
cat << EOF > jconfig.h
#define JPEG_LIB_VERSION 80 /* Version 6b */
#define LIBJPEG_TURBO_VERSION 3.1.m
#define LIBJPEG_TURBO_VERSION_NUMBER 1
#define C_ARITH_CODING_SUPPORTED 1
#define D_ARITH_CODING_SUPPORTED 1
#define BITS_IN_JSAMPLE 8
#define HAVE_LOCALE_H 1
#define HAVE_STDDEF_H 1
#define HAVE_STDLIB_H 1
#define HAVE_UNSIGNED_CHAR 1
#define HAVE_UNSIGNED_SHORT 1
#define NEED_SYS_TYPES_H 1
#define WITH_SIMD 0
EOF
cat << EOF > jconfigint.h
#define BUILD "20180328"
#define INLINE __attribute__((always_inline))
#define PACKAGE_NAME "mozjpeg"
#define VERSION "#{spec.version}"
#ifdef __SIZEOF_SIZE_T__
#define SIZEOF_SIZE_T __SIZEOF_SIZE_T__
#else
#error Cannot determine the size of size_t
#endif
EOF
CMD
spec.private_header_files = "bmp.h",
"cderror.h",
"cdjpeg.h",
"jchuff.h",
"jcmaster.h",
"jconfigint.h",
"jdcoefct.h",
"jdct.h",
"jdhuff.h",
"jdmainct.h",
"jdmaster.h",
"jdsample.h",
"jmemsys.h",
"jpeg_nbits_table.h",
"jpegcomp.h",
"jsimd.h",
"jsimddct.h",
"jversion.h",
"wrppm.h"
spec.public_header_files = "jerror.h",
"jinclude.h",
"jconfig.h",
"jmorecfg.h",
"jpeglib.h",
"jpegint.h",
"transupp.h"
spec.source_files = "jcapimin.c",
"jcapistd.c",
"jccoefct.c",
"jccolor.c",
"jcdctmgr.c",
"jcext.c",
"jchuff.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",
"jdatasrc.c",
"jdcoefct.c",
"jdcolor.c",
"jddctmgr.c",
"jdhuff.c",
"jdinput.c",
"jdmainct.c",
"jdmarker.c",
"jdmaster.c",
"jdmerge.c",
"jdphuff.c",
"jdpostct.c",
"jdsample.c",
"jdtrans.c",
"jerror.c",
"jfdctflt.c",
"jfdctfst.c",
"jfdctint.c",
"jidctflt.c",
"jidctfst.c",
"jidctint.c",
"jidctred.c",
"jquant1.c",
"jquant2.c",
"jutils.c",
"jmemmgr.c",
"jaricom.c",
"jcarith.c",
"jdarith.c",
"transupp.c",
"jmemnobs.c",
"jsimd_none.c",
"jerror.h",
"jinclude.h",
"jconfig.h",
"jmorecfg.h",
"jpeglib.h",
"jpegint.h",
"transupp.h",
"bmp.h",
"cderror.h",
"cdjpeg.h",
"jchuff.h",
"jcmaster.h",
"jconfigint.h",
"jdcoefct.h",
"jdct.h",
"jdhuff.h",
"jdmainct.h",
"jdmaster.h",
"jdsample.h",
"jmemsys.h",
"jpeg_nbits_table.h",
"jpegcomp.h",
"jsimd.h",
"jsimddct.h",
"jversion.h",
"wrppm.h"
# Despite their extensions, these are header files that shouldn't be compiled
# on their own but should still be present for other files to include.
spec.preserve_path = "jdcolext.c",
"jstdhuff.c",
"jdcol565.c",
"jdmrgext.c",
"jdmrg565.c",
"jccolext.c"
end

View File

@@ -1,15 +0,0 @@
#!/bin/bash
set -e
if [ $# == 0 ]; then
echo "usage: OUTPUT=<label> $0 *.out"
exit 1
fi
TOTAL=total.out
if [ -n "$OUTPUT" ]; then
TOTAL="$OUTPUT.out"
fi
awk '{size[FNR]+=$2;bytes[FNR]+=$3;psnr[FNR]+=$2*$4;psnrhvs[FNR]+=$2*$5;ssim[FNR]+=$2*$6;fastssim[FNR]+=$2*$7;}END{for(i=1;i<=FNR;i++)print i-1,size[i],bytes[i],psnr[i]/size[i],psnrhvs[i]/size[i],ssim[i]/size[i],fastssim[i]/size[i];}' $@ > $TOTAL

View File

@@ -1,106 +0,0 @@
#!/bin/bash
set -e
if [ $# == 0 ]; then
echo "usage: DAALA_ROOT=<daala_root> MOZJPEG_ROOT=<mozjpeg_root> $0 *.y4m"
exit 1
fi
if [ -z $MOZJPEG_ROOT ]; then
MOZJPEG_ROOT=.
fi
if [ -z $DAALA_ROOT ]; then
echo "DAALA_ROOT not set."
exit 1
fi
if [ -z "$PLANE" ]; then
export PLANE=0
fi
if [ $PLANE != 0 ] && [ $PLANE != 1 ] && [ $PLANE != 2 ]; then
echo "Invalid plane $PLANE. Must be 0, 1 or 2."
exit 1
fi
if [ -z "$YUVJPEG" ]; then
export YUVJPEG=$MOZJPEG_ROOT/yuvjpeg
fi
if [ -z "$JPEGYUV" ]; then
export JPEGYUV=$MOZJPEG_ROOT/jpegyuv
fi
if [ ! -x "$YUVJPEG" ]; then
echo "Executable not found YUVJPEG=$YUVJPEG"
echo "Do you have the right MOZJPEG_ROOT=$MOZJPEG_ROOT"
exit 1
fi
if [ ! -x "$JPEGYUV" ]; then
echo "Executable not found JPEGYUV=$JPEGYUV"
echo "Do you have the right MOZJPEG_ROOT=$MOZJPEG_ROOT"
exit 1
fi
# TODO refactor these out of the daala project into a metrics project
if [ -z "$YUV2YUV4MPEG" ]; then
export YUV2YUV4MPEG=$DAALA_ROOT/tools/yuv2yuv4mpeg
fi
if [ -z "$DUMP_PSNR" ]; then
export DUMP_PSNR=$DAALA_ROOT/tools/dump_psnr
fi
if [ -z "$DUMP_PSNRHVS" ]; then
export DUMP_PSNRHVS=$DAALA_ROOT/tools/dump_psnrhvs
fi
if [ -z "$DUMP_SSIM" ]; then
export DUMP_SSIM=$DAALA_ROOT/tools/dump_ssim
fi
if [ -z "$DUMP_FASTSSIM" ]; then
export DUMP_FASTSSIM=$DAALA_ROOT/tools/dump_fastssim
fi
if [ ! -x "$YUV2YUV4MPEG" ]; then
echo "Executable not found YUV2YUV4MPEG=$YUV2YUV4MPEG"
echo "Do you have the right DAALA_ROOT=$DAALA_ROOT"
exit 1
fi
if [ ! -x "$DUMP_PSNR" ]; then
echo "Executable not found DUMP_PSNR=$DUMP_PSNR"
echo "Do you have the right DAALA_ROOT=$DAALA_ROOT"
exit 1
fi
if [ ! -x "$DUMP_PSNRHVS" ]; then
echo "Executable not found DUMP_PSNRHVS=$DUMP_PSNRHVS"
echo "Do you have the right DAALA_ROOT=$DAALA_ROOT"
exit 1
fi
if [ ! -x "$DUMP_SSIM" ]; then
echo "Executable not found DUMP_SSIM=$DUMP_SSIM"
echo "Do you have the right DAALA_ROOT=$DAALA_ROOT"
exit 1
fi
if [ ! -x "$DUMP_FASTSSIM" ]; then
echo "Executable not found DUMP_FASTSSIM=$DUMP_FASTSSIM"
echo "Do you have the right DAALA_ROOT=$DAALA_ROOT"
exit 1
fi
RD_COLLECT_SUB=$(dirname "$0")/rd_collect_sub.sh
if [ -z "$CORES" ]; then
CORES=`grep -i processor /proc/cpuinfo | wc -l`
#echo "CORES not set, using $CORES"
fi
find $@ -type f -name "*.y4m" -print0 | xargs -0 -n1 -P$CORES $RD_COLLECT_SUB

View File

@@ -1,28 +0,0 @@
#!/bin/bash
set -e
FILE=$1
BASENAME=$(basename $FILE)
rm $BASENAME.out 2> /dev/null || true
echo $BASENAME
tail -n+3 $FILE > $BASENAME-in.yuv
WIDTH=$(head -1 $FILE | cut -d\ -f 2 | tr -d 'W')
HEIGHT=$(head -1 $FILE | cut -d\ -f 3 | tr -d 'H')
for x in {0..100}; do
$YUVJPEG $x "$WIDTH"x$HEIGHT $BASENAME-in.yuv $BASENAME.jpeg
$JPEGYUV $BASENAME.jpeg $BASENAME.yuv
$YUV2YUV4MPEG $BASENAME -w$WIDTH -h$HEIGHT -an0 -ad0 -c420mpeg2
PIXELS=$(($WIDTH*$HEIGHT))
SIZE=$(wc -c $BASENAME.jpeg | awk '{ print $1 }')
PSNR=$($DUMP_PSNR $FILE $BASENAME.y4m 2> /dev/null | grep Total | tr -s ' ' | cut -d\ -f $((4+$PLANE*2)))
PSNRHVS=$($DUMP_PSNRHVS $FILE $BASENAME.y4m 2> /dev/null | grep Total | tr -s ' ' | cut -d\ -f $((4+$PLANE*2)))
SSIM=$($DUMP_SSIM $FILE $BASENAME.y4m 2> /dev/null | grep Total | tr -s ' ' | cut -d\ -f $((4+$PLANE*2)))
FASTSSIM=$($DUMP_FASTSSIM -c $FILE $BASENAME.y4m 2> /dev/null | grep Total | tr -s ' ' | cut -d\ -f $((4+$PLANE*2)))
rm $BASENAME.jpeg $BASENAME.yuv $BASENAME.y4m
echo $x $PIXELS $SIZE $PSNR $PSNRHVS $SSIM $FASTSSIM >> $BASENAME.out
#tail -1 $BASENAME.out
done
rm $BASENAME-in.yuv

View File

@@ -1,47 +0,0 @@
#!/bin/bash
set -e
# Use this to average data from multiple runs
#awk '{size[FNR]+=$2;bytes[FNR]+=$3;psnr[FNR]+=$2*$4;psnrhvs[FNR]+=$2*$5;ssim[FNR]+=$2*$6;fastssim[FNR]+=$2*$7;}END{for(i=1;i<=FNR;i++)print i+1,size[i],bytes[i],psnr[i]/size[i],psnrhvs[i]/size[i],ssim[i]/size[i],fastssim[i]/size[i];}' *.out > total.out
if [ -n "$IMAGE" ]; then
IMAGE="$IMAGE-"
fi
if [ $# == 0 ]; then
echo "usage: IMAGE=<prefix> $0 *.out"
exit 1
fi
if [ -z "$GNUPLOT" -a -n "`type -p gnuplot`" ]; then
GNUPLOT=`type -p gnuplot`
fi
if [ ! -x "$GNUPLOT" ]; then
echo "Executable not found GNUPLOT=$GNUPLOT"
echo "Please install it or set GNUPLOT to point to an installed copy"
exit 1
fi
CMDS="$CMDS set term pngcairo dashed size 1024,768;"
CMDS="$CMDS set log x;"
CMDS="$CMDS set xlabel 'Bits/Pixel';"
CMDS="$CMDS set ylabel 'dB';"
CMDS="$CMDS set key bot right;"
for FILE in "$@"; do
BASENAME=$(basename $FILE)
PSNR="$PSNR $PREFIX '$FILE' using (\$3*8/\$2):4 with lines title '${BASENAME%.*} (PSNR)'"
PSNRHVS="$PSNRHVS $PREFIX '$FILE' using (\$3*8/\$2):5 with lines title '${BASENAME%.*} (PSNR-HVS)'"
SSIM="$SSIM $PREFIX '$FILE' using (\$3*8/\$2):6 with lines title '${BASENAME%.*} (SSIM)'"
FASTSSIM="$FASTSSIM $PREFIX '$FILE' using (\$3*8/\$2):7 with lines title '${BASENAME%.*} (FAST SSIM)'"
PREFIX=","
done
SUFFIX="psnr.png"
$GNUPLOT -e "$CMDS set output \"$IMAGE$SUFFIX\"; plot $PSNR;" 2> /dev/null
SUFFIX="psnrhvs.png"
$GNUPLOT -e "$CMDS set output \"$IMAGE$SUFFIX\"; plot $PSNRHVS;" 2> /dev/null
SUFFIX="ssim.png"
$GNUPLOT -e "$CMDS set output \"$IMAGE$SUFFIX\"; plot $SSIM;" 2> /dev/null
SUFFIX="fastssim.png"
$GNUPLOT -e "$CMDS set output \"$IMAGE$SUFFIX\"; plot $FASTSSIM;" 2> /dev/null

View File

@@ -521,7 +521,7 @@ start_input_bmp(j_compress_ptr cinfo, cjpeg_source_ptr sinfo)
return;
}
if (biWidth <= 0 || biHeight <= 0 || biWidth > 0x7fffffffL || biHeight > 0x7fffffffL)
if (biWidth <= 0 || biHeight <= 0)
ERREXIT(cinfo, JERR_BMP_EMPTY);
#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
if (sinfo->max_pixels &&

160
rdjpeg.c
View File

@@ -1,160 +0,0 @@
/*
* rdjpeg.c
*
* Copyright (C) 1991-1996, Thomas G. Lane.
* mozjpeg Modifications:
* Copyright (C) 2014, Mozilla Corporation.
* This file is part of the Independent JPEG Group's software.
* For conditions of distribution and use, see the accompanying README file.
*
*/
#include "cdjpeg.h" /* Common decls for cjpeg/djpeg applications */
#if JPEG_RAW_READER
#define NUM_ROWS 32
#endif
/* Private version of data source object */
typedef struct _jpeg_source_struct * jpeg_source_ptr;
typedef struct _jpeg_source_struct {
struct cjpeg_source_struct pub; /* public fields */
j_compress_ptr cinfo; /* back link saves passing separate parm */
struct jpeg_decompress_struct dinfo;
struct jpeg_error_mgr jerr;
} jpeg_source_struct;
METHODDEF(JDIMENSION)
get_rows (j_compress_ptr cinfo, cjpeg_source_ptr sinfo)
{
jpeg_source_ptr source = (jpeg_source_ptr) sinfo;
#if !JPEG_RAW_READER
return jpeg_read_scanlines(&source->dinfo, source->pub.buffer, source->pub.buffer_height);
#else
jpeg_read_raw_data(&source->dinfo, source->pub.plane_pointer, 8*cinfo->max_v_samp_factor);
return 8*cinfo->max_v_samp_factor;
#endif
}
/*
* Read the file header; return image size and component count.
*/
METHODDEF(void)
start_input_jpeg (j_compress_ptr cinfo, cjpeg_source_ptr sinfo)
{
#if JPEG_RAW_READER
int i;
#endif
int m;
jpeg_source_ptr source = (jpeg_source_ptr) sinfo;
source->dinfo.err = jpeg_std_error(&source->jerr);
jpeg_create_decompress(&source->dinfo);
jpeg_stdio_src(&source->dinfo, source->pub.input_file);
jpeg_save_markers(&source->dinfo, JPEG_COM, 0xFFFF);
for (m = 0; m < 16; m++)
jpeg_save_markers(&source->dinfo, JPEG_APP0 + m, 0xFFFF);
jpeg_read_header(&source->dinfo, TRUE);
source->pub.marker_list = source->dinfo.marker_list;
#if !JPEG_RAW_READER
source->dinfo.raw_data_out = FALSE;
jpeg_start_decompress(&source->dinfo);
cinfo->in_color_space = source->dinfo.out_color_space;
cinfo->input_components = source->dinfo.output_components;
cinfo->data_precision = source->dinfo.data_precision;
cinfo->image_width = source->dinfo.image_width;
cinfo->image_height = source->dinfo.image_height;
cinfo->raw_data_in = FALSE;
source->pub.buffer = (*cinfo->mem->alloc_sarray)
((j_common_ptr) cinfo, JPOOL_IMAGE,
(JDIMENSION) (cinfo->image_width * cinfo->input_components), (JDIMENSION) 1);
source->pub.buffer_height = 1;
#else
source->dinfo.raw_data_out = TRUE;
source->dinfo.do_fancy_upsampling = FALSE;
jpeg_start_decompress(&source->dinfo);
cinfo->in_color_space = source->dinfo.out_color_space;
cinfo->input_components = source->dinfo.output_components;
cinfo->data_precision = source->dinfo.data_precision;
cinfo->image_width = source->dinfo.image_width;
cinfo->image_height = source->dinfo.image_height;
jpeg_set_colorspace(cinfo, source->dinfo.jpeg_color_space);
cinfo->max_v_samp_factor = source->dinfo.max_v_samp_factor;
cinfo->max_h_samp_factor = source->dinfo.max_h_samp_factor;
cinfo->raw_data_in = TRUE;
#if JPEG_LIB_VERSION >= 70
cinfo->do_fancy_upsampling = FALSE;
#endif
for (i = 0; i < cinfo->input_components; i++) {
cinfo->comp_info[i].h_samp_factor = source->dinfo.comp_info[i].h_samp_factor;
cinfo->comp_info[i].v_samp_factor = source->dinfo.comp_info[i].v_samp_factor;
source->pub.plane_pointer[i] = (*cinfo->mem->alloc_sarray)
((j_common_ptr) cinfo, JPOOL_IMAGE,
(JDIMENSION) cinfo->image_width, (JDIMENSION) NUM_ROWS);
}
#endif
source->pub.get_pixel_rows = get_rows;
}
/*
* Finish up at the end of the file.
*/
METHODDEF(void)
finish_input_jpeg (j_compress_ptr cinfo, cjpeg_source_ptr sinfo)
{
jpeg_source_ptr source = (jpeg_source_ptr) sinfo;
jpeg_finish_decompress(&source->dinfo);
jpeg_destroy_decompress(&source->dinfo);
}
/*
* The module selection routine for JPEG format input.
*/
GLOBAL(cjpeg_source_ptr)
jinit_read_jpeg (j_compress_ptr cinfo)
{
jpeg_source_ptr source;
/* Create module interface object */
source = (jpeg_source_ptr)
(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
sizeof(jpeg_source_struct));
source->cinfo = cinfo; /* make back link for subroutines */
/* Fill in method ptrs, except get_pixel_rows which start_input sets */
source->pub.start_input = start_input_jpeg;
source->pub.finish_input = finish_input_jpeg;
return (cjpeg_source_ptr) source;
}

View File

@@ -30,16 +30,6 @@
#include <io.h> /* to declare setmode() */
#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
#ifdef DONT_USE_B_MODE /* define mode parameters for fopen() */
#define READ_BINARY "r"
#else
@@ -120,7 +110,6 @@ read_2_bytes(void)
#define M_SOI 0xD8 /* Start Of Image (beginning of datastream) */
#define M_EOI 0xD9 /* End Of Image (end of datastream) */
#define M_SOS 0xDA /* Start Of Scan (begins compressed data) */
#define M_APP0 0xE0 /* Application-specific marker, type N */
#define M_APP12 0xEC /* (we don't bother to list all 16 APPn's) */
#define M_COM 0xFE /* COMment */
@@ -451,11 +440,6 @@ main(int argc, char **argv)
char *arg;
int verbose = 0, raw = 0;
/* On Mac, fetch a command line. */
#ifdef USE_CCOMMAND
argc = ccommand(&argv);
#endif
progname = argv[0];
if (progname == NULL || progname[0] == 0)
progname = "rdjpgcom"; /* in case C library doesn't provide it */

194
rdpng.c
View File

@@ -1,194 +0,0 @@
#include "cdjpeg.h" /* Common decls for cjpeg/djpeg applications */
#ifdef PNG_SUPPORTED
#include <png.h> /* if this fails, you need to install libpng-devel */
typedef struct png_source_struct {
struct cjpeg_source_struct pub;
png_structp png_ptr;
png_infop info_ptr;
JDIMENSION current_row;
} png_source_struct;
METHODDEF(void)
finish_input_png (j_compress_ptr cinfo, cjpeg_source_ptr sinfo);
METHODDEF(JDIMENSION)
get_pixel_rows_png (j_compress_ptr cinfo, cjpeg_source_ptr sinfo);
METHODDEF(void)
start_input_png (j_compress_ptr cinfo, cjpeg_source_ptr sinfo);
GLOBAL(cjpeg_source_ptr)
jinit_read_png(j_compress_ptr cinfo)
{
png_source_struct *source = (*cinfo->mem->alloc_small)((j_common_ptr) cinfo, JPOOL_IMAGE, sizeof(png_source_struct));
memset(source, 0, sizeof(*source));
/* Fill in method ptrs, except get_pixel_rows which start_input sets */
source->pub.start_input = start_input_png;
source->pub.finish_input = finish_input_png;
return &source->pub;
}
METHODDEF(void) error_input_png(png_structp png_ptr, png_const_charp msg) {
j_compress_ptr cinfo = png_get_error_ptr(png_ptr);
ERREXITS(cinfo, JERR_PNG_ERROR, msg);
}
/* This is a small ICC profile for sRGB */
static unsigned char tiny_srgb[] = {0,0,2,24,108,99,109,115,2,16,0,0,109,110,
116,114,82,71,66,32,88,89,90,32,7,220,0,1,0,25,0,3,0,41,0,57,97,99,115,112,65,
80,80,76,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,214,0,1,0,0,0,
0,211,45,108,99,109,115,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,10,100,101,115,99,0,0,0,252,0,0,0,106,
99,112,114,116,0,0,1,104,0,0,0,11,119,116,112,116,0,0,1,116,0,0,0,20,98,107,
112,116,0,0,1,136,0,0,0,20,114,88,89,90,0,0,1,156,0,0,0,20,103,88,89,90,0,0,1,
176,0,0,0,20,98,88,89,90,0,0,1,196,0,0,0,20,114,84,82,67,0,0,1,216,0,0,0,64,98,
84,82,67,0,0,1,216,0,0,0,64,103,84,82,67,0,0,1,216,0,0,0,64,100,101,115,99,0,0,
0,0,0,0,0,13,115,82,71,66,32,77,111,122,74,80,69,71,0,0,0,0,0,0,0,0,1,0,0,0,0,
1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,116,101,120,
116,0,0,0,0,80,68,0,0,88,89,90,32,0,0,0,0,0,0,246,214,0,1,0,0,0,0,211,45,88,89,
90,32,0,0,0,0,0,0,3,22,0,0,3,51,0,0,2,164,88,89,90,32,0,0,0,0,0,0,111,162,0,0,
56,245,0,0,3,144,88,89,90,32,0,0,0,0,0,0,98,153,0,0,183,133,0,0,24,218,88,89,
90,32,0,0,0,0,0,0,36,160,0,0,15,132,0,0,182,207,99,117,114,118,0,0,0,0,0,0,0,
26,0,0,0,203,1,201,3,99,5,146,8,107,11,246,16,63,21,81,27,52,33,241,41,144,50,
24,59,146,70,5,81,119,93,237,107,112,122,5,137,177,154,124,172,105,191,125,211,
195,233,48,255,255,};
METHODDEF(void)
start_input_png (j_compress_ptr cinfo, cjpeg_source_ptr sinfo)
{
png_source_struct *source = (png_source_struct *)sinfo;
png_uint_32 width, height;
int bit_depth, color_type;
int has_srgb_chunk;
double gamma;
png_bytep profile;
png_charp unused1;
int unused2;
png_uint_32 proflen;
int has_profile;
size_t datalen;
JOCTET *dataptr;
struct jpeg_marker_struct *marker;
png_size_t rowbytes;
source->png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, cinfo, error_input_png, NULL);
source->info_ptr = png_create_info_struct(source->png_ptr);
if (!source->png_ptr || !source->info_ptr) {
ERREXITS(cinfo, JERR_PNG_ERROR, "Can't create read/info_struct");
return;
}
png_set_palette_to_rgb(source->png_ptr);
png_set_expand_gray_1_2_4_to_8(source->png_ptr);
png_set_strip_alpha(source->png_ptr);
png_set_interlace_handling(source->png_ptr);
png_init_io(source->png_ptr, source->pub.input_file);
png_read_info(source->png_ptr, source->info_ptr);
png_get_IHDR(source->png_ptr, source->info_ptr, &width, &height,
&bit_depth, &color_type, NULL, NULL, NULL);
if (width > 65535 || height > 65535) {
ERREXITS(cinfo, JERR_PNG_ERROR, "Image too large");
return;
}
if (color_type == PNG_COLOR_TYPE_GRAY || color_type == PNG_COLOR_TYPE_GRAY_ALPHA) {
cinfo->in_color_space = JCS_GRAYSCALE;
cinfo->input_components = 1;
} else {
cinfo->in_color_space = JCS_RGB;
cinfo->input_components = 3;
}
if (bit_depth == 16) {
png_set_strip_16(source->png_ptr);
}
cinfo->data_precision = 8;
cinfo->image_width = width;
cinfo->image_height = height;
has_srgb_chunk = png_get_valid(source->png_ptr, source->info_ptr, PNG_INFO_sRGB);
gamma = 0.45455;
if (!has_srgb_chunk) {
png_get_gAMA(source->png_ptr, source->info_ptr, &gamma);
}
cinfo->input_gamma = gamma;
sinfo->get_pixel_rows = get_pixel_rows_png;
source->pub.marker_list = NULL;
profile = NULL;
unused1 = NULL;
unused2 = 0;
proflen = 0;
has_profile = 0;
if (has_srgb_chunk) {
/* PNG can declare use of an sRGB profile without embedding an ICC file, but JPEG doesn't have such feature */
has_profile = 1;
profile = tiny_srgb;
proflen = sizeof(tiny_srgb);
} else {
has_profile = png_get_iCCP(source->png_ptr, source->info_ptr, &unused1, &unused2, &profile, &proflen); /* your libpng is out of date if you get a warning here */
}
if (has_profile && profile && proflen) {
if (proflen < 65535-14) {
datalen = proflen + 14;
dataptr = (*cinfo->mem->alloc_small)((j_common_ptr)cinfo, JPOOL_IMAGE, datalen);
memcpy(dataptr, "ICC_PROFILE\0\x01\x01", 14);
memcpy(dataptr + 14, profile, proflen);
marker = (*cinfo->mem->alloc_small)((j_common_ptr)cinfo, JPOOL_IMAGE, sizeof(struct jpeg_marker_struct));
marker->next = NULL;
marker->marker = JPEG_APP0+2;
marker->original_length = 0;
marker->data_length = datalen;
marker->data = dataptr;
source->pub.marker_list = marker;
} else {
WARNMS(cinfo, JERR_PNG_PROFILETOOLARGE);
}
}
png_read_update_info(source->png_ptr, source->info_ptr);
rowbytes = png_get_rowbytes(source->png_ptr, source->info_ptr);
source->pub.buffer = (*cinfo->mem->alloc_sarray)((j_common_ptr)cinfo, JPOOL_IMAGE, (JDIMENSION)rowbytes, 1);
source->pub.buffer_height = 1;
}
METHODDEF(JDIMENSION)
get_pixel_rows_png (j_compress_ptr cinfo, cjpeg_source_ptr sinfo)
{
png_source_struct *source = (png_source_struct *)sinfo;
png_read_row(source->png_ptr, source->pub.buffer[0], NULL);
return 1;
}
METHODDEF(void)
finish_input_png (j_compress_ptr cinfo, cjpeg_source_ptr sinfo)
{
png_source_struct *source = (png_source_struct *)sinfo;
png_read_end(source->png_ptr, source->info_ptr);
png_destroy_read_struct(&source->png_ptr, &source->info_ptr, NULL);
}
#endif

View File

@@ -26,7 +26,7 @@
LOCAL(int)
text_getc (FILE *file)
text_getc(FILE *file)
/* Read next char, skipping over any comments (# to end of line) */
/* A comment/newline sequence is returned as a newline */
{
@@ -43,7 +43,7 @@ text_getc (FILE *file)
LOCAL(boolean)
read_text_integer (FILE *file, long *result, int *termchar)
read_text_integer(FILE *file, long *result, int *termchar)
/* Read an unsigned decimal integer from a file, store it in result */
/* Reads one trailing character after the integer; returns it in termchar */
{
@@ -59,14 +59,14 @@ read_text_integer (FILE *file, long *result, int *termchar)
}
} while (isspace(ch));
if (! isdigit(ch)) {
if (!isdigit(ch)) {
*termchar = ch;
return FALSE;
}
val = ch - '0';
while ((ch = text_getc(file)) != EOF) {
if (! isdigit(ch))
if (!isdigit(ch))
break;
val *= 10;
val += ch - '0';
@@ -78,7 +78,7 @@ read_text_integer (FILE *file, long *result, int *termchar)
#if JPEG_LIB_VERSION < 70
static int q_scale_factor[NUM_QUANT_TBLS] = {100, 100, 100, 100};
static int q_scale_factor[NUM_QUANT_TBLS] = { 100, 100, 100, 100 };
#endif
GLOBAL(boolean)
@@ -110,14 +110,14 @@ read_quant_tables(j_compress_ptr cinfo, char *filename, boolean force_baseline)
fclose(fp);
return FALSE;
}
table[0] = (unsigned int) val;
table[0] = (unsigned int)val;
for (i = 1; i < DCTSIZE2; i++) {
if (! read_text_integer(fp, &val, &termchar)) {
if (!read_text_integer(fp, &val, &termchar)) {
fprintf(stderr, "Invalid table data in file %s\n", filename);
fclose(fp);
return FALSE;
}
table[i] = (unsigned int) val;
table[i] = (unsigned int)val;
}
#if JPEG_LIB_VERSION >= 70
jpeg_add_quant_table(cinfo, tblno, table, cinfo->q_scale_factor[tblno],
@@ -143,14 +143,14 @@ read_quant_tables(j_compress_ptr cinfo, char *filename, boolean force_baseline)
#ifdef C_MULTISCAN_FILES_SUPPORTED
LOCAL(boolean)
read_scan_integer (FILE *file, long *result, int *termchar)
read_scan_integer(FILE *file, long *result, int *termchar)
/* Variant of read_text_integer that always looks for a non-space termchar;
* this simplifies parsing of punctuation in scan scripts.
*/
{
register int ch;
if (! read_text_integer(file, result, termchar))
if (!read_text_integer(file, result, termchar))
return FALSE;
ch = *termchar;
while (ch != EOF && isspace(ch))
@@ -172,7 +172,7 @@ read_scan_integer (FILE *file, long *result, int *termchar)
GLOBAL(boolean)
read_scan_script (j_compress_ptr cinfo, char *filename)
read_scan_script(j_compress_ptr cinfo, char *filename)
/* Read a scan script from the specified text file.
* Each entry in the file defines one scan to be emitted.
* Entries are separated by semicolons ';'.
@@ -209,7 +209,7 @@ read_scan_script (j_compress_ptr cinfo, char *filename)
fclose(fp);
return FALSE;
}
scanptr->component_index[0] = (int) val;
scanptr->component_index[0] = (int)val;
ncomps = 1;
while (termchar == ' ') {
if (ncomps >= MAX_COMPS_IN_SCAN) {
@@ -218,29 +218,29 @@ read_scan_script (j_compress_ptr cinfo, char *filename)
fclose(fp);
return FALSE;
}
if (! read_scan_integer(fp, &val, &termchar))
if (!read_scan_integer(fp, &val, &termchar))
goto bogus;
scanptr->component_index[ncomps] = (int) val;
scanptr->component_index[ncomps] = (int)val;
ncomps++;
}
scanptr->comps_in_scan = ncomps;
if (termchar == ':') {
if (! read_scan_integer(fp, &val, &termchar) || termchar != ' ')
if (!read_scan_integer(fp, &val, &termchar) || termchar != ' ')
goto bogus;
scanptr->Ss = (int) val;
if (! read_scan_integer(fp, &val, &termchar) || termchar != ' ')
scanptr->Ss = (int)val;
if (!read_scan_integer(fp, &val, &termchar) || termchar != ' ')
goto bogus;
scanptr->Se = (int) val;
if (! read_scan_integer(fp, &val, &termchar) || termchar != ' ')
scanptr->Se = (int)val;
if (!read_scan_integer(fp, &val, &termchar) || termchar != ' ')
goto bogus;
scanptr->Ah = (int) val;
if (! read_scan_integer(fp, &val, &termchar))
scanptr->Ah = (int)val;
if (!read_scan_integer(fp, &val, &termchar))
goto bogus;
scanptr->Al = (int) val;
scanptr->Al = (int)val;
} else {
/* set non-progressive parameters */
scanptr->Ss = 0;
scanptr->Se = DCTSIZE2-1;
scanptr->Se = DCTSIZE2 - 1;
scanptr->Ah = 0;
scanptr->Al = 0;
}
@@ -265,14 +265,11 @@ bogus:
* but if you want to compress multiple images you'd want JPOOL_PERMANENT.
*/
scanptr = (jpeg_scan_info *)
(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
(*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_IMAGE,
scanno * sizeof(jpeg_scan_info));
memcpy(scanptr, scans, scanno * sizeof(jpeg_scan_info));
cinfo->scan_info = scanptr;
cinfo->num_scans = scanno;
/* Disable scan optimization if using custom scan */
jpeg_c_set_bool_param(cinfo, JBOOLEAN_OPTIMIZE_SCANS, FALSE);
}
fclose(fp);
@@ -288,10 +285,7 @@ bogus:
* The spec says that the values given produce "good" quality, and
* when divided by 2, "very good" quality.
*/
static const unsigned int std_luminance_quant_tbl[9][DCTSIZE2] = {
{
/* JPEG Annex K
*/
static const unsigned int std_luminance_quant_tbl[DCTSIZE2] = {
16, 11, 10, 16, 24, 40, 51, 61,
12, 12, 14, 19, 26, 58, 60, 55,
14, 13, 16, 24, 40, 57, 69, 56,
@@ -300,105 +294,8 @@ static const unsigned int std_luminance_quant_tbl[9][DCTSIZE2] = {
24, 35, 55, 64, 81, 104, 113, 92,
49, 64, 78, 87, 103, 121, 120, 101,
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[9][DCTSIZE2] = {
{
/* JPEG Annex K
*/
static const unsigned int std_chrominance_quant_tbl[DCTSIZE2] = {
17, 18, 24, 47, 99, 99, 99, 99,
18, 21, 26, 66, 99, 99, 99, 99,
24, 26, 56, 99, 99, 99, 99, 99,
@@ -407,173 +304,62 @@ 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
},
{
/* 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
}
};
LOCAL(void)
jpeg_default_qtables (j_compress_ptr cinfo, boolean force_baseline)
jpeg_default_qtables(j_compress_ptr cinfo, boolean force_baseline)
{
int quant_tbl_master_idx = 0;
if (jpeg_c_int_param_supported(cinfo, JINT_BASE_QUANT_TBL_IDX))
quant_tbl_master_idx = jpeg_c_get_int_param(cinfo, JINT_BASE_QUANT_TBL_IDX);
jpeg_add_quant_table(cinfo, 0, std_luminance_quant_tbl[quant_tbl_master_idx],
q_scale_factor[0], force_baseline);
jpeg_add_quant_table(cinfo, 1, std_chrominance_quant_tbl[quant_tbl_master_idx],
q_scale_factor[1], force_baseline);
jpeg_add_quant_table(cinfo, 0, std_luminance_quant_tbl, q_scale_factor[0],
force_baseline);
jpeg_add_quant_table(cinfo, 1, std_chrominance_quant_tbl, q_scale_factor[1],
force_baseline);
}
#endif
GLOBAL(boolean)
set_quality_ratings (j_compress_ptr cinfo, char *arg, boolean force_baseline)
set_quality_ratings(j_compress_ptr cinfo, char *arg, boolean force_baseline)
/* Process a quality-ratings parameter string, of the form
* N[,N,...]
* If there are more q-table slots than parameters, the last value is replicated.
*/
{
float val = 75.f; /* default value */
int val = 75; /* default value */
int tblno;
char ch;
for (tblno = 0; tblno < NUM_QUANT_TBLS; tblno++) {
if (*arg) {
ch = ','; /* if not set by sscanf, will be ',' */
if (sscanf(arg, "%f%c", &val, &ch) < 1)
if (sscanf(arg, "%d%c", &val, &ch) < 1)
return FALSE;
if (ch != ',') /* syntax check */
return FALSE;
/* Convert user 0-100 rating to percentage scaling */
#if JPEG_LIB_VERSION >= 70
cinfo->q_scale_factor[tblno] = jpeg_float_quality_scaling(val);
cinfo->q_scale_factor[tblno] = jpeg_quality_scaling(val);
#else
q_scale_factor[tblno] = jpeg_float_quality_scaling(val);
q_scale_factor[tblno] = jpeg_quality_scaling(val);
#endif
while (*arg && *arg++ != ','); /* advance to next segment of arg
string */
} else {
/* reached end of parameter, set remaining factors to last value */
#if JPEG_LIB_VERSION >= 70
cinfo->q_scale_factor[tblno] = jpeg_float_quality_scaling(val);
cinfo->q_scale_factor[tblno] = jpeg_quality_scaling(val);
#else
q_scale_factor[tblno] = jpeg_float_quality_scaling(val);
q_scale_factor[tblno] = jpeg_quality_scaling(val);
#endif
}
}
jpeg_default_qtables(cinfo, force_baseline);
/* For some images chroma subsampling significantly degrades color quality,
making it impossible to achieve high visual quality regardless of quality setting.
To make the quality setting more intuitive, disable subsampling when high-quality
color is desired. */
if (val >= 90) {
set_sample_factors(cinfo, "1x1");
} else if (val >= 80) {
set_sample_factors(cinfo, "2x1");
}
return TRUE;
}
GLOBAL(boolean)
set_quant_slots (j_compress_ptr cinfo, char *arg)
set_quant_slots(j_compress_ptr cinfo, char *arg)
/* Process a quantization-table-selectors parameter string, of the form
* N[,N,...]
* If there are more components than parameters, the last value is replicated.
@@ -592,7 +378,7 @@ set_quant_slots (j_compress_ptr cinfo, char *arg)
return FALSE;
if (val < 0 || val >= NUM_QUANT_TBLS) {
fprintf(stderr, "JPEG quantization tables are numbered 0..%d\n",
NUM_QUANT_TBLS-1);
NUM_QUANT_TBLS - 1);
return FALSE;
}
cinfo->comp_info[ci].quant_tbl_no = val;
@@ -608,7 +394,7 @@ set_quant_slots (j_compress_ptr cinfo, char *arg)
GLOBAL(boolean)
set_sample_factors (j_compress_ptr cinfo, char *arg)
set_sample_factors(j_compress_ptr cinfo, char *arg)
/* Process a sample-factors parameter string, of the form
* HxV[,HxV,...]
* If there are more components than parameters, "1x1" is assumed for the rest.

View File

@@ -12,7 +12,7 @@
\pard\tx220\tx720\pardeftab720\li720\fi-720
\ls1\ilvl0\cf0 {\listtext \'95 }Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.\
{\listtext \'95 }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.\
{\listtext \'95 }Neither the name of the mozjpeg Project nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.\
{\listtext \'95 }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.\
\pard\pardeftab720\qc
\cf0 \
\pard\pardeftab720

View File

@@ -14,4 +14,4 @@
\f0 \cf0 \
from the command line.\
}
}

View File

@@ -7,18 +7,25 @@ Essential: no
Maintainer: @PKGVENDOR@ <@PKGEMAIL@>
Homepage: @PKGURL@
Installed-Size: {__SIZE}
Description: A JPEG codec that provides increased compression for JPEG images (at the expense of compression performance)
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.
Description: A SIMD-accelerated JPEG codec that provides both the libjpeg and TurboJPEG APIs
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.
.
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-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.

View File

@@ -161,7 +161,7 @@ install_subbuild()
if [ "$BUILDDIRARMV8" != "" ]; then
install_subbuild $BUILDDIRARMV8 Armv8 armv8 arm64
fi
fi
install_name_tool -id $LIBDIR/$LIBJPEG_DSO_NAME $PKGROOT/$LIBDIR/$LIBJPEG_DSO_NAME
install_name_tool -id $LIBDIR/$TURBOJPEG_DSO_NAME $PKGROOT/$LIBDIR/$TURBOJPEG_DSO_NAME

View File

@@ -9,7 +9,7 @@
# - 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 mozjpeg Project nor the names of its
# - 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.
#

View File

@@ -31,7 +31,7 @@ endif()
if(WIN32)
if(WITH_MEM_SRCDST)
set(DEFFILE ../win/jpeg${SO_MAJOR_VERSION}-memsrcdst.def)
else()
else()
set(DEFFILE ../win/jpeg${SO_MAJOR_VERSION}.def)
endif()
endif()
@@ -42,9 +42,6 @@ if(MSVC)
endif()
add_library(jpeg SHARED ${JPEG_SRCS} ${DEFFILE} $<TARGET_OBJECTS:simd>
${SIMD_OBJS})
if(UNIX)
target_link_libraries(jpeg m)
endif()
set_target_properties(jpeg PROPERTIES SOVERSION ${SO_MAJOR_VERSION}
VERSION ${SO_MAJOR_VERSION}.${SO_AGE}.${SO_MINOR_VERSION})
@@ -75,36 +72,15 @@ if(WITH_12BIT)
set(COMPILE_FLAGS "-DGIF_SUPPORTED -DPPM_SUPPORTED ${USE_SETMODE}")
else()
set(COMPILE_FLAGS "-DBMP_SUPPORTED -DGIF_SUPPORTED -DPPM_SUPPORTED -DTARGA_SUPPORTED ${USE_SETMODE}")
set(CJPEG_BMP_SOURCES ../rdbmp.c ../rdtarga.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()
set(CJPEG_BMP_SOURCES ../rdbmp.c ../rdtarga.c)
set(DJPEG_BMP_SOURCES ../wrbmp.c ../wrtarga.c)
endif()
add_executable(cjpeg ../cjpeg.c ../cdjpeg.c ../rdgif.c ../rdppm.c ../rdjpeg.c
add_executable(cjpeg ../cjpeg.c ../cdjpeg.c ../rdgif.c ../rdppm.c
../rdswitch.c ${CJPEG_BMP_SOURCES})
set_property(TARGET cjpeg PROPERTY COMPILE_FLAGS ${COMPILE_FLAGS})
target_link_libraries(cjpeg jpeg)
if(PNG_SUPPORTED)
# to avoid finding static 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)
find_package(PNG 1.6 REQUIRED)
find_package(ZLIB REQUIRED)
target_include_directories(cjpeg PUBLIC ${PNG_INCLUDE_DIR} ${ZLIB_INCLUDE_DIR})
target_link_libraries(cjpeg ${PNG_LIBRARY} ${ZLIB_LIBRARY})
endif()
add_executable(djpeg ../djpeg.c ../cdjpeg.c ../rdcolmap.c ../rdswitch.c
../wrgif.c ../wrppm.c ${DJPEG_BMP_SOURCES})
set_property(TARGET djpeg PROPERTY COMPILE_FLAGS ${COMPILE_FLAGS})

View File

@@ -195,7 +195,7 @@ foreach(file ${SIMD_SOURCES})
endforeach()
if(MSVC_IDE OR XCODE)
set(SIMD_OBJS ${SIMD_OBJS} PARENT_SCOPE)
set(SIMD_OBJS ${SIMD_OBJS} PARENT_SCOPE)
add_library(simd OBJECT ${CPU_TYPE}/jsimd.c)
add_custom_target(simd-objs DEPENDS ${SIMD_OBJS})
add_dependencies(simd simd-objs)
@@ -449,6 +449,9 @@ elseif(CPU_TYPE STREQUAL "loongson" OR CPU_TYPE MATCHES "^mips64")
set(CMAKE_REQUIRED_FLAGS -Wa,-mloongson-mmi,-mloongson-ext)
check_c_source_compiles("
#if !(defined(__mips__) && __mips_isa_rev < 6)
#error Loongson MMI can't work with MIPS Release 6+
#endif
int main(void) {
int c = 0, a = 0, b = 0;
asm (

View File

@@ -25,8 +25,6 @@
#include "../../../jsimddct.h"
#include "../../jsimd.h"
#include <stdio.h>
#include <string.h>
#include <ctype.h>
static unsigned int simd_support = ~0;

View File

@@ -25,8 +25,6 @@
#include "../../jsimd.h"
#include "jconfigint.h"
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#define JSIMD_FASTLD3 1

View File

@@ -23,8 +23,6 @@
#include "../../jsimddct.h"
#include "../jsimd.h"
#include <stdio.h>
#include <string.h>
#include <ctype.h>
static unsigned int simd_support = ~0;

View File

@@ -24,8 +24,6 @@
#include "../../jsimddct.h"
#include "../jsimd.h"
#include <stdio.h>
#include <string.h>
#include <ctype.h>
static unsigned int simd_support = ~0;

View File

@@ -27,11 +27,12 @@
#include "../../jsimddct.h"
#include "../jsimd.h"
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#if defined(__OpenBSD__)
#if defined(__APPLE__)
#include <sys/types.h>
#include <sys/sysctl.h>
#elif defined(__OpenBSD__)
#include <sys/param.h>
#include <sys/sysctl.h>
#include <machine/cpu.h>
@@ -121,6 +122,10 @@ init_simd(void)
int bufsize = 1024; /* an initial guess for the line buffer size limit */
#elif defined(__amigaos4__)
uint32 altivec = 0;
#elif defined(__APPLE__)
int mib[2] = { CTL_HW, HW_VECTORUNIT };
int altivec;
size_t len = sizeof(altivec);
#elif defined(__OpenBSD__)
int mib[2] = { CTL_MACHDEP, CPU_ALTIVEC };
int altivec;
@@ -134,7 +139,7 @@ init_simd(void)
simd_support = 0;
#if defined(__ALTIVEC__) || defined(__APPLE__)
#if defined(__ALTIVEC__)
simd_support |= JSIMD_ALTIVEC;
#elif defined(__linux__) || defined(ANDROID) || defined(__ANDROID__)
while (!parse_proc_cpuinfo(bufsize)) {
@@ -146,7 +151,7 @@ init_simd(void)
IExec->GetCPUInfoTags(GCIT_VectorUnit, &altivec, TAG_DONE);
if (altivec == VECTORTYPE_ALTIVEC)
simd_support |= JSIMD_ALTIVEC;
#elif defined(__OpenBSD__)
#elif defined(__APPLE__) || defined(__OpenBSD__)
if (sysctl(mib, 2, &altivec, &len, NULL, 0) == 0 && altivec != 0)
simd_support |= JSIMD_ALTIVEC;
#elif defined(__FreeBSD__)

View File

@@ -27,6 +27,7 @@
*/
#include "jinclude.h"
#include <errno.h>
#define CHECK_VALUE(actual, expected, desc) \

View File

@@ -107,7 +107,7 @@ static char *formatName(int subsamp, int cs, char *buf)
if (cs == TJCS_YCbCr)
return (char *)subNameLong[subsamp];
else if (cs == TJCS_YCCK || cs == TJCS_CMYK) {
snprintf(buf, 80, "%s %s", csName[cs], subNameLong[subsamp]);
SNPRINTF(buf, 80, "%s %s", csName[cs], subNameLong[subsamp]);
return buf;
} else
return (char *)csName[cs];
@@ -120,10 +120,10 @@ static char *sigfig(double val, int figs, char *buf, int len)
int digitsAfterDecimal = figs - (int)ceil(log10(fabs(val)));
if (digitsAfterDecimal < 1)
snprintf(format, 80, "%%.0f");
SNPRINTF(format, 80, "%%.0f");
else
snprintf(format, 80, "%%.%df", digitsAfterDecimal);
snprintf(buf, len, format, val);
SNPRINTF(format, 80, "%%.%df", digitsAfterDecimal);
SNPRINTF(buf, len, format, val);
return buf;
}
@@ -160,7 +160,7 @@ static int decomp(unsigned char *srcBuf, unsigned char **jpegBuf,
unsigned char *dstPtr, *dstPtr2, *yuvBuf = NULL;
if (jpegQual > 0) {
snprintf(qualStr, 13, "_Q%d", jpegQual);
SNPRINTF(qualStr, 13, "_Q%d", jpegQual);
qualStr[12] = 0;
}
@@ -262,20 +262,20 @@ static int decomp(unsigned char *srcBuf, unsigned char **jpegBuf,
if (!doWrite) goto bailout;
if (sf.num != 1 || sf.denom != 1)
snprintf(sizeStr, 24, "%d_%d", sf.num, sf.denom);
SNPRINTF(sizeStr, 24, "%d_%d", sf.num, sf.denom);
else if (tilew != w || tileh != h)
snprintf(sizeStr, 24, "%dx%d", tilew, tileh);
else snprintf(sizeStr, 24, "full");
SNPRINTF(sizeStr, 24, "%dx%d", tilew, tileh);
else SNPRINTF(sizeStr, 24, "full");
if (decompOnly)
snprintf(tempStr, 1024, "%s_%s.%s", fileName, sizeStr, ext);
SNPRINTF(tempStr, 1024, "%s_%s.%s", fileName, sizeStr, ext);
else
snprintf(tempStr, 1024, "%s_%s%s_%s.%s", fileName, subName[subsamp],
SNPRINTF(tempStr, 1024, "%s_%s%s_%s.%s", fileName, subName[subsamp],
qualStr, sizeStr, ext);
if (tjSaveImage(tempStr, dstBuf, scaledw, 0, scaledh, pf, flags) == -1)
THROW_TJG("saving bitmap");
ptr = strrchr(tempStr, '.');
snprintf(ptr, 1024 - (ptr - tempStr), "-err.%s", ext);
SNPRINTF(ptr, 1024 - (ptr - tempStr), "-err.%s", ext);
if (srcBuf && sf.num == 1 && sf.denom == 1) {
if (!quiet) printf("Compression error written to %s.\n", tempStr);
if (subsamp == TJ_GRAYSCALE) {
@@ -478,7 +478,7 @@ static int fullTest(unsigned char *srcBuf, int w, int h, int subsamp,
(double)totalJpegSize * 8. / 1000000. * (double)iter / elapsed);
}
if (tilew == w && tileh == h && doWrite) {
snprintf(tempStr, 1024, "%s_%s_Q%d.jpg", fileName, subName[subsamp],
SNPRINTF(tempStr, 1024, "%s_%s_Q%d.jpg", fileName, subName[subsamp],
jpegQual);
if ((file = fopen(tempStr, "wb")) == NULL)
THROW_UNIX("opening reference image");

View File

@@ -409,7 +409,7 @@ static void compTest(tjhandle handle, unsigned char **dstBuf,
jpegQual, flags));
}
snprintf(tempStr, 1024, "%s_enc_%s_%s_%s_Q%d.jpg", basename, pfStr, buStr,
SNPRINTF(tempStr, 1024, "%s_enc_%s_%s_%s_Q%d.jpg", basename, pfStr, buStr,
subName[subsamp], jpegQual);
writeJPEG(*dstBuf, *dstSize, tempStr);
printf("Done.\n Result in %s\n", tempStr);
@@ -782,7 +782,7 @@ static int doBmpTest(const char *ext, int width, int align, int height, int pf,
THROW("Could not allocate memory");
initBitmap(buf, width, pitch, height, pf, flags);
snprintf(filename, 80, "test_bmp_%s_%d_%s.%s", pixFormatStr[pf], align,
SNPRINTF(filename, 80, "test_bmp_%s_%d_%s.%s", pixFormatStr[pf], align,
(flags & TJFLAG_BOTTOMUP) ? "bu" : "td", ext);
TRY_TJ(tjSaveImage(filename, buf, width, pitch, height, pf, flags));
md5sum = MD5File(filename, md5buf);
@@ -887,13 +887,9 @@ static int bmpTest(void)
return 0;
}
#ifdef _WIN32
#define setenv(envvar, value, dummy) _putenv_s(envvar, value)
#endif
int main(int argc, char *argv[])
{
setenv("TJ_REVERT", "1", 1);
int i, num4bf = 5;
#ifdef _WIN32

View File

@@ -1,5 +1,5 @@
/*
* Copyright (C)2011 D. R. Commander. All Rights Reserved.
* Copyright (C)2011, 2022 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:
@@ -27,9 +27,20 @@
*/
#ifdef _WIN32
#ifndef strcasecmp
#define strcasecmp stricmp
#endif
#ifndef strncasecmp
#define strncasecmp strnicmp
#endif
#endif
#ifdef _MSC_VER
#define SNPRINTF(str, n, format, ...) \
_snprintf_s(str, n, _TRUNCATE, format, ##__VA_ARGS__)
#else
#define SNPRINTF snprintf
#endif
#ifndef min
#define min(a, b) ((a) < (b) ? (a) : (b))

View File

@@ -20,12 +20,6 @@
* jpegtran.c for an example of correct usage.
*/
#ifdef __cplusplus
#ifndef DONT_USE_EXTERN_C
extern "C" {
#endif
#endif
/* If you happen not to want the image transform support, disable it here */
#ifndef TRANSFORMS_SUPPORTED
#define TRANSFORMS_SUPPORTED 1 /* 0 disables transform code */
@@ -235,9 +229,3 @@ EXTERN(void) jcopy_markers_setup(j_decompress_ptr srcinfo,
EXTERN(void) jcopy_markers_execute(j_decompress_ptr srcinfo,
j_compress_ptr dstinfo,
JCOPY_OPTION option);
#ifdef __cplusplus
#ifndef DONT_USE_EXTERN_C
}
#endif
#endif

View File

@@ -26,8 +26,6 @@
* POSSIBILITY OF SUCH DAMAGE.
*/
#include <stdlib.h>
#include <string.h>
#include "turbojpeg.h"
#include "jinclude.h"
#include <jni.h>

View File

@@ -1,8 +1,6 @@
/*
* Copyright (C)2009-2022 D. R. Commander. All Rights Reserved.
* Copyright (C)2021 Alex Richardson. All Rights Reserved.
* mozjpeg Modifications:
* Copyright (C) 2014, Mozilla Corporation.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
@@ -32,8 +30,6 @@
/* TurboJPEG/LJT: this implements the TurboJPEG API using libjpeg or
libjpeg-turbo */
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <jinclude.h>
#define JPEG_INTERNALS
@@ -130,9 +126,9 @@ static void my_progress_monitor(j_common_ptr dinfo)
int scan_no = ((j_decompress_ptr)dinfo)->input_scan_number;
if (scan_no > 500) {
snprintf(myprog->this->errStr, JMSG_LENGTH_MAX,
SNPRINTF(myprog->this->errStr, JMSG_LENGTH_MAX,
"Progressive JPEG image has more than 500 scans");
snprintf(errStr, JMSG_LENGTH_MAX,
SNPRINTF(errStr, JMSG_LENGTH_MAX,
"Progressive JPEG image has more than 500 scans");
myprog->this->isInstanceError = TRUE;
myerr->warning = FALSE;
@@ -195,24 +191,24 @@ static int cs2pf[JPEG_NUMCS] = {
};
#define THROWG(m) { \
snprintf(errStr, JMSG_LENGTH_MAX, "%s", m); \
SNPRINTF(errStr, JMSG_LENGTH_MAX, "%s", m); \
retval = -1; goto bailout; \
}
#ifdef _MSC_VER
#define THROW_UNIX(m) { \
char strerrorBuf[80] = { 0 }; \
strerror_s(strerrorBuf, 80, errno); \
snprintf(errStr, JMSG_LENGTH_MAX, "%s\n%s", m, strerrorBuf); \
SNPRINTF(errStr, JMSG_LENGTH_MAX, "%s\n%s", m, strerrorBuf); \
retval = -1; goto bailout; \
}
#else
#define THROW_UNIX(m) { \
snprintf(errStr, JMSG_LENGTH_MAX, "%s\n%s", m, strerror(errno)); \
SNPRINTF(errStr, JMSG_LENGTH_MAX, "%s\n%s", m, strerror(errno)); \
retval = -1; goto bailout; \
}
#endif
#define THROW(m) { \
snprintf(this->errStr, JMSG_LENGTH_MAX, "%s", m); \
SNPRINTF(this->errStr, JMSG_LENGTH_MAX, "%s", m); \
this->isInstanceError = TRUE; THROWG(m) \
}
@@ -227,7 +223,7 @@ static int cs2pf[JPEG_NUMCS] = {
j_decompress_ptr dinfo = NULL; \
\
if (!this) { \
snprintf(errStr, JMSG_LENGTH_MAX, "Invalid handle"); \
SNPRINTF(errStr, JMSG_LENGTH_MAX, "Invalid handle"); \
return -1; \
} \
cinfo = &this->cinfo; dinfo = &this->dinfo; \
@@ -239,7 +235,7 @@ static int cs2pf[JPEG_NUMCS] = {
j_compress_ptr cinfo = NULL; \
\
if (!this) { \
snprintf(errStr, JMSG_LENGTH_MAX, "Invalid handle"); \
SNPRINTF(errStr, JMSG_LENGTH_MAX, "Invalid handle"); \
return -1; \
} \
cinfo = &this->cinfo; \
@@ -251,7 +247,7 @@ static int cs2pf[JPEG_NUMCS] = {
j_decompress_ptr dinfo = NULL; \
\
if (!this) { \
snprintf(errStr, JMSG_LENGTH_MAX, "Invalid handle"); \
SNPRINTF(errStr, JMSG_LENGTH_MAX, "Invalid handle"); \
return -1; \
} \
dinfo = &this->dinfo; \
@@ -287,10 +283,6 @@ static void setCompDefaults(struct jpeg_compress_struct *cinfo,
cinfo->in_color_space = pf2cs[pixelFormat];
cinfo->input_components = tjPixelSize[pixelFormat];
#ifndef NO_GETENV
if (!GETENV_S(env, 7, "TJ_REVERT") && !strcmp(env, "1"))
cinfo->master->compress_profile=JCP_FASTEST;
#endif
jpeg_set_defaults(cinfo);
#ifndef NO_GETENV
@@ -339,10 +331,6 @@ static void setCompDefaults(struct jpeg_compress_struct *cinfo,
jpeg_simple_progression(cinfo);
#endif
/* Set scan pattern again as colorspace might have changed */
if(cinfo->master->compress_profile == JCP_MAX_COMPRESSION)
jpeg_simple_progression(cinfo);
cinfo->comp_info[0].h_samp_factor = tjMCUWidth[subsamp] / 8;
cinfo->comp_info[1].h_samp_factor = 1;
cinfo->comp_info[2].h_samp_factor = 1;
@@ -519,14 +507,6 @@ static tjhandle _tjInitCompress(tjinstance *this)
}
jpeg_create_compress(&this->cinfo);
#ifndef NO_GETENV
/* This is used in unit tests */
char *env = NULL;
if((env=getenv("TJ_REVERT"))!=NULL && strlen(env)>0 && !strcmp(env, "1"))
jpeg_c_set_int_param(&this->cinfo, JINT_COMPRESS_PROFILE, JCP_FASTEST);
#endif
/* Make an initial call so it will create the destination manager */
jpeg_mem_dest_tj(&this->cinfo, &buf, &size, 0);
@@ -539,12 +519,12 @@ DLLEXPORT tjhandle tjInitCompress(void)
tjinstance *this = NULL;
if ((this = (tjinstance *)malloc(sizeof(tjinstance))) == NULL) {
snprintf(errStr, JMSG_LENGTH_MAX,
SNPRINTF(errStr, JMSG_LENGTH_MAX,
"tjInitCompress(): Memory allocation failure");
return NULL;
}
memset(this, 0, sizeof(tjinstance));
snprintf(this->errStr, JMSG_LENGTH_MAX, "No error");
SNPRINTF(this->errStr, JMSG_LENGTH_MAX, "No error");
return _tjInitCompress(this);
}
@@ -1213,12 +1193,12 @@ DLLEXPORT tjhandle tjInitDecompress(void)
tjinstance *this;
if ((this = (tjinstance *)malloc(sizeof(tjinstance))) == NULL) {
snprintf(errStr, JMSG_LENGTH_MAX,
SNPRINTF(errStr, JMSG_LENGTH_MAX,
"tjInitDecompress(): Memory allocation failure");
return NULL;
}
memset(this, 0, sizeof(tjinstance));
snprintf(this->errStr, JMSG_LENGTH_MAX, "No error");
SNPRINTF(this->errStr, JMSG_LENGTH_MAX, "No error");
return _tjInitDecompress(this);
}
@@ -1245,7 +1225,13 @@ DLLEXPORT int tjDecompressHeader3(tjhandle handle,
}
jpeg_mem_src_tj(dinfo, jpegBuf, jpegSize);
jpeg_read_header(dinfo, TRUE);
/* jpeg_read_header() calls jpeg_abort() and returns JPEG_HEADER_TABLES_ONLY
if the datastream is a tables-only datastream. Since we aren't using a
suspending data source, the only other value it can return is
JPEG_HEADER_OK. */
if (jpeg_read_header(dinfo, FALSE) == JPEG_HEADER_TABLES_ONLY)
return 0;
*width = dinfo->image_width;
*height = dinfo->image_height;
@@ -1297,7 +1283,7 @@ DLLEXPORT int tjDecompressHeader(tjhandle handle, unsigned char *jpegBuf,
DLLEXPORT tjscalingfactor *tjGetScalingFactors(int *numscalingfactors)
{
if (numscalingfactors == NULL) {
snprintf(errStr, JMSG_LENGTH_MAX,
SNPRINTF(errStr, JMSG_LENGTH_MAX,
"tjGetScalingFactors(): Invalid argument");
return NULL;
}
@@ -1904,12 +1890,12 @@ DLLEXPORT tjhandle tjInitTransform(void)
tjhandle handle = NULL;
if ((this = (tjinstance *)malloc(sizeof(tjinstance))) == NULL) {
snprintf(errStr, JMSG_LENGTH_MAX,
SNPRINTF(errStr, JMSG_LENGTH_MAX,
"tjInitTransform(): Memory allocation failure");
return NULL;
}
memset(this, 0, sizeof(tjinstance));
snprintf(this->errStr, JMSG_LENGTH_MAX, "No error");
SNPRINTF(this->errStr, JMSG_LENGTH_MAX, "No error");
handle = _tjInitCompress(this);
if (!handle) return NULL;
handle = _tjInitDecompress(this);
@@ -2000,7 +1986,7 @@ DLLEXPORT int tjTransform(tjhandle handle, const unsigned char *jpegBuf,
if (xinfo[i].crop) {
if ((t[i].r.x % tjMCUWidth[jpegSubsamp]) != 0 ||
(t[i].r.y % tjMCUHeight[jpegSubsamp]) != 0) {
snprintf(this->errStr, JMSG_LENGTH_MAX,
SNPRINTF(this->errStr, JMSG_LENGTH_MAX,
"To crop this JPEG image, x must be a multiple of %d\n"
"and y must be a multiple of %d.\n",
tjMCUWidth[jpegSubsamp], tjMCUHeight[jpegSubsamp]);

View File

@@ -1129,27 +1129,38 @@ DLLEXPORT tjhandle tjInitDecompress(void);
/**
* Retrieve information about a JPEG image without decompressing it.
* Retrieve information about a JPEG image without decompressing it, or prime
* the decompressor with quantization and Huffman tables.
*
* @param handle a handle to a TurboJPEG decompressor or transformer instance
*
* @param jpegBuf pointer to a buffer containing a JPEG image
* @param jpegBuf 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.
*
* @param jpegSize size of the JPEG image (in bytes)
* @param jpegSize size of the JPEG image or tables-only datastream (in bytes)
*
* @param width pointer to an integer variable that will receive the width (in
* pixels) of the JPEG image
* pixels) of the JPEG image. If <tt>jpegBuf</tt> points to a tables-only
* datastream, then <tt>width</tt> is ignored.
*
* @param height pointer to an integer variable that will receive the height
* (in pixels) of the JPEG image
* (in pixels) of the JPEG image. If <tt>jpegBuf</tt> points to a tables-only
* datastream, then <tt>height</tt> is ignored.
*
* @param jpegSubsamp pointer to an integer variable that will receive the
* level of chrominance subsampling used when the JPEG image was compressed
* (see @ref TJSAMP "Chrominance subsampling options".)
* (see @ref TJSAMP "Chrominance subsampling options".) If <tt>jpegBuf</tt>
* points to a tables-only datastream, then <tt>jpegSubsamp</tt> is ignored.
*
* @param jpegColorspace pointer to an integer variable that will receive one
* of the JPEG colorspace constants, indicating the colorspace of the JPEG
* image (see @ref TJCS "JPEG colorspaces".)
* image (see @ref TJCS "JPEG colorspaces".) If <tt>jpegBuf</tt>
* points to a tables-only datastream, then <tt>jpegColorspace</tt> is ignored.
*
* @return 0 if successful, or -1 if an error occurred (see #tjGetErrorStr2()
* and #tjGetErrorCode().)

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