Compare commits

..

78 Commits
v1.0.1 ... v2.1

Author SHA1 Message Date
Josh Aas
594b7258cc Bump version to 2.1. 2014-07-29 09:12:48 -05:00
fbossen
0533b31891 Merge pull request #79 from arjun024/devel
more logical flow of control if trellis_quant enabled
2014-07-25 09:02:45 -04:00
Arjun Sreedharan
cca53c920d more logical flow of control if trellis_quant enabled
if trellis_quant is enabled, increment total number of
passes by optimization beginning pass number.

Signed-off-by: Arjun Sreedharan <arjun024@gmail.com>
2014-07-25 17:33:35 +05:30
Josh Aas
5901802871 Update README.md with link to 2.0 announcement and mailing list. 2014-07-24 16:39:26 -05:00
Frank Bossen
fbef31f76d Add option to disable progressive coding in cjpeg
Redefine baseline option in cjpeg to actually create a baseline JPEG
file by disabling progressive coding
2014-07-24 17:09:27 -04:00
Frank Bossen
1aa50b71d9 Use precomputed table
From jpeglib-turbo r1221:
Integrate a slightly modified version of Mozilla's patch for
precomputing the bit-counting LUT.  This is useful if the table needs
to be shared among multiple processes, although the primary reason for
doing that is reduced footprint on mobile devices, which are probably
already covered by the clz intrinsic code.
2014-07-24 10:50:59 -04:00
Frank Bossen
3adc64a4cb Improve floating point DCT
From libjpeg-turbo r1288
Port the more accurate (and slightly faster) floating point IDCT
implementation from jpeg-8a and later.  New research revealed that the
SSE/SSE2 floating point IDCT implementation was actually more accurate
than the jpeg-6b implementation, not less, which is why its
mathematical results have always differed from those of the jpeg-6b
implementation.  This patch brings the accuracy of the C code in line
with that of the SSE/SSE2 code.
2014-07-23 10:26:46 -04:00
Frank Bossen
ccb1d12f53 Update doc re: various DCT implementations
From libjpeg-turbo r1287
2014-07-23 10:23:24 -04:00
Frank Bossen
c73a82c6aa Fix build for wrjpgcom
See r1325 in libjpeg-turbo
2014-07-23 09:22:55 -04:00
Frank Bossen
b9f25333f6 Disable scan optimization if no scan given
Addresses segmentation fault issue in #69
2014-07-21 20:11:46 +02:00
Josh Aas
0f6b96c68e Merge pull request #73 from pornel/master
Added few error messages in cjpeg
2014-07-21 11:23:20 -05:00
Josh Aas
eeea9ed397 Merge pull request #72 from jlongman/master
Bugfix: AM_PROG_AR is not recognized by older automake, so only use it w...
2014-07-21 11:21:30 -05:00
Josh Aas
b95528727f Merge pull request #75 from pmed/master
Fixed mozjpeg build with Visual C++ 2010
2014-07-21 11:18:33 -05:00
Pavel Medvedev
d9605b0560 Fixed mozjpeg build with Visual C++ 2010
Moved several variable declarations out of inner scopes to the function scope to compile C code with Visual C++ 2010
2014-07-21 15:32:54 +04:00
Kornel Lesiński
40e6e8b2a2 Added few error messages in cjpeg 2014-07-20 16:11:59 +01:00
Frank Bossen
514307e9e6 Fix trellis for nonprogressive mode (#69)
Correct number of trellis passes when in nonprogressive mode
2014-07-18 18:10:56 +02:00
jlongman
7388a54647 Bugfix: AM_PROG_AR is not recognized by older automake, so only use it when defined 2014-07-17 14:16:24 -04:00
Josh Aas
e7a135b930 Bump version number for 2.0, make this version 2.0.1. 2014-07-15 13:55:55 -05:00
Frank Bossen
62300280b5 Update MS-SSIM tuning
Change optimization parameters when tuning for MS-SSIM for better
performance
2014-07-10 16:55:53 +09:00
Frank Bossen
55e3e7e819 Fix #64
Setting a user-defined quality level in cjpeg was incorrectly setting
quantization table
2014-07-09 11:37:36 +09:00
Josh Aas
0c59a4daf6 Merge pull request #62 from negge/master
Updating yuvjpeg and jpegyuv to match Daala tools.
2014-07-07 13:07:07 -05:00
Nathan E. Egge
d47fa82ae8 Updating yuvjpeg and jpegyuv to match Daala tools.
Add support for jpeg images with non-multiple of 16 sizes.
2014-07-07 13:46:59 -04:00
Frank Bossen
c3b7375ad8 Fix #56 2014-06-26 12:45:03 -04:00
Frank Bossen
b8c8ef9851 Silence compiler warning
gcc 4.8 was throwing 'foo' may be used uninitialized in this function
[-Wmaybe-uninitialized]
2014-06-04 16:31:27 +02:00
Frank Bossen
a9356f18b4 Silence compiler warning 2014-05-30 03:18:37 +02:00
Frank Bossen
5dc78b3681 Merge branch 'jpegin' 2014-05-30 03:15:46 +02:00
Frank Bossen
66bf3abec7 Improve support of JPEG input in cjpeg
Add macro JPEG_RAW_READER that defines whether to pass RAW sample data
from input to output JPEG files (hence preserving color space and
sampling). Macro is now disabled by default.
Add code to copy metadata from input to output JPEG, hence preserving
color profiles and other important information
2014-05-30 03:14:09 +02:00
Frank Bossen
535b1ee3ef Fix issue with JPEG read in cjpeg
Color space and sampling was not properly configured leading to errors
when encoding from a JPEG file.
2014-05-16 16:33:10 -04:00
Frank Bossen
e170b61137 Add support for JPEG input in cjpeg 2014-05-16 11:00:34 -04:00
Frank Bossen
ea4fad9aec Fix #50
Make trellis work with DCT implementations other than the default:
scale and store transform coefficients for trellis
2014-05-10 14:59:58 -04:00
Frank Bossen
4b1094cc3a Disable trellis in jpegtran
Trellis quantization is not supposed to be enabled in the jpegtran
application as it does not perform transform and quantization.
Should fix #49
2014-05-10 08:19:31 -04:00
Josh Aas
3f1e5d6842 Update version to 2.0pre. 2014-05-09 22:11:12 -05:00
Frank Bossen
93da07241d Merge branch 'trellis' 2014-05-09 18:28:26 -04:00
Frank Bossen
87254c1c44 Use single DC scan by default
Value of cinfo->one_dc_scan is set to true by default to use a single
DC scan for all components.
Option -onedcscan is replaced by -multidcscan to enable multiple DC
scans.
While this change appears to degrade compression performance it
improves compatibility with a wider range of JPEG decoders.
2014-05-09 10:46:00 -04:00
Josh Aas
a5195816f6 Add configure check for libm/pow. Fixes Linux build issue. 2014-05-08 22:25:29 -05:00
Frank Bossen
13e2115054 Add option to have single DC scan
Add option to have a single DC scan wherein all components are
interleaved when using progressive mode. This may resolve compatibility
issues raised in #29 and #48.
This option is available through -onedcscan in cjpeg
2014-05-08 17:33:14 -04:00
Frank Bossen
8a99fcac80 Correct comment 2014-05-08 17:00:53 -04:00
Frank Bossen
061d42c272 Fix #47
When specifying -debug or -verbose in the cjpeg application the scans
selected by the scan optimization process are printed to stderr
2014-05-08 16:44:33 -04:00
Frank Bossen
d236890325 Update copyright headers/statements 2014-05-08 16:42:51 -04:00
Frank Bossen
c8e03dbda5 Fix issue with trellis and no scan opt
Disabling scan optimization with trellis enabled was leading to
incorrect results
2014-05-08 15:50:22 -04:00
Frank Bossen
8b8d88c850 Improve cjpeg help text
List options related to trellis quantization in cjpeg help text
2014-05-05 11:38:43 -04:00
Frank Bossen
a5403fda93 Remove outdated and incorrect comment 2014-05-05 11:31:34 -04:00
Frank Bossen
c88aade31c Revert type change
Revert type of use_moz_defaults to boolean
2014-04-30 14:54:18 -04:00
Frank Bossen
101df25fde Modify trellis parameter defaults
Modify trellis parameters to optimize for PSNR-HVS by default
2014-04-29 14:03:34 -04:00
Frank Bossen
21b2f11a42 Fix issue with quantization matrix optimization
Update quantization matrix in trellis loop
2014-04-29 13:00:50 -04:00
Frank Bossen
cd3c32f15d Update trellis optimization parameters
Slightly improved parameters are provided when optimizing for SSIM
metric
2014-04-29 12:33:46 -04:00
Frank Bossen
87d506416f Fix issue when trellis is disabled
master->pass_number_scan_opt_base needs to be set to appropriate value
when trellis is disabled
2014-04-29 12:32:05 -04:00
Frank Bossen
b03b5797f4 Add optimization of quantization matrix
Optimizes quantization matrix by minimizing reconstruction error based
on quantized coefficients.
Feature is controlled by cinfo->trellis_q_opt; disabled by default.
2014-04-28 16:28:05 -04:00
Frank Bossen
e5f8575776 Add option to tune for MS-SSIM
Added -tune-ms-ssim option to cjpeg to tune for multiscale SSIM metric
2014-04-27 22:01:40 -04:00
Josh Aas
b36bec4d71 Merge pull request #44 from h0r14/master
turbojpeg warning [-Wattributes]
2014-04-27 20:47:01 -05:00
Horia Racoviceanu
62003f9ae5 turbojpeg warning [-Wattributes]
warning: always_inline function might not be inlinable
Patch from http://sourceforge.net/p/libjpeg-turbo/patches/56/
2014-04-27 02:39:59 +00:00
Josh Aas
7d7e24c60a Merge pull request #43 from reubenhwk/cleanup_v2
Cleanup v2
2014-04-24 08:22:24 -05:00
Reuben Hawkins
b4c7d90b3f bump version to v1.0.2 2014-04-23 20:19:47 -05:00
Reuben Hawkins
e4fa772b58 adjust_exif_parameters only needed in JPEG_LIB_VER > 70
The invocation of this function is wrapped in an ifdef JPEGLIB >70
but the definition of the function wasn't.  This change adds the
ifdef around the function definition.
2014-04-23 20:19:47 -05:00
Reuben Hawkins
2086f28340 tjbench.c: return retval in funcs defining it
the throw macros set retval, but not all functions use/return this
value.  This change, mainly to clean up compiler warnings, makes
those functions return a value.
2014-04-23 20:19:47 -05:00
Reuben Hawkins
548aeb977d turbojpeg.c: clean up warnings around getinstance
This macro defined two local variables, cinfo and dinfo, but both
aren't always used.  Add a (void)cinfo; and (void)dinfo in there
to hush up the compiler.
2014-04-17 23:00:01 -05:00
Reuben Hawkins
b93b80b3aa jcmaster.c: fix compiler warnings
* remove unused variable size[8]
* initialize base_scan_idx
2014-04-17 23:00:01 -05:00
Reuben Hawkins
706f2a8881 configure.ac: fix INLINE definition
The inline attribute must still be prefixed with 'inline' to work
correctly.
2014-04-17 23:00:01 -05:00
Reuben Hawkins
abffeb8390 configure.ac: enable silent build rules
Silent build rules make it much less likely for warnings to go by
unnoticed.
2014-04-17 23:00:01 -05:00
Reuben Hawkins
bd845c8691 configure.ac: fix some autoconf warnings 2014-04-17 23:00:01 -05:00
Reuben Hawkins
4e5e4787e4 configure.ac: use AC_LANG_SOURCE where appropriate 2014-04-17 23:00:01 -05:00
Reuben Hawkins
100ed0a5f9 bump version to v1.0.1 2014-04-17 23:00:01 -05:00
Frank Bossen
45c800e2d6 Fix #40
Improve code portability to deal with cases where:
- right shift is always unsigned
- size of int is not 32 bits
2014-04-15 18:17:09 +02:00
Frank Bossen
3fd6eec30b Remove comment on portability
Derivation of sign value relies on shift right operator >> being an
arithmetic shift. It is thus not strictly portable since the C standard
defines the result of x >> y as "implementation-defined" when x is a
signed integer with a negative value.
2014-04-15 15:23:30 +02:00
Frank Bossen
d273dc190c Fix #39
Avoid declaring variable in middle of code block
2014-04-15 15:07:55 +02:00
fbossen
5d4e113b06 Merge pull request #38 from pengvado/master
36% faster encode_mcu_AC_first(), by eliminating an unpredictable branch in the inner loop
2014-04-15 01:57:12 +02:00
Loren Merritt
8db334cde2 36% faster encode_mcu_AC_first(), by eliminating an unpredictable branch in the inner loop
Which corresponds to 15% faster overall encoding in "progressive scan optimization" mode.
(And a negligible speedup in -fastcrush mode.)
2014-04-13 05:30:44 +00:00
Frank Bossen
1733487e17 Add option to perform multiple trellis quantization iterations
Multiple trellis iterations may improve coding performance as Huffman
tables are updated with each iteration. In practice the benefit appears
to be very minimal
2014-04-01 23:14:29 +02:00
Frank Bossen
2012e32f19 Update trellis quantization to support progressive coding mode
Trellis quantization is modified:
- to work on the configurable spectral range Ss to Se
- to optionally optimize runs of EOBs
- to optionally split optimization between 2 spectral ranges
In trellis quantization passes Huffman table code optimization is
modified such as to generable a valid code length for each possible
symbol by resetting frequency counters to 1 instead of 0
2014-04-01 20:14:37 +02:00
Josh Aas
f4c556031c Merge pull request #32 from elfring/Complete_quoting_for_parameters_of_some_CMake_commands
Complete quoting for parameters of some CMake commands.
2014-04-01 11:46:48 -05:00
Markus Elfring
553e2cb89e Bug #17: Completed quoting for parameters of some CMake commands
A wiki article pointed out that whitespace will only be preserved for parameters
in CMake commands if passed strings will be appropriately quoted or escaped.
http://cmake.org/Wiki/CMake/Language_Syntax#CMake_splits_arguments_unless_you_use_quotation_marks_or_escapes.

Quoting was added so that more places should also handle file names correctly
which contain space characters or semicolons eventually.

Signed-off-by: Markus Elfring <elfring@users.sourceforge.net>
2014-04-01 17:47:42 +02:00
Frank Bossen
4d0329b235 Add option to disable trellis quantization 2014-03-28 18:16:46 +01:00
Frank Bossen
199fffb759 Enable combination of trellis quantization and scan optimization 2014-03-28 12:42:37 +01:00
Frank Bossen
2de8e97989 Add option to use lambda weighting table
Different lambda values may be used for each frequency in DCT domain.
The weighting table is currently not configurable but can be
enabled/disabled with cinfo-> use_lambda_weight_tbl
2014-03-26 00:06:07 +01:00
Frank Bossen
6f168e4f80 Add parameters to cjpeg to tune for different metrics
-tune-psnr, -tune-ssim and -tune-hvs-psnr are added to cjpeg to control
the trellis quantization process and optimize output for PSNR, SSIM and
HVS-PSNR distortion metrics
2014-03-25 11:48:30 +01:00
Frank Bossen
3e8afe7f94 Add option to control lambda parameter from command line
-lambda1 and -lambda2 command line parameters are added to cjpeg to
control trellis quantization
2014-03-24 20:51:46 +01:00
Frank Bossen
758ed27a05 Add option to use flat quantization table
Set cinfo->use_flat_quant_tbl to TRUE to use flat quantization table or
-flat option in cjpeg
2014-03-24 16:30:56 +01:00
Frank Bossen
d200b2c144 Initial implementation of trellis quantization
A new pass type trellis_pass is added. It defines a pass where trellis
quantization is done in the quantize_trellis() function.
Trellis quantization can be enabled by setting use_moz_defaults to 2 or
by using the -trellis option in cjpeg
Note that trellis does currently not work with scan optimization. Scan
optimization is disabled when trellis is enabled.
2014-03-23 21:06:01 +01:00
40 changed files with 5643 additions and 394 deletions

View File

@@ -5,11 +5,11 @@
cmake_minimum_required(VERSION 2.6)
project(libmozjpeg C)
set(VERSION 1.0.0)
set(VERSION 2.1)
if(MINGW OR CYGWIN)
execute_process(COMMAND "date" "+%Y%m%d" OUTPUT_VARIABLE BUILD)
string(REGEX REPLACE "\n" "" BUILD ${BUILD})
string(REGEX REPLACE "\n" "" BUILD "${BUILD}")
elseif(WIN32)
execute_process(COMMAND "wmic.exe" "os" "get" "LocalDateTime" OUTPUT_VARIABLE
BUILD)
@@ -141,7 +141,7 @@ message(STATUS "Install directory = ${CMAKE_INSTALL_PREFIX}")
configure_file(win/jconfig.h.in jconfig.h)
configure_file(win/config.h.in config.h)
include_directories(${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_SOURCE_DIR})
include_directories("${CMAKE_CURRENT_BINARY_DIR}" "${CMAKE_SOURCE_DIR}")
if(WITH_JAVA)
find_package(Java)
@@ -247,7 +247,7 @@ set_property(TARGET tjbench-static PROPERTY COMPILE_FLAGS
"-DBMP_SUPPORTED -DPPM_SUPPORTED")
add_executable(cjpeg-static cjpeg.c cdjpeg.c rdbmp.c rdgif.c rdppm.c rdswitch.c
rdtarga.c)
rdtarga.c rdjpeg.c)
set_property(TARGET cjpeg-static PROPERTY COMPILE_FLAGS
"-DBMP_SUPPORTED -DGIF_SUPPORTED -DPPM_SUPPORTED -DTARGA_SUPPORTED -DUSE_SETMODE")
target_link_libraries(cjpeg-static jpeg-static)
@@ -264,7 +264,7 @@ set_property(TARGET jpegtran-static PROPERTY COMPILE_FLAGS "-DUSE_SETMODE")
add_executable(rdjpgcom rdjpgcom.c)
add_executable(wrjpgcom rdjpgcom.c)
add_executable(wrjpgcom wrjpgcom.c)
#
@@ -313,133 +313,133 @@ set(MD5_JPEG_PROG_ARI 0a8f1c8f66e113c3cf635df0a475a617)
set(MD5_JPEG_CROP b4197f377e621c4e9b1d20471432610d)
if(WITH_JAVA)
add_test(TJUnitTest ${JAVA_RUNTIME} -cp java/${OBJDIR}turbojpeg.jar -Djava.library.path=${CMAKE_CURRENT_BINARY_DIR}/${OBJDIR} TJUnitTest)
add_test(TJUnitTest-yuv ${JAVA_RUNTIME} -cp java/${OBJDIR}turbojpeg.jar -Djava.library.path=${CMAKE_CURRENT_BINARY_DIR}/${OBJDIR} TJUnitTest -yuv)
add_test(TJUnitTest-yuv-nopad ${JAVA_RUNTIME} -cp java/${OBJDIR}turbojpeg.jar -Djava.library.path=${CMAKE_CURRENT_BINARY_DIR}/${OBJDIR} TJUnitTest -yuv -noyuvpad)
add_test(TJUnitTest-bi ${JAVA_RUNTIME} -cp java/${OBJDIR}turbojpeg.jar -Djava.library.path=${CMAKE_CURRENT_BINARY_DIR}/${OBJDIR} TJUnitTest -bi)
add_test(TJUnitTest-bi-yuv ${JAVA_RUNTIME} -cp java/${OBJDIR}turbojpeg.jar -Djava.library.path=${CMAKE_CURRENT_BINARY_DIR}/${OBJDIR} TJUnitTest -bi -yuv)
add_test(TJUnitTest-bi-yuv-nopad ${JAVA_RUNTIME} -cp java/${OBJDIR}turbojpeg.jar -Djava.library.path=${CMAKE_CURRENT_BINARY_DIR}/${OBJDIR} TJUnitTest -bi -yuv -noyuvpad)
add_test(TJUnitTest ${JAVA_RUNTIME} -cp "java/${OBJDIR}turbojpeg.jar" "-Djava.library.path=${CMAKE_CURRENT_BINARY_DIR}/${OBJDIR}" TJUnitTest)
add_test(TJUnitTest-yuv ${JAVA_RUNTIME} -cp "java/${OBJDIR}turbojpeg.jar" "-Djava.library.path=${CMAKE_CURRENT_BINARY_DIR}/${OBJDIR}" TJUnitTest -yuv)
add_test(TJUnitTest-yuv-nopad ${JAVA_RUNTIME} -cp "java/${OBJDIR}turbojpeg.jar" "-Djava.library.path=${CMAKE_CURRENT_BINARY_DIR}/${OBJDIR}" TJUnitTest -yuv -noyuvpad)
add_test(TJUnitTest-bi ${JAVA_RUNTIME} -cp "java/${OBJDIR}turbojpeg.jar" "-Djava.library.path=${CMAKE_CURRENT_BINARY_DIR}/${OBJDIR}" TJUnitTest -bi)
add_test(TJUnitTest-bi-yuv ${JAVA_RUNTIME} -cp "java/${OBJDIR}turbojpeg.jar" "-Djava.library.path=${CMAKE_CURRENT_BINARY_DIR}/${OBJDIR}" TJUnitTest -bi -yuv)
add_test(TJUnitTest-bi-yuv-nopad ${JAVA_RUNTIME} -cp "java/${OBJDIR}turbojpeg.jar" "-Djava.library.path=${CMAKE_CURRENT_BINARY_DIR}/${OBJDIR}" TJUnitTest -bi -yuv -noyuvpad)
endif()
add_test(tjunittest tjunittest)
add_test(tjunittest-alloc tjunittest -alloc)
add_test(tjunittest-yuv tjunittest -yuv)
add_test(tjunittest-yuv-alloc tjunittest -yuv -alloc)
add_test(tjunittest-yuv-nopad tjunittest -yuv -noyuvpad)
add_test(cjpeg-int sharedlib/cjpeg -dct int -outfile testoutint.jpg ${CMAKE_SOURCE_DIR}/testimages/testorig.ppm)
add_test(cjpeg-int-cmp ${CMAKE_COMMAND} -DMD5=${MD5_JPEG_INT} -DFILE=testoutint.jpg -P ${CMAKE_SOURCE_DIR}/cmakescripts/md5cmp.cmake)
add_test(cjpeg-fast sharedlib/cjpeg -dct fast -opt -outfile testoutfst.jpg ${CMAKE_SOURCE_DIR}/testimages/testorig.ppm)
add_test(cjpeg-fast-cmp ${CMAKE_COMMAND} -DMD5=${MD5_JPEG_FAST} -DFILE=testoutfst.jpg -P ${CMAKE_SOURCE_DIR}/cmakescripts/md5cmp.cmake)
add_test(cjpeg-fast-100 sharedlib/cjpeg -dct fast -quality 100 -opt -outfile testoutfst100.jpg ${CMAKE_SOURCE_DIR}/testimages/testorig.ppm)
add_test(cjpeg-fast-100-cmp ${CMAKE_COMMAND} -DMD5=${MD5_JPEG_FAST_100} -DFILE=testoutfst100.jpg -P ${CMAKE_SOURCE_DIR}/cmakescripts/md5cmp.cmake)
add_test(cjpeg-float sharedlib/cjpeg -dct float -outfile testoutflt.jpg ${CMAKE_SOURCE_DIR}/testimages/testorig.ppm)
add_test(cjpeg-int sharedlib/cjpeg -dct int -outfile testoutint.jpg "${CMAKE_SOURCE_DIR}/testimages/testorig.ppm")
add_test(cjpeg-int-cmp "${CMAKE_COMMAND}" -DMD5=${MD5_JPEG_INT} -DFILE=testoutint.jpg -P "${CMAKE_SOURCE_DIR}/cmakescripts/md5cmp.cmake")
add_test(cjpeg-fast sharedlib/cjpeg -dct fast -opt -outfile testoutfst.jpg "${CMAKE_SOURCE_DIR}/testimages/testorig.ppm")
add_test(cjpeg-fast-cmp "${CMAKE_COMMAND}" -DMD5=${MD5_JPEG_FAST} -DFILE=testoutfst.jpg -P "${CMAKE_SOURCE_DIR}/cmakescripts/md5cmp.cmake")
add_test(cjpeg-fast-100 sharedlib/cjpeg -dct fast -quality 100 -opt -outfile testoutfst100.jpg "${CMAKE_SOURCE_DIR}/testimages/testorig.ppm")
add_test(cjpeg-fast-100-cmp "${CMAKE_COMMAND}" -DMD5=${MD5_JPEG_FAST_100} -DFILE=testoutfst100.jpg -P "${CMAKE_SOURCE_DIR}/cmakescripts/md5cmp.cmake")
add_test(cjpeg-float sharedlib/cjpeg -dct float -outfile testoutflt.jpg "${CMAKE_SOURCE_DIR}/testimages/testorig.ppm")
if(WITH_SIMD)
add_test(cjpeg-float-cmp ${CMAKE_COMMAND} -DMD5=${MD5_JPEG_FLOAT} -DFILE=testoutflt.jpg -P ${CMAKE_SOURCE_DIR}/cmakescripts/md5cmp.cmake)
add_test(cjpeg-float-cmp "${CMAKE_COMMAND}" -DMD5=${MD5_JPEG_FLOAT} -DFILE=testoutflt.jpg -P "${CMAKE_SOURCE_DIR}/cmakescripts/md5cmp.cmake")
else()
add_test(cjpeg-float-cmp ${CMAKE_COMMAND} -DMD5=${MD5_JPEG_FLOAT_NOSIMD} -DFILE=testoutflt.jpg -P ${CMAKE_SOURCE_DIR}/cmakescripts/md5cmp.cmake)
add_test(cjpeg-float-cmp "${CMAKE_COMMAND}" -DMD5=${MD5_JPEG_FLOAT_NOSIMD} -DFILE=testoutflt.jpg -P "${CMAKE_SOURCE_DIR}/cmakescripts/md5cmp.cmake")
endif()
add_test(cjpeg-int-gray sharedlib/cjpeg -dct int -grayscale -outfile testoutgray.jpg ${CMAKE_SOURCE_DIR}/testimages/testorig.ppm)
add_test(cjpeg-int-gray-cmp ${CMAKE_COMMAND} -DMD5=${MD5_JPEG_INT_GRAY} -DFILE=testoutgray.jpg -P ${CMAKE_SOURCE_DIR}/cmakescripts/md5cmp.cmake)
add_test(djpeg-int sharedlib/djpeg -dct int -fast -ppm -outfile testoutint.ppm ${CMAKE_SOURCE_DIR}/testimages/testorig.jpg)
add_test(djpeg-int-cmp ${CMAKE_COMMAND} -DMD5=${MD5_PPM_INT} -DFILE=testoutint.ppm -P ${CMAKE_SOURCE_DIR}/cmakescripts/md5cmp.cmake)
add_test(djpeg-fast sharedlib/djpeg -dct fast -ppm -outfile testoutfst.ppm ${CMAKE_SOURCE_DIR}/testimages/testorig.jpg)
add_test(djpeg-fast-cmp ${CMAKE_COMMAND} -DMD5=${MD5_PPM_FAST} -DFILE=testoutfst.ppm -P ${CMAKE_SOURCE_DIR}/cmakescripts/md5cmp.cmake)
add_test(djpeg-float sharedlib/djpeg -dct float -ppm -outfile testoutflt.ppm ${CMAKE_SOURCE_DIR}/testimages/testorig.jpg)
add_test(cjpeg-int-gray sharedlib/cjpeg -dct int -grayscale -outfile testoutgray.jpg "${CMAKE_SOURCE_DIR}/testimages/testorig.ppm")
add_test(cjpeg-int-gray-cmp "${CMAKE_COMMAND}" -DMD5=${MD5_JPEG_INT_GRAY} -DFILE=testoutgray.jpg -P "${CMAKE_SOURCE_DIR}/cmakescripts/md5cmp.cmake")
add_test(djpeg-int sharedlib/djpeg -dct int -fast -ppm -outfile testoutint.ppm "${CMAKE_SOURCE_DIR}/testimages/testorig.jpg")
add_test(djpeg-int-cmp "${CMAKE_COMMAND}" -DMD5=${MD5_PPM_INT} -DFILE=testoutint.ppm -P "${CMAKE_SOURCE_DIR}/cmakescripts/md5cmp.cmake")
add_test(djpeg-fast sharedlib/djpeg -dct fast -ppm -outfile testoutfst.ppm "${CMAKE_SOURCE_DIR}/testimages/testorig.jpg")
add_test(djpeg-fast-cmp "${CMAKE_COMMAND}" -DMD5=${MD5_PPM_FAST} -DFILE=testoutfst.ppm -P "${CMAKE_SOURCE_DIR}/cmakescripts/md5cmp.cmake")
add_test(djpeg-float sharedlib/djpeg -dct float -ppm -outfile testoutflt.ppm "${CMAKE_SOURCE_DIR}/testimages/testorig.jpg")
if(WITH_SIMD)
add_test(djpeg-float-cmp ${CMAKE_COMMAND} -DMD5=${MD5_PPM_FLOAT} -DFILE=testoutflt.ppm -P ${CMAKE_SOURCE_DIR}/cmakescripts/md5cmp.cmake)
add_test(djpeg-float-cmp "${CMAKE_COMMAND}" -DMD5=${MD5_PPM_FLOAT} -DFILE=testoutflt.ppm -P "${CMAKE_SOURCE_DIR}/cmakescripts/md5cmp.cmake")
else()
add_test(djpeg-float-cmp ${CMAKE_COMMAND} -DMD5=${MD5_PPM_FLOAT_NOSIMD} -DFILE=testoutflt.ppm -P ${CMAKE_SOURCE_DIR}/cmakescripts/md5cmp.cmake)
add_test(djpeg-float-cmp "${CMAKE_COMMAND}" -DMD5=${MD5_PPM_FLOAT_NOSIMD} -DFILE=testoutflt.ppm -P "${CMAKE_SOURCE_DIR}/cmakescripts/md5cmp.cmake")
endif()
foreach(scale 2_1 15_8 7_4 13_8 3_2 11_8 5_4 9_8 7_8 3_4 5_8 1_2 3_8 1_4 1_8)
string(REGEX REPLACE "_" "/" scalearg ${scale})
add_test(djpeg-int-${scale} sharedlib/djpeg -dct int -nosmooth -scale ${scalearg} -ppm -outfile testoutint${scale}.ppm ${CMAKE_SOURCE_DIR}/testimages/testorig.jpg)
add_test(djpeg-int-${scale}-cmp ${CMAKE_COMMAND} -DMD5=${MD5_PPM_INT_${scale}} -DFILE=testoutint${scale}.ppm -P ${CMAKE_SOURCE_DIR}/cmakescripts/md5cmp.cmake)
add_test(djpeg-int-${scale} sharedlib/djpeg -dct int -nosmooth -scale ${scalearg} -ppm -outfile testoutint${scale}.ppm "${CMAKE_SOURCE_DIR}/testimages/testorig.jpg")
add_test(djpeg-int-${scale}-cmp "${CMAKE_COMMAND}" -DMD5=${MD5_PPM_INT_${scale}} -DFILE=testoutint${scale}.ppm -P "${CMAKE_SOURCE_DIR}/cmakescripts/md5cmp.cmake")
endforeach()
add_test(djpeg-fast-1_2 sharedlib/djpeg -dct fast -scale 1/2 -ppm -outfile testoutfst1_2.ppm ${CMAKE_SOURCE_DIR}/testimages/testorig.jpg)
add_test(djpeg-fast-1_2-cmp ${CMAKE_COMMAND} -DMD5=${MD5_PPM_FAST_1_2} -DFILE=testoutfst1_2.ppm -P ${CMAKE_SOURCE_DIR}/cmakescripts/md5cmp.cmake)
add_test(djpeg-256 sharedlib/djpeg -dct int -bmp -colors 256 -outfile testout.bmp ${CMAKE_SOURCE_DIR}/testimages/testorig.jpg)
add_test(djpeg-256-cmp ${CMAKE_COMMAND} -DMD5=${MD5_BMP_256} -DFILE=testout.bmp -P ${CMAKE_SOURCE_DIR}/cmakescripts/md5cmp.cmake)
add_test(cjpeg-prog sharedlib/cjpeg -dct int -progressive -outfile testoutp.jpg ${CMAKE_SOURCE_DIR}/testimages/testorig.ppm)
add_test(cjpeg-prog-cmp ${CMAKE_COMMAND} -DMD5=${MD5_JPEG_PROG} -DFILE=testoutp.jpg -P ${CMAKE_SOURCE_DIR}/cmakescripts/md5cmp.cmake)
add_test(jpegtran-prog sharedlib/jpegtran -outfile testoutt.jpg testoutp.jpg)
add_test(jpegtran-prog-cmp ${CMAKE_COMMAND} -DMD5=${MD5_JPEG_INT} -DFILE=testoutt.jpg -P ${CMAKE_SOURCE_DIR}/cmakescripts/md5cmp.cmake)
add_test(djpeg-fast-1_2 sharedlib/djpeg -dct fast -scale 1/2 -ppm -outfile testoutfst1_2.ppm "${CMAKE_SOURCE_DIR}/testimages/testorig.jpg")
add_test(djpeg-fast-1_2-cmp "${CMAKE_COMMAND}" -DMD5=${MD5_PPM_FAST_1_2} -DFILE=testoutfst1_2.ppm -P "${CMAKE_SOURCE_DIR}/cmakescripts/md5cmp.cmake")
add_test(djpeg-256 sharedlib/djpeg -dct int -bmp -colors 256 -outfile testout.bmp "${CMAKE_SOURCE_DIR}/testimages/testorig.jpg")
add_test(djpeg-256-cmp "${CMAKE_COMMAND}" -DMD5=${MD5_BMP_256} -DFILE=testout.bmp -P "${CMAKE_SOURCE_DIR}/cmakescripts/md5cmp.cmake")
add_test(cjpeg-prog sharedlib/cjpeg -dct int -progressive -outfile testoutp.jpg "${CMAKE_SOURCE_DIR}/testimages/testorig.ppm")
add_test(cjpeg-prog-cmp "${CMAKE_COMMAND}" -DMD5=${MD5_JPEG_PROG} -DFILE=testoutp.jpg -P "${CMAKE_SOURCE_DIR}/cmakescripts/md5cmp.cmake")
add_test(jpegtran-prog sharedlib/jpegtran -outfile testoutt.jpg testoutp.jpg")
add_test(jpegtran-prog-cmp "${CMAKE_COMMAND}" -DMD5=${MD5_JPEG_INT} -DFILE=testoutt.jpg -P "${CMAKE_SOURCE_DIR}/cmakescripts/md5cmp.cmake")
if(WITH_ARITH_ENC)
add_test(cjpeg-ari sharedlib/cjpeg -dct int -arithmetic -outfile testoutari.jpg ${CMAKE_SOURCE_DIR}/testimages/testorig.ppm)
add_test(cjpeg-ari-cmp ${CMAKE_COMMAND} -DMD5=${MD5_JPEG_ARI} -DFILE=testoutari.jpg -P ${CMAKE_SOURCE_DIR}/cmakescripts/md5cmp.cmake )
add_test(jpegtran-toari sharedlib/jpegtran -arithmetic -outfile testouta.jpg ${CMAKE_SOURCE_DIR}/testimages/testimgint.jpg)
add_test(jpegtran-toari-cmp ${CMAKE_COMMAND} -DMD5=${MD5_JPEG_ARI} -DFILE=testouta.jpg -P ${CMAKE_SOURCE_DIR}/cmakescripts/md5cmp.cmake)
add_test(cjpeg-prog-ari sharedlib/cjpeg -dct int -progressive -arithmetic -sample 1x1 -outfile testoutpa.jpg ${CMAKE_SOURCE_DIR}/testimages/testorig.ppm)
add_test(cjpeg-prog-ari-cmp ${CMAKE_COMMAND} -DMD5=${MD5_JPEG_PROG_ARI} -DFILE=testoutpa.jpg -P ${CMAKE_SOURCE_DIR}/cmakescripts/md5cmp.cmake )
add_test(cjpeg-ari sharedlib/cjpeg -dct int -arithmetic -outfile testoutari.jpg "${CMAKE_SOURCE_DIR}/testimages/testorig.ppm")
add_test(cjpeg-ari-cmp "${CMAKE_COMMAND}" -DMD5=${MD5_JPEG_ARI} -DFILE=testoutari.jpg -P "${CMAKE_SOURCE_DIR}/cmakescripts/md5cmp.cmake")
add_test(jpegtran-toari sharedlib/jpegtran -arithmetic -outfile testouta.jpg "${CMAKE_SOURCE_DIR}/testimages/testimgint.jpg")
add_test(jpegtran-toari-cmp "${CMAKE_COMMAND}" -DMD5=${MD5_JPEG_ARI} -DFILE=testouta.jpg -P "${CMAKE_SOURCE_DIR}/cmakescripts/md5cmp.cmake")
add_test(cjpeg-prog-ari sharedlib/cjpeg -dct int -progressive -arithmetic -sample 1x1 -outfile testoutpa.jpg "${CMAKE_SOURCE_DIR}/testimages/testorig.ppm")
add_test(cjpeg-prog-ari-cmp "${CMAKE_COMMAND}" -DMD5=${MD5_JPEG_PROG_ARI} -DFILE=testoutpa.jpg -P "${CMAKE_SOURCE_DIR}/cmakescripts/md5cmp.cmake")
endif()
if(WITH_ARITH_DEC)
add_test(djpeg-ari sharedlib/djpeg -dct int -fast -ppm -outfile testoutari.ppm ${CMAKE_SOURCE_DIR}/testimages/testimgari.jpg)
add_test(djpeg-ari-cmp ${CMAKE_COMMAND} -DMD5=${MD5_PPM_ARI} -DFILE=testoutari.ppm -P ${CMAKE_SOURCE_DIR}/cmakescripts/md5cmp.cmake)
add_test(jpegtran-fromari sharedlib/jpegtran -outfile testouta.jpg ${CMAKE_SOURCE_DIR}/testimages/testimgari.jpg)
add_test(jpegtran-fromari-cmp ${CMAKE_COMMAND} -DMD5=${MD5_JPEG_INT} -DFILE=testouta.jpg -P ${CMAKE_SOURCE_DIR}/cmakescripts/md5cmp.cmake)
add_test(djpeg-ari sharedlib/djpeg -dct int -fast -ppm -outfile testoutari.ppm "${CMAKE_SOURCE_DIR}/testimages/testimgari.jpg")
add_test(djpeg-ari-cmp "${CMAKE_COMMAND}" -DMD5=${MD5_PPM_ARI} -DFILE=testoutari.ppm -P "${CMAKE_SOURCE_DIR}/cmakescripts/md5cmp.cmake")
add_test(jpegtran-fromari sharedlib/jpegtran -outfile testouta.jpg "${CMAKE_SOURCE_DIR}/testimages/testimgari.jpg")
add_test(jpegtran-fromari-cmp "${CMAKE_COMMAND}" -DMD5=${MD5_JPEG_INT} -DFILE=testouta.jpg -P "${CMAKE_SOURCE_DIR}/cmakescripts/md5cmp.cmake")
endif()
add_test(jpegtran-crop sharedlib/jpegtran -crop 120x90+20+50 -transpose -perfect -outfile testoutcrop.jpg ${CMAKE_SOURCE_DIR}/testimages/testorig.jpg)
add_test(jpegtran-crop-cmp ${CMAKE_COMMAND} -DMD5=${MD5_JPEG_CROP} -DFILE=testoutcrop.jpg -P ${CMAKE_SOURCE_DIR}/cmakescripts/md5cmp.cmake)
add_test(jpegtran-crop sharedlib/jpegtran -crop 120x90+20+50 -transpose -perfect -outfile testoutcrop.jpg "${CMAKE_SOURCE_DIR}/testimages/testorig.jpg")
add_test(jpegtran-crop-cmp "${CMAKE_COMMAND}" -DMD5=${MD5_JPEG_CROP} -DFILE=testoutcrop.jpg -P "${CMAKE_SOURCE_DIR}/cmakescripts/md5cmp.cmake")
add_test(tjunittest-static tjunittest-static)
add_test(tjunittest-static-alloc tjunittest-static -alloc)
add_test(tjunittest-static-yuv tjunittest-static -yuv)
add_test(tjunittest-static-yuv-alloc tjunittest-static -yuv -alloc)
add_test(tjunittest-static-yuv-nopad tjunittest-static -yuv -noyuvpad)
add_test(cjpeg-static-int cjpeg-static -dct int -outfile testoutint.jpg ${CMAKE_SOURCE_DIR}/testimages/testorig.ppm)
add_test(cjpeg-static-int-cmp ${CMAKE_COMMAND} -DMD5=${MD5_JPEG_INT} -DFILE=testoutint.jpg -P ${CMAKE_SOURCE_DIR}/cmakescripts/md5cmp.cmake)
add_test(cjpeg-static-fast cjpeg-static -dct fast -opt -outfile testoutfst.jpg ${CMAKE_SOURCE_DIR}/testimages/testorig.ppm)
add_test(cjpeg-static-fast-cmp ${CMAKE_COMMAND} -DMD5=${MD5_JPEG_FAST} -DFILE=testoutfst.jpg -P ${CMAKE_SOURCE_DIR}/cmakescripts/md5cmp.cmake)
add_test(cjpeg-static-fast-100 cjpeg-static -dct fast -quality 100 -opt -outfile testoutfst100.jpg ${CMAKE_SOURCE_DIR}/testimages/testorig.ppm)
add_test(cjpeg-static-fast-100-cmp ${CMAKE_COMMAND} -DMD5=${MD5_JPEG_FAST_100} -DFILE=testoutfst100.jpg -P ${CMAKE_SOURCE_DIR}/cmakescripts/md5cmp.cmake)
add_test(cjpeg-static-float cjpeg-static -dct float -outfile testoutflt.jpg ${CMAKE_SOURCE_DIR}/testimages/testorig.ppm)
add_test(cjpeg-static-int cjpeg-static -dct int -outfile testoutint.jpg "${CMAKE_SOURCE_DIR}/testimages/testorig.ppm")
add_test(cjpeg-static-int-cmp "${CMAKE_COMMAND}" -DMD5=${MD5_JPEG_INT} -DFILE=testoutint.jpg -P "${CMAKE_SOURCE_DIR}/cmakescripts/md5cmp.cmake")
add_test(cjpeg-static-fast cjpeg-static -dct fast -opt -outfile testoutfst.jpg "${CMAKE_SOURCE_DIR}/testimages/testorig.ppm")
add_test(cjpeg-static-fast-cmp "${CMAKE_COMMAND}" -DMD5=${MD5_JPEG_FAST} -DFILE=testoutfst.jpg -P "${CMAKE_SOURCE_DIR}/cmakescripts/md5cmp.cmake")
add_test(cjpeg-static-fast-100 cjpeg-static -dct fast -quality 100 -opt -outfile testoutfst100.jpg "${CMAKE_SOURCE_DIR}/testimages/testorig.ppm")
add_test(cjpeg-static-fast-100-cmp "${CMAKE_COMMAND}" -DMD5=${MD5_JPEG_FAST_100} -DFILE=testoutfst100.jpg -P "${CMAKE_SOURCE_DIR}/cmakescripts/md5cmp.cmake")
add_test(cjpeg-static-float cjpeg-static -dct float -outfile testoutflt.jpg "${CMAKE_SOURCE_DIR}/testimages/testorig.ppm")
if(WITH_SIMD)
add_test(cjpeg-static-float-cmp ${CMAKE_COMMAND} -DMD5=${MD5_JPEG_FLOAT} -DFILE=testoutflt.jpg -P ${CMAKE_SOURCE_DIR}/cmakescripts/md5cmp.cmake)
add_test(cjpeg-static-float-cmp "${CMAKE_COMMAND}" -DMD5=${MD5_JPEG_FLOAT} -DFILE=testoutflt.jpg -P "${CMAKE_SOURCE_DIR}/cmakescripts/md5cmp.cmake")
else()
add_test(cjpeg-static-float-cmp ${CMAKE_COMMAND} -DMD5=${MD5_JPEG_FLOAT_NOSIMD} -DFILE=testoutflt.jpg -P ${CMAKE_SOURCE_DIR}/cmakescripts/md5cmp.cmake)
add_test(cjpeg-static-float-cmp "${CMAKE_COMMAND}" -DMD5=${MD5_JPEG_FLOAT_NOSIMD} -DFILE=testoutflt.jpg -P "${CMAKE_SOURCE_DIR}/cmakescripts/md5cmp.cmake")
endif()
add_test(cjpeg-static-int-gray cjpeg-static -dct int -grayscale -outfile testoutgray.jpg ${CMAKE_SOURCE_DIR}/testimages/testorig.ppm)
add_test(cjpeg-static-int-gray-cmp ${CMAKE_COMMAND} -DMD5=${MD5_JPEG_INT_GRAY} -DFILE=testoutgray.jpg -P ${CMAKE_SOURCE_DIR}/cmakescripts/md5cmp.cmake)
add_test(djpeg-static-int djpeg-static -dct int -fast -ppm -outfile testoutint.ppm ${CMAKE_SOURCE_DIR}/testimages/testorig.jpg)
add_test(djpeg-static-int-cmp ${CMAKE_COMMAND} -DMD5=${MD5_PPM_INT} -DFILE=testoutint.ppm -P ${CMAKE_SOURCE_DIR}/cmakescripts/md5cmp.cmake)
add_test(djpeg-static-fast djpeg-static -dct fast -ppm -outfile testoutfst.ppm ${CMAKE_SOURCE_DIR}/testimages/testorig.jpg)
add_test(djpeg-static-fast-cmp ${CMAKE_COMMAND} -DMD5=${MD5_PPM_FAST} -DFILE=testoutfst.ppm -P ${CMAKE_SOURCE_DIR}/cmakescripts/md5cmp.cmake)
add_test(djpeg-static-float djpeg-static -dct float -ppm -outfile testoutflt.ppm ${CMAKE_SOURCE_DIR}/testimages/testorig.jpg)
add_test(cjpeg-static-int-gray cjpeg-static -dct int -grayscale -outfile testoutgray.jpg "${CMAKE_SOURCE_DIR}/testimages/testorig.ppm")
add_test(cjpeg-static-int-gray-cmp "${CMAKE_COMMAND}" -DMD5=${MD5_JPEG_INT_GRAY} -DFILE=testoutgray.jpg -P "${CMAKE_SOURCE_DIR}/cmakescripts/md5cmp.cmake")
add_test(djpeg-static-int djpeg-static -dct int -fast -ppm -outfile testoutint.ppm "${CMAKE_SOURCE_DIR}/testimages/testorig.jpg")
add_test(djpeg-static-int-cmp "${CMAKE_COMMAND}" -DMD5=${MD5_PPM_INT} -DFILE=testoutint.ppm -P "${CMAKE_SOURCE_DIR}/cmakescripts/md5cmp.cmake")
add_test(djpeg-static-fast djpeg-static -dct fast -ppm -outfile testoutfst.ppm "${CMAKE_SOURCE_DIR}/testimages/testorig.jpg")
add_test(djpeg-static-fast-cmp "${CMAKE_COMMAND}" -DMD5=${MD5_PPM_FAST} -DFILE=testoutfst.ppm -P "${CMAKE_SOURCE_DIR}/cmakescripts/md5cmp.cmake")
add_test(djpeg-static-float djpeg-static -dct float -ppm -outfile testoutflt.ppm "${CMAKE_SOURCE_DIR}/testimages/testorig.jpg")
if(WITH_SIMD)
add_test(djpeg-static-float-cmp ${CMAKE_COMMAND} -DMD5=${MD5_PPM_FLOAT} -DFILE=testoutflt.ppm -P ${CMAKE_SOURCE_DIR}/cmakescripts/md5cmp.cmake)
add_test(djpeg-static-float-cmp "${CMAKE_COMMAND}" -DMD5=${MD5_PPM_FLOAT} -DFILE=testoutflt.ppm -P "${CMAKE_SOURCE_DIR}/cmakescripts/md5cmp.cmake")
else()
add_test(djpeg-static-float-cmp ${CMAKE_COMMAND} -DMD5=${MD5_PPM_FLOAT_NOSIMD} -DFILE=testoutflt.ppm -P ${CMAKE_SOURCE_DIR}/cmakescripts/md5cmp.cmake)
add_test(djpeg-static-float-cmp "${CMAKE_COMMAND}" -DMD5=${MD5_PPM_FLOAT_NOSIMD} -DFILE=testoutflt.ppm -P "${CMAKE_SOURCE_DIR}/cmakescripts/md5cmp.cmake")
endif()
foreach(scale 2_1 15_8 7_4 13_8 3_2 11_8 5_4 9_8 7_8 3_4 5_8 1_2 3_8 1_4 1_8)
string(REGEX REPLACE "_" "/" scalearg ${scale})
add_test(djpeg-static-int-${scale} djpeg-static -dct int -nosmooth -scale ${scalearg} -ppm -outfile testoutint${scale}.ppm ${CMAKE_SOURCE_DIR}/testimages/testorig.jpg)
add_test(djpeg-static-int-${scale}-cmp ${CMAKE_COMMAND} -DMD5=${MD5_PPM_INT_${scale}} -DFILE=testoutint${scale}.ppm -P ${CMAKE_SOURCE_DIR}/cmakescripts/md5cmp.cmake)
add_test(djpeg-static-int-${scale} djpeg-static -dct int -nosmooth -scale ${scalearg} -ppm -outfile testoutint${scale}.ppm "${CMAKE_SOURCE_DIR}/testimages/testorig.jpg")
add_test(djpeg-static-int-${scale}-cmp "${CMAKE_COMMAND}" -DMD5=${MD5_PPM_INT_${scale}} -DFILE=testoutint${scale}.ppm -P "${CMAKE_SOURCE_DIR}/cmakescripts/md5cmp.cmake")
endforeach()
add_test(djpeg-static-fast-1_2 djpeg-static -dct fast -scale 1/2 -ppm -outfile testoutfst1_2.ppm ${CMAKE_SOURCE_DIR}/testimages/testorig.jpg)
add_test(djpeg-static-fast-1_2-cmp ${CMAKE_COMMAND} -DMD5=${MD5_PPM_FAST_1_2} -DFILE=testoutfst1_2.ppm -P ${CMAKE_SOURCE_DIR}/cmakescripts/md5cmp.cmake)
add_test(djpeg-static-256 djpeg-static -dct int -bmp -colors 256 -outfile testout.bmp ${CMAKE_SOURCE_DIR}/testimages/testorig.jpg)
add_test(djpeg-static-256-cmp ${CMAKE_COMMAND} -DMD5=${MD5_BMP_256} -DFILE=testout.bmp -P ${CMAKE_SOURCE_DIR}/cmakescripts/md5cmp.cmake)
add_test(cjpeg-static-prog cjpeg-static -dct int -progressive -outfile testoutp.jpg ${CMAKE_SOURCE_DIR}/testimages/testorig.ppm)
add_test(cjpeg-static-prog-cmp ${CMAKE_COMMAND} -DMD5=${MD5_JPEG_PROG} -DFILE=testoutp.jpg -P ${CMAKE_SOURCE_DIR}/cmakescripts/md5cmp.cmake)
add_test(jpegtran-static-prog jpegtran-static -outfile testoutt.jpg testoutp.jpg)
add_test(jpegtran-static-prog-cmp ${CMAKE_COMMAND} -DMD5=${MD5_JPEG_INT} -DFILE=testoutt.jpg -P ${CMAKE_SOURCE_DIR}/cmakescripts/md5cmp.cmake)
add_test(djpeg-static-fast-1_2 djpeg-static -dct fast -scale 1/2 -ppm -outfile testoutfst1_2.ppm "${CMAKE_SOURCE_DIR}/testimages/testorig.jpg")
add_test(djpeg-static-fast-1_2-cmp "${CMAKE_COMMAND}" -DMD5=${MD5_PPM_FAST_1_2} -DFILE=testoutfst1_2.ppm -P "${CMAKE_SOURCE_DIR}/cmakescripts/md5cmp.cmake")
add_test(djpeg-static-256 djpeg-static -dct int -bmp -colors 256 -outfile testout.bmp "${CMAKE_SOURCE_DIR}/testimages/testorig.jpg")
add_test(djpeg-static-256-cmp "${CMAKE_COMMAND}" -DMD5=${MD5_BMP_256} -DFILE=testout.bmp -P "${CMAKE_SOURCE_DIR}/cmakescripts/md5cmp.cmake")
add_test(cjpeg-static-prog cjpeg-static -dct int -progressive -outfile testoutp.jpg "${CMAKE_SOURCE_DIR}/testimages/testorig.ppm")
add_test(cjpeg-static-prog-cmp "${CMAKE_COMMAND}" -DMD5=${MD5_JPEG_PROG} -DFILE=testoutp.jpg -P "${CMAKE_SOURCE_DIR}/cmakescripts/md5cmp.cmake")
add_test(jpegtran-static-prog jpegtran-static -outfile testoutt.jpg testoutp.jpg")
add_test(jpegtran-static-prog-cmp "${CMAKE_COMMAND}" -DMD5=${MD5_JPEG_INT} -DFILE=testoutt.jpg -P "${CMAKE_SOURCE_DIR}/cmakescripts/md5cmp.cmake")
if(WITH_ARITH_ENC)
add_test(cjpeg-static-ari cjpeg-static -dct int -arithmetic -outfile testoutari.jpg ${CMAKE_SOURCE_DIR}/testimages/testorig.ppm)
add_test(cjpeg-static-ari-cmp ${CMAKE_COMMAND} -DMD5=${MD5_JPEG_ARI} -DFILE=testoutari.jpg -P ${CMAKE_SOURCE_DIR}/cmakescripts/md5cmp.cmake )
add_test(jpegtran-static-toari jpegtran-static -arithmetic -outfile testouta.jpg ${CMAKE_SOURCE_DIR}/testimages/testimgint.jpg)
add_test(jpegtran-static-toari-cmp ${CMAKE_COMMAND} -DMD5=${MD5_JPEG_ARI} -DFILE=testouta.jpg -P ${CMAKE_SOURCE_DIR}/cmakescripts/md5cmp.cmake)
add_test(cjpeg-static-prog-ari cjpeg-static -dct int -progressive -arithmetic -sample 1x1 -outfile testoutpa.jpg ${CMAKE_SOURCE_DIR}/testimages/testorig.ppm)
add_test(cjpeg-static-prog-ari-cmp ${CMAKE_COMMAND} -DMD5=${MD5_JPEG_PROG_ARI} -DFILE=testoutpa.jpg -P ${CMAKE_SOURCE_DIR}/cmakescripts/md5cmp.cmake )
add_test(cjpeg-static-ari cjpeg-static -dct int -arithmetic -outfile testoutari.jpg "${CMAKE_SOURCE_DIR}/testimages/testorig.ppm")
add_test(cjpeg-static-ari-cmp "${CMAKE_COMMAND}" -DMD5=${MD5_JPEG_ARI} -DFILE=testoutari.jpg -P "${CMAKE_SOURCE_DIR}/cmakescripts/md5cmp.cmake")
add_test(jpegtran-static-toari jpegtran-static -arithmetic -outfile testouta.jpg "${CMAKE_SOURCE_DIR}/testimages/testimgint.jpg")
add_test(jpegtran-static-toari-cmp "${CMAKE_COMMAND}" -DMD5=${MD5_JPEG_ARI} -DFILE=testouta.jpg -P "${CMAKE_SOURCE_DIR}/cmakescripts/md5cmp.cmake")
add_test(cjpeg-static-prog-ari cjpeg-static -dct int -progressive -arithmetic -sample 1x1 -outfile testoutpa.jpg "${CMAKE_SOURCE_DIR}/testimages/testorig.ppm")
add_test(cjpeg-static-prog-ari-cmp "${CMAKE_COMMAND}" -DMD5=${MD5_JPEG_PROG_ARI} -DFILE=testoutpa.jpg -P "${CMAKE_SOURCE_DIR}/cmakescripts/md5cmp.cmake")
endif()
if(WITH_ARITH_DEC)
add_test(djpeg-static-ari djpeg-static -dct int -fast -ppm -outfile testoutari.ppm ${CMAKE_SOURCE_DIR}/testimages/testimgari.jpg)
add_test(djpeg-static-ari-cmp ${CMAKE_COMMAND} -DMD5=${MD5_PPM_ARI} -DFILE=testoutari.ppm -P ${CMAKE_SOURCE_DIR}/cmakescripts/md5cmp.cmake)
add_test(jpegtran-static-fromari jpegtran-static -outfile testouta.jpg ${CMAKE_SOURCE_DIR}/testimages/testimgari.jpg)
add_test(jpegtran-static-fromari-cmp ${CMAKE_COMMAND} -DMD5=${MD5_JPEG_INT} -DFILE=testouta.jpg -P ${CMAKE_SOURCE_DIR}/cmakescripts/md5cmp.cmake)
add_test(djpeg-static-ari djpeg-static -dct int -fast -ppm -outfile testoutari.ppm "${CMAKE_SOURCE_DIR}/testimages/testimgari.jpg")
add_test(djpeg-static-ari-cmp "${CMAKE_COMMAND}" -DMD5=${MD5_PPM_ARI} -DFILE=testoutari.ppm -P "${CMAKE_SOURCE_DIR}/cmakescripts/md5cmp.cmake")
add_test(jpegtran-static-fromari jpegtran-static -outfile testouta.jpg "${CMAKE_SOURCE_DIR}/testimages/testimgari.jpg")
add_test(jpegtran-static-fromari-cmp "${CMAKE_COMMAND}" -DMD5=${MD5_JPEG_INT} -DFILE=testouta.jpg -P "${CMAKE_SOURCE_DIR}/cmakescripts/md5cmp.cmake")
endif()
add_test(jpegtran-static-crop jpegtran-static -crop 120x90+20+50 -transpose -perfect -outfile testoutcrop.jpg ${CMAKE_SOURCE_DIR}/testimages/testorig.jpg)
add_test(jpegtran-static-crop-cmp ${CMAKE_COMMAND} -DMD5=${MD5_JPEG_CROP} -DFILE=testoutcrop.jpg -P ${CMAKE_SOURCE_DIR}/cmakescripts/md5cmp.cmake)
add_test(jpegtran-static-crop jpegtran-static -crop 120x90+20+50 -transpose -perfect -outfile testoutcrop.jpg "${CMAKE_SOURCE_DIR}/testimages/testorig.jpg")
add_test(jpegtran-static-crop-cmp "${CMAKE_COMMAND}" -DMD5=${MD5_JPEG_CROP} -DFILE=testoutcrop.jpg -P "${CMAKE_SOURCE_DIR}/cmakescripts/md5cmp.cmake")
add_custom_target(testclean COMMAND ${CMAKE_COMMAND} -P
${CMAKE_SOURCE_DIR}/cmakescripts/testclean.cmake)
add_custom_target(testclean COMMAND "${CMAKE_COMMAND}" -P
"${CMAKE_SOURCE_DIR}/cmakescripts/testclean.cmake" VERBATIM)
#
@@ -460,7 +460,7 @@ endif()
if(64BIT)
set(INST_PLATFORM "${INST_PLATFORM} 64-bit")
set(INST_NAME ${INST_NAME}64)
set(INST_REG_NAME ${INST_DIR}64)
set(INST_REG_NAME "${INST_DIR}64")
set(INST_DEFS ${INST_DEFS} -DWIN64)
endif()
@@ -474,7 +474,7 @@ else()
set(INST_DEFS ${INST_DEFS} "-DBUILDDIR=")
endif()
STRING(REGEX REPLACE "/" "\\\\" INST_DIR ${CMAKE_INSTALL_PREFIX})
STRING(REGEX REPLACE "/" "\\\\" INST_DIR "${CMAKE_INSTALL_PREFIX}")
configure_file(release/libmozjpeg.nsi.in libmozjpeg.nsi @ONLY)
@@ -493,12 +493,12 @@ install(TARGETS jpeg-static turbojpeg turbojpeg-static rdjpgcom wrjpgcom tjbench
RUNTIME DESTINATION bin
)
install(FILES ${CMAKE_SOURCE_DIR}/README ${CMAKE_SOURCE_DIR}/README-mozilla.txt
${CMAKE_SOURCE_DIR}/example.c ${CMAKE_SOURCE_DIR}/libjpeg.txt
${CMAKE_SOURCE_DIR}/structure.txt ${CMAKE_SOURCE_DIR}/usage.txt
${CMAKE_SOURCE_DIR}/wizard.txt
install(FILES "${CMAKE_SOURCE_DIR}/README" "${CMAKE_SOURCE_DIR}/README-mozilla.txt"
"${CMAKE_SOURCE_DIR}/example.c" "${CMAKE_SOURCE_DIR}/libjpeg.txt"
"${CMAKE_SOURCE_DIR}/structure.txt" "${CMAKE_SOURCE_DIR}/usage.txt"
"${CMAKE_SOURCE_DIR}/wizard.txt"
DESTINATION doc)
install(FILES ${CMAKE_BINARY_DIR}/jconfig.h ${CMAKE_SOURCE_DIR}/jerror.h
${CMAKE_SOURCE_DIR}/jmorecfg.h ${CMAKE_SOURCE_DIR}/jpeglib.h
${CMAKE_SOURCE_DIR}/turbojpeg.h DESTINATION include)
install(FILES "${CMAKE_BINARY_DIR}/jconfig.h" "${CMAKE_SOURCE_DIR}/jerror.h"
"${CMAKE_SOURCE_DIR}/jmorecfg.h" "${CMAKE_SOURCE_DIR}/jpeglib.h"
"${CMAKE_SOURCE_DIR}/turbojpeg.h" DESTINATION include)

View File

@@ -23,6 +23,14 @@ and is out of scope for a codec library.
[5] The TurboJPEG API can now be used to compress JPEG images from YUV planar
source images.
[7] Improved the accuracy and performance of the non-SIMD implementation of the
floating point inverse DCT (using code borrowed from libjpeg v8a and later.)
The accuracy of this implementation now matches the accuracy of the SSE/SSE2
implementation. Note, however, that the floating point DCT/IDCT algorithms are
mainly a legacy feature. They generally do not produce significantly better
accuracy than the slow integer DCT/IDCT algorithms, and they are quite a bit
slower.
1.3.1
=====

View File

@@ -108,7 +108,7 @@ endif
cjpeg_SOURCES = cdjpeg.h cderror.h cdjpeg.c cjpeg.c rdbmp.c rdgif.c \
rdppm.c rdswitch.c rdtarga.c
rdppm.c rdswitch.c rdtarga.c rdjpeg.c
cjpeg_LDADD = libjpeg.la

View File

@@ -419,10 +419,25 @@ details.
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 are not guaranteed to
be identical (the accuracy of the floating point DCT/IDCT is constant when
using libjpeg-turbo's SIMD extensions, but otherwise, it can depend heavily on
the compiler and compiler settings.)
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.)
-- When not using the SIMD extensions, then the accuracy of the floating point
DCT/IDCT can depend on the compiler and 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
@@ -430,16 +445,14 @@ 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 a bit differently than libjpeg v6b does,
and libjpeg-turbo's SIMD extensions are based on the libjpeg v6b behavior.
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.
-- When using the floating point IDCT, for the reasons stated above and also
because the floating point IDCT algorithm was modified in libjpeg v8a to
improve accuracy.
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

View File

@@ -7,6 +7,8 @@ The idea is to reduce transfer times for JPEGs on the Web, thus reducing page lo
'mozjpeg' is not intended to be a general JPEG library replacement. It makes tradeoffs that are intended to benefit Web use cases and focuses solely on improving encoding. It is best used as part of a Web encoding workflow. For a general JPEG library (e.g. your system libjpeg), especially if you care about decoding, we recommend libjpeg-turbo.
For more information, see the project announcement:
More information:
https://blog.mozilla.org/research/2014/03/05/introducing-the-mozjpeg-project/
* [Version 1.0 Announcement](https://blog.mozilla.org/research/2014/03/05/introducing-the-mozjpeg-project/)
* [Version 2.0 Announcement](https://blog.mozilla.org/research/2014/07/15/mozilla-advances-jpeg-encoding-with-mozjpeg-2-0/)
* [Mailing List](https://lists.mozilla.org/listinfo/dev-mozjpeg)</a>

View File

@@ -144,26 +144,26 @@ AC_DEFUN([AC_CHECK_COMPATIBLE_ARM_ASSEMBLER_IFELSE],[
ac_save_CFLAGS="$CFLAGS"
CFLAGS="$CCASFLAGS -x assembler-with-cpp"
CC="$CCAS"
AC_COMPILE_IFELSE([[
AC_COMPILE_IFELSE([AC_LANG_SOURCE([[
.text
.fpu neon
.arch armv7a
.object_arch armv4
.arm
pld [r0]
vmovn.u16 d0, q0]], ac_good_gnu_arm_assembler=yes)
vmovn.u16 d0, q0]])], ac_good_gnu_arm_assembler=yes)
ac_use_gas_preprocessor=no
if test "x$ac_good_gnu_arm_assembler" = "xno" ; then
CC="gas-preprocessor.pl $CCAS"
AC_COMPILE_IFELSE([[
AC_COMPILE_IFELSE([AC_LANG_SOURCE([[
.text
.fpu neon
.arch armv7a
.object_arch armv4
.arm
pld [r0]
vmovn.u16 d0, q0]], ac_use_gas_preprocessor=yes)
vmovn.u16 d0, q0]])], ac_use_gas_preprocessor=yes)
fi
CFLAGS="$ac_save_CFLAGS"
CC="$ac_save_CC"
@@ -189,7 +189,7 @@ AC_DEFUN([AC_CHECK_COMPATIBLE_MIPSEL_ASSEMBLER_IFELSE],[
ac_save_CFLAGS="$CFLAGS"
CFLAGS="$CCASFLAGS -mdspr2"
AC_COMPILE_IFELSE([[
AC_COMPILE_IFELSE([AC_LANG_SOURCE([[
int main ()
{
@@ -201,7 +201,7 @@ AC_DEFUN([AC_CHECK_COMPATIBLE_MIPSEL_ASSEMBLER_IFELSE],[
);
return c;
}
]], have_mips_dspr2=yes)
]])], have_mips_dspr2=yes)
CFLAGS=$ac_save_CFLAGS
if test "x$have_mips_dspr2" = "xyes" ; then

View File

@@ -3,6 +3,8 @@
*
* Copyright (C) 1994-1997, 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.
*
* This file contains common declarations for the sample applications
@@ -16,6 +18,7 @@
#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
@@ -35,6 +38,13 @@ struct cjpeg_source_struct {
JSAMPARRAY buffer;
JDIMENSION buffer_height;
#if JPEG_RAW_READER
// For reading JPEG
JSAMPARRAY plane_pointer[4];
#endif
jpeg_saved_marker_ptr marker_list;
};
@@ -94,6 +104,7 @@ typedef struct cdjpeg_progress_mgr * cd_progress_ptr;
#ifdef NEED_SHORT_EXTERNAL_NAMES
#define jinit_read_bmp jIRdBMP
#define jinit_write_bmp jIWrBMP
#define jinit_read_jpeg jIRdJPG
#define jinit_read_gif jIRdGIF
#define jinit_write_gif jIWrGIF
#define jinit_read_ppm jIRdPPM
@@ -122,6 +133,7 @@ EXTERN(djpeg_dest_ptr) jinit_write_bmp JPP((j_decompress_ptr cinfo,
boolean is_os2));
EXTERN(cjpeg_source_ptr) jinit_read_gif JPP((j_compress_ptr cinfo));
EXTERN(djpeg_dest_ptr) jinit_write_gif JPP((j_decompress_ptr cinfo));
EXTERN(cjpeg_source_ptr) jinit_read_jpeg JPP((j_compress_ptr cinfo));
EXTERN(cjpeg_source_ptr) jinit_read_ppm JPP((j_compress_ptr cinfo));
EXTERN(djpeg_dest_ptr) jinit_write_ppm JPP((j_decompress_ptr cinfo));
EXTERN(cjpeg_source_ptr) jinit_read_rle JPP((j_compress_ptr cinfo));

23
cjpeg.1
View File

@@ -1,4 +1,4 @@
.TH CJPEG 1 "18 January 2013"
.TH CJPEG 1 "11 May 2014"
.SH NAME
cjpeg \- compress an image file to a JPEG file
.SH SYNOPSIS
@@ -166,14 +166,25 @@ Use integer DCT method (default).
.TP
.B \-dct fast
Use fast integer DCT (less accurate).
In libjpeg-turbo, the fast method is generally about 5-15% faster than the int
method when using the x86/x86-64 SIMD extensions (results may vary with other
SIMD implementations, or when using libjpeg-turbo without SIMD extensions.)
For quality levels of 90 and below, there should be little or no perceptible
difference between the two algorithms. For quality levels above 90, however,
the difference between the fast and the int methods becomes more pronounced.
With quality=97, for instance, the fast method incurs generally about a 1-3 dB
loss (in PSNR) relative to the int method, but this can be larger for some
images. Do not use the fast method with quality levels above 97. The
algorithm often degenerates at quality=98 and above and can actually produce a
more lossy image than if lower quality levels had been used.
.TP
.B \-dct float
Use floating-point DCT method.
The float method is very slightly more accurate than the int method, but is
much slower unless your machine has very fast floating-point hardware. Also
note that results of the floating-point method may vary slightly across
machines, while the integer methods should give the same results everywhere.
The fast integer method is much less accurate than the other two.
The float method is mostly a legacy feature. It does not produce significantly
more accurate results than the int method, and it is much slower. The float
method may also give different results on different machines due to varying
roundoff behavior, whereas the integer methods should give the same results on
all machines.
.TP
.BI \-restart " N"
Emit a JPEG restart marker every N MCU rows, or every N MCU blocks if "B" is

136
cjpeg.c
View File

@@ -80,7 +80,7 @@ static const char * const cdjpeg_message_table[] = {
*/
static boolean is_targa; /* records user -targa switch */
static boolean is_jpeg;
LOCAL(cjpeg_source_ptr)
select_file_type (j_compress_ptr cinfo, FILE * infile)
@@ -121,6 +121,9 @@ select_file_type (j_compress_ptr cinfo, FILE * infile)
case 0x00:
return jinit_read_targa(cinfo);
#endif
case 0xff:
is_jpeg = TRUE;
return jinit_read_jpeg(cinfo);
default:
ERREXIT(cinfo, JERR_UNKNOWN_FORMAT);
break;
@@ -165,11 +168,18 @@ usage (void)
#ifdef C_PROGRESSIVE_SUPPORTED
fprintf(stderr, " -progressive Create progressive JPEG file (enabled by default)\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, " -multidcscan Use multiple DC scans (may be incompatible with some JPEG decoders)\n");
fprintf(stderr, " -notrellis Disable trellis optimization\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");
#ifdef C_ARITH_CODING_SUPPORTED
fprintf(stderr, " -arithmetic Use arithmetic coding\n");
@@ -197,7 +207,6 @@ usage (void)
#endif
fprintf(stderr, " -verbose or -debug Emit debug output\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");
@@ -270,11 +279,17 @@ 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 */
if (++argn >= argc) { /* advance to next argument */
fprintf(stderr, "%s: missing argument for dct\n", progname);
usage();
}
if (keymatch(argv[argn], "int", 1)) {
cinfo->dct_method = JDCT_ISLOW;
} else if (keymatch(argv[argn], "fast", 2)) {
@@ -282,6 +297,7 @@ parse_switches (j_compress_ptr cinfo, int argc, char **argv,
} else if (keymatch(argv[argn], "float", 2)) {
cinfo->dct_method = JDCT_FLOAT;
} else
fprintf(stderr, "%s: invalid argument for dct\n", progname);
usage();
} else if (keymatch(arg, "debug", 1) || keymatch(arg, "verbose", 1)) {
@@ -302,6 +318,10 @@ parse_switches (j_compress_ptr cinfo, int argc, char **argv,
} else if (keymatch(arg, "fastcrush", 4)) {
cinfo->optimize_scans = FALSE;
} else if (keymatch(arg, "flat", 4)) {
cinfo->use_flat_quant_tbl = TRUE;
jpeg_set_quality(cinfo, 75, TRUE);
} else if (keymatch(arg, "grayscale", 2) || keymatch(arg, "greyscale",2)) {
/* Force a monochrome JPEG file to be generated. */
jpeg_set_colorspace(cinfo, JCS_GRAYSCALE);
@@ -310,6 +330,16 @@ 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();
cinfo->lambda_log_scale1 = atof(argv[argn]);
} else if (keymatch(arg, "lambda2", 7)) {
if (++argn >= argc) /* advance to next argument */
usage();
cinfo->lambda_log_scale2 = atof(argv[argn]);
} else if (keymatch(arg, "maxmemory", 3)) {
/* Maximum memory in Kb (or Mb with 'm'). */
long lval;
@@ -323,6 +353,9 @@ parse_switches (j_compress_ptr cinfo, int argc, char **argv,
lval *= 1000L;
cinfo->mem->max_memory_to_use = lval * 1000L;
} else if (keymatch(arg, "multidcscan", 3)) {
cinfo->one_dc_scan = FALSE;
} else if (keymatch(arg, "optimize", 1) || keymatch(arg, "optimise", 1)) {
/* Enable entropy parm optimization. */
#ifdef ENTROPY_OPT_SUPPORTED
@@ -335,8 +368,10 @@ 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 */
if (++argn >= argc) { /* advance to next argument */
fprintf(stderr, "%s: missing argument for outfile\n", progname);
usage();
}
outfilename = argv[argn]; /* save it away for later use */
} else if (keymatch(arg, "progressive", 1)) {
@@ -362,8 +397,10 @@ 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 */
if (++argn >= argc) { /* advance to next argument */
fprintf(stderr, "%s: missing argument for quality\n", progname);
usage();
}
qualityarg = argv[argn];
} else if (keymatch(arg, "qslots", 2)) {
@@ -446,7 +483,40 @@ parse_switches (j_compress_ptr cinfo, int argc, char **argv,
/* Input file is Targa format. */
is_targa = TRUE;
} else if (keymatch(arg, "notrellis", 1)) {
/* disable trellis quantization */
cinfo->trellis_quant = FALSE;
} else if (keymatch(arg, "tune-psnr", 6)) {
cinfo->use_flat_quant_tbl = TRUE;
cinfo->lambda_log_scale1 = 9.0;
cinfo->lambda_log_scale2 = 0.0;
cinfo->use_lambda_weight_tbl = FALSE;
jpeg_set_quality(cinfo, 75, TRUE);
} else if (keymatch(arg, "tune-ssim", 6)) {
cinfo->use_flat_quant_tbl = TRUE;
cinfo->lambda_log_scale1 = 12.0;
cinfo->lambda_log_scale2 = 13.5;
cinfo->use_lambda_weight_tbl = FALSE;
jpeg_set_quality(cinfo, 75, TRUE);
} else if (keymatch(arg, "tune-ms-ssim", 6)) {
cinfo->use_flat_quant_tbl = FALSE;
cinfo->lambda_log_scale1 = 14.25;
cinfo->lambda_log_scale2 = 12.75;
cinfo->use_lambda_weight_tbl = TRUE;
jpeg_set_quality(cinfo, 75, TRUE);
} else if (keymatch(arg, "tune-hvs-psnr", 6)) {
cinfo->use_flat_quant_tbl = FALSE;
cinfo->lambda_log_scale1 = 16.0;
cinfo->lambda_log_scale2 = 15.5;
cinfo->use_lambda_weight_tbl = TRUE;
jpeg_set_quality(cinfo, 75, TRUE);
} else {
fprintf(stderr, "%s: unknown option '%s'\n", progname, arg);
usage(); /* bogus switch */
}
}
@@ -458,20 +528,26 @@ 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))
if (! set_quality_ratings(cinfo, qualityarg, force_baseline)) {
fprintf(stderr, "%s: can't set quality ratings\n", progname);
usage();
}
if (qtablefile != NULL) /* process -qtables if it was present */
if (! read_quant_tables(cinfo, qtablefile, force_baseline))
if (! read_quant_tables(cinfo, qtablefile, force_baseline)) {
fprintf(stderr, "%s: can't read qtable file\n", progname);
usage();
}
if (qslotsarg != NULL) /* process -qslots if it was present */
if (! set_quant_slots(cinfo, qslotsarg))
usage();
if (samplearg != NULL) /* process -sample if it was present */
if (! set_sample_factors(cinfo, samplearg))
if (! set_sample_factors(cinfo, samplearg)) {
fprintf(stderr, "%s: can't set sample factors\n", progname);
usage();
}
#ifdef C_PROGRESSIVE_SUPPORTED
if (simple_progressive) /* process -progressive; -scans can override */
@@ -609,7 +685,10 @@ main (int argc, char **argv)
(*src_mgr->start_input) (&cinfo, src_mgr);
/* Now that we know input colorspace, fix colorspace-dependent defaults */
jpeg_default_colorspace(&cinfo);
#if JPEG_RAW_READER
if (!is_jpeg)
#endif
jpeg_default_colorspace(&cinfo);
/* Adjust default compression parameters by re-parsing the options */
file_index = parse_switches(&cinfo, argc, argv, 0, TRUE);
@@ -625,10 +704,47 @@ main (int argc, char **argv)
/* Start compressor */
jpeg_start_compress(&cinfo, TRUE);
/* Copy metadata */
if (is_jpeg) {
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);
}
}
/* Process data */
while (cinfo.next_scanline < cinfo.image_height) {
num_scanlines = (*src_mgr->get_pixel_rows) (&cinfo, src_mgr);
(void) jpeg_write_scanlines(&cinfo, src_mgr->buffer, num_scanlines);
#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);
}
/* Finish compression and release memory */

View File

@@ -2,10 +2,11 @@
# Process this file with autoconf to produce a configure script.
AC_PREREQ([2.56])
AC_INIT([libmozjpeg], [1.0.0])
AC_INIT([libmozjpeg], [2.1])
BUILD=`date +%Y%m%d`
AM_INIT_AUTOMAKE([-Wall foreign dist-bzip2])
m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES(yes)])
AC_PREFIX_DEFAULT(/opt/libmozjpeg)
# Always build with prototypes
@@ -16,8 +17,10 @@ SAVED_CFLAGS=${CFLAGS}
SAVED_CPPFLAGS=${CPPFLAGS}
AC_PROG_CPP
AC_PROG_CC
AM_PROG_CC_C_O
AM_PROG_AS
AC_PROG_INSTALL
m4_ifdef([AM_PROG_AR], [AM_PROG_AR])
AC_PROG_LIBTOOL
AC_PROG_LN_S
@@ -90,6 +93,7 @@ if test "x${SUNCC}" = "xyes"; then
fi
# Checks for libraries.
AC_CHECK_LIB([m],[pow])
# Checks for header files.
AC_HEADER_STDC
@@ -235,13 +239,13 @@ VERS_1 {
global: *;
};
EOF
AC_LINK_IFELSE(AC_LANG_PROGRAM([], []),
AC_LINK_IFELSE([AC_LANG_SOURCE([AC_LANG_PROGRAM([], [])])],
[VERSION_SCRIPT_FLAG=-Wl,--version-script,;
AC_MSG_RESULT([yes (GNU style)])],
[])
if test "x$VERSION_SCRIPT_FLAG" = "x"; then
LDFLAGS="$SAVED_LDFLAGS -Wl,-M,conftest.map"
AC_LINK_IFELSE(AC_LANG_PROGRAM([], []),
AC_LINK_IFELSE([AC_LANG_SOURCE([AC_LANG_PROGRAM([], [])])],
[VERSION_SCRIPT_FLAG=-Wl,-M,;
AC_MSG_RESULT([yes (Sun style)])],
[])
@@ -262,7 +266,7 @@ AC_SUBST(VERSION_SCRIPT_FLAG)
AC_MSG_CHECKING(for inline)
ljt_cv_inline=""
AC_TRY_COMPILE(, [} __attribute__((always_inline)) int foo() { return 0; }
int bar() { return foo();], ljt_cv_inline="__attribute__((always_inline))",
int bar() { return foo();], ljt_cv_inline="inline __attribute__((always_inline))",
AC_TRY_COMPILE(, [} __inline__ int foo() { return 0; }
int bar() { return foo();], ljt_cv_inline="__inline__",
AC_TRY_COMPILE(, [} __inline int foo() { return 0; }
@@ -270,7 +274,7 @@ int bar() { return foo();], ljt_cv_inline="__inline",
AC_TRY_COMPILE(, [} inline int foo() { return 0; }
int bar() { return foo();], ljt_cv_inline="inline"))))
AC_MSG_RESULT($ljt_cv_inline)
AC_DEFINE_UNQUOTED([INLINE],[$ljt_cv_inline],[How to obtain function inlining.])
AC_DEFINE_UNQUOTED([INLINE],[inline $ljt_cv_inline],[How to obtain function inlining.])
# Arithmetic coding support
AC_MSG_CHECKING([whether to include arithmetic encoding support])

26
djpeg.1
View File

@@ -1,4 +1,4 @@
.TH DJPEG 1 "18 January 2013"
.TH DJPEG 1 "11 May 2014"
.SH NAME
djpeg \- decompress a JPEG file to an image file
.SH SYNOPSIS
@@ -115,14 +115,28 @@ Use integer DCT method (default).
.TP
.B \-dct fast
Use fast integer DCT (less accurate).
In libjpeg-turbo, the fast method is generally about 5-15% faster than the int
method when using the x86/x86-64 SIMD extensions (results may vary with other
SIMD implementations, or when using libjpeg-turbo without SIMD extensions.) If
the JPEG image was compressed using a quality level of 85 or below, then there
should be little or no perceptible difference between the two algorithms. When
decompressing images that were compressed using quality levels above 85,
however, the difference between the fast and int methods becomes more
pronounced. With images compressed using quality=97, for instance, the fast
method incurs generally about a 4-6 dB loss (in PSNR) relative to the int
method, but this can be larger for some images. If you can avoid it, do not
use the fast method when decompressing images that were compressed using
quality levels above 97. The algorithm often degenerates for such images and
can actually produce a more lossy output image than if the JPEG image had been
compressed using lower quality levels.
.TP
.B \-dct float
Use floating-point DCT method.
The float method is very slightly more accurate than the int method, but is
much slower unless your machine has very fast floating-point hardware. Also
note that results of the floating-point method may vary slightly across
machines, while the integer methods should give the same results everywhere.
The fast integer method is much less accurate than the other two.
The float method is mostly a legacy feature. It does not produce significantly
more accurate results than the int method, and it is much slower. The float
method may also give different results on different machines due to varying
roundoff behavior, whereas the integer methods should give the same results on
all machines.
.TP
.B \-dither fs
Use Floyd-Steinberg dithering in color quantization.

View File

@@ -1,5 +1,5 @@
set(JAR_FILE turbojpeg.jar)
set(MANIFEST_FILE ${CMAKE_CURRENT_SOURCE_DIR}/MANIFEST.MF)
set(MANIFEST_FILE "${CMAKE_CURRENT_SOURCE_DIR}/MANIFEST.MF")
set(JAVA_CLASSNAMES org/libjpegturbo/turbojpeg/TJ
org/libjpegturbo/turbojpeg/TJCompressor
@@ -15,7 +15,7 @@ set(JAVA_CLASSNAMES org/libjpegturbo/turbojpeg/TJ
if(MSVC_IDE)
set(OBJDIR "${CMAKE_CURRENT_BINARY_DIR}/$(OutDir)")
else()
set(OBJDIR ${CMAKE_CURRENT_BINARY_DIR})
set(OBJDIR "${CMAKE_CURRENT_BINARY_DIR}")
endif()
set(TURBOJPEG_DLL_NAME "turbojpeg")
@@ -23,33 +23,34 @@ if(MINGW)
set(TURBOJPEG_DLL_NAME "libturbojpeg")
endif()
configure_file(org/libjpegturbo/turbojpeg/TJLoader.java.in
${CMAKE_CURRENT_BINARY_DIR}/org/libjpegturbo/turbojpeg/TJLoader.java)
"${CMAKE_CURRENT_BINARY_DIR}/org/libjpegturbo/turbojpeg/TJLoader.java")
set(JAVA_SOURCES "")
set(JAVA_CLASSES "")
set(JAVA_CLASSES_FULL "")
foreach(class ${JAVA_CLASSNAMES})
set(JAVA_SOURCES ${JAVA_SOURCES} ${CMAKE_CURRENT_SOURCE_DIR}/${class}.java)
set(JAVA_CLASSES ${JAVA_CLASSES} ${class}.class)
set(JAVA_CLASSES_FULL ${JAVA_CLASSES_FULL} ${OBJDIR}/${class}.class)
list(APPEND JAVA_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/${class}.java")
list(APPEND JAVA_CLASSES "${class}.class")
list(APPEND JAVA_CLASSES_FULL "${OBJDIR}/${class}.class")
endforeach()
set(JAVA_SOURCES ${JAVA_SOURCES}
${CMAKE_CURRENT_BINARY_DIR}/org/libjpegturbo/turbojpeg/TJLoader.java)
set(JAVA_CLASSES ${JAVA_CLASSES}
org/libjpegturbo/turbojpeg/TJLoader.class)
set(JAVA_CLASSES_FULL ${JAVA_CLASSES_FULL}
${OBJDIR}/org/libjpegturbo/turbojpeg/TJLoader.class)
list(APPEND JAVA_SOURCES
"${CMAKE_CURRENT_BINARY_DIR}/org/libjpegturbo/turbojpeg/TJLoader.java")
list(APPEND JAVA_CLASSES org/libjpegturbo/turbojpeg/TJLoader.class)
list(APPEND JAVA_CLASSES_FULL
"${OBJDIR}/org/libjpegturbo/turbojpeg/TJLoader.class")
string(REGEX REPLACE " " ";" JAVACFLAGS "${JAVACFLAGS}")
add_custom_command(OUTPUT ${JAVA_CLASSES_FULL} DEPENDS ${JAVA_SOURCES}
COMMAND ${JAVA_COMPILE} ARGS ${JAVACFLAGS} -d ${OBJDIR} ${JAVA_SOURCES})
COMMAND "${JAVA_COMPILE}" ARGS ${JAVACFLAGS} -d "${OBJDIR}" ${JAVA_SOURCES}
VERBATIM)
add_custom_command(OUTPUT ${JAR_FILE} DEPENDS ${JAVA_CLASSES_FULL}
${MANIFEST_FILE}
COMMAND ${JAVA_ARCHIVE} cfm ${JAR_FILE} ${MANIFEST_FILE} ${JAVA_CLASSES}
WORKING_DIRECTORY ${OBJDIR})
add_custom_command(OUTPUT "${JAR_FILE}" DEPENDS ${JAVA_CLASSES_FULL}
"${MANIFEST_FILE}"
COMMAND "${JAVA_ARCHIVE}" cfm "${JAR_FILE}" "${MANIFEST_FILE}" ${JAVA_CLASSES}
WORKING_DIRECTORY "${OBJDIR}"
VERBATIM)
add_custom_target(java ALL DEPENDS ${JAR_FILE})
add_custom_target(java ALL DEPENDS "${JAR_FILE}")
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${JAR_FILE} DESTINATION classes)
install(FILES "${CMAKE_CURRENT_BINARY_DIR}/${JAR_FILE}" DESTINATION classes)

View File

@@ -46,7 +46,7 @@ jpeg_start_compress (j_compress_ptr cinfo, boolean 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->num_scans_luma == 0)
if (cinfo->num_scans_luma == 0 || cinfo->scan_info == NULL || cinfo->num_scans == 0)
cinfo->optimize_scans = FALSE;
/* (Re)initialize error mgr and destination modules */

View File

@@ -2,6 +2,8 @@
* jccoefct.c
*
* Copyright (C) 1994-1997, 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.
*
@@ -13,7 +15,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
@@ -52,6 +54,10 @@ 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;
@@ -66,6 +72,8 @@ METHODDEF(boolean) compress_first_pass
METHODDEF(boolean) compress_output
JPP((j_compress_ptr cinfo, JSAMPIMAGE input_buf));
#endif
METHODDEF(boolean) compress_trellis_pass
JPP((j_compress_ptr cinfo, JSAMPIMAGE input_buf));
LOCAL(void)
@@ -122,6 +130,12 @@ 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;
@@ -177,7 +191,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);
ypos, xpos, (JDIMENSION) blockcnt, NULL);
if (blockcnt < compptr->MCU_width) {
/* Create some dummy blocks at the right edge of the image. */
jzero_far((void FAR *) coef->MCU_buffer[blkn + blockcnt],
@@ -252,6 +266,7 @@ 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++) {
@@ -260,6 +275,12 @@ compress_first_pass (j_compress_ptr cinfo, JSAMPIMAGE input_buf)
((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);
/* Count non-dummy DCT block rows in this iMCU row. */
if (coef->iMCU_row_num < last_iMCU_row)
block_rows = compptr->v_samp_factor;
@@ -282,7 +303,7 @@ compress_first_pass (j_compress_ptr cinfo, JSAMPIMAGE input_buf)
(*cinfo->fdct->forward_DCT) (cinfo, compptr,
input_buf[ci], thisblockrow,
(JDIMENSION) (block_row * DCTSIZE),
(JDIMENSION) 0, blocks_across);
(JDIMENSION) 0, blocks_across, buffer_dst[block_row]);
if (ndummy > 0) {
/* Create dummy blocks at the right edge of the image. */
thisblockrow += blocks_across; /* => first dummy block */
@@ -326,6 +347,101 @@ 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 actbl_data;
c_derived_tbl *actbl = &actbl_data;
compptr = cinfo->cur_comp_info[ci];
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;
/* 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];
quantize_trellis(cinfo, actbl, thisblockrow, buffer_dst[block_row], blocks_across, cinfo->quant_tbl_ptrs[compptr->quant_tbl_no], cinfo->norm_src[compptr->quant_tbl_no], cinfo->norm_coef[compptr->quant_tbl_no]);
if (ndummy > 0) {
/* Create dummy blocks at the right edge of the image. */
thisblockrow += blocks_across; /* => first dummy block */
jzero_far((void FAR *) 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 FAR *) 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.
@@ -377,6 +493,7 @@ compress_output (j_compress_ptr cinfo, JSAMPIMAGE input_buf)
}
}
}
/* Try to write the MCU. */
if (! (*cinfo->entropy->encode_mcu) (cinfo, coef->MCU_buffer)) {
/* Suspension forced; update state counters and exit */
@@ -429,6 +546,14 @@ jinit_c_coef_controller (j_compress_ptr cinfo, boolean need_full_buffer)
(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);
}
#else
ERREXIT(cinfo, JERR_BAD_BUFFER_MODE);

View File

@@ -7,6 +7,8 @@
* Copyright (C) 1999-2006, MIYASAKA Masaru.
* Copyright 2009 Pierre Ossman <ossman@cendio.se> for Cendio AB
* Copyright (C) 2011 D. R. Commander
* mozjpeg Modifications:
* Copyright (C) 2014, Mozilla Corporation.
* For conditions of distribution and use, see the accompanying README file.
*
* This file contains the forward-DCT management logic.
@@ -20,7 +22,8 @@
#include "jpeglib.h"
#include "jdct.h" /* Private declarations for DCT subsystem */
#include "jsimddct.h"
#include <assert.h>
#include <math.h>
/* Private subobject for this module */
@@ -412,7 +415,7 @@ METHODDEF(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)
JDIMENSION num_blocks, JBLOCKROW dst)
/* This version is used for integer DCT implementations. */
{
/* This routine is heavily used, so it's worth coding it tightly. */
@@ -436,6 +439,36 @@ forward_DCT (j_compress_ptr cinfo, jpeg_component_info * compptr,
/* Perform the DCT */
(*do_dct) (workspace);
/* Save unquantized transform coefficients for later trellis quantization */
if (dst) {
int i;
if (cinfo->dct_method == JDCT_IFAST) {
static const INT16 aanscales[DCTSIZE2] = {
/* precomputed values scaled up by 14 bits */
16384, 22725, 21407, 19266, 16384, 12873, 8867, 4520,
22725, 31521, 29692, 26722, 22725, 17855, 12299, 6270,
21407, 29692, 27969, 25172, 21407, 16819, 11585, 5906,
19266, 26722, 25172, 22654, 19266, 15137, 10426, 5315,
16384, 22725, 21407, 19266, 16384, 12873, 8867, 4520,
12873, 17855, 16819, 15137, 12873, 10114, 6967, 3552,
8867, 12299, 11585, 10426, 8867, 6967, 4799, 2446,
4520, 6270, 5906, 5315, 4520, 3552, 2446, 1247
};
for (i = 0; i < DCTSIZE2; i++) {
int x = workspace[i];
int s = aanscales[i];
x = (x >= 0) ? (x * 32768 + s) / (2*s) : (x * 32768 - s) / (2*s);
dst[bi][i] = x;
}
} else {
for (i = 0; i < DCTSIZE2; i++) {
dst[bi][i] = workspace[i];
}
}
}
/* Quantize/descale the coefficients, and store into coef_blocks[] */
(*do_quantize) (coef_blocks[bi], divisors, workspace);
}
@@ -502,7 +535,7 @@ METHODDEF(void)
forward_DCT_float (j_compress_ptr cinfo, jpeg_component_info * compptr,
JSAMPARRAY sample_data, JBLOCKROW coef_blocks,
JDIMENSION start_row, JDIMENSION start_col,
JDIMENSION num_blocks)
JDIMENSION num_blocks, JBLOCKROW dst)
/* This version is used for floating-point DCT implementations. */
{
/* This routine is heavily used, so it's worth coding it tightly. */
@@ -510,6 +543,8 @@ forward_DCT_float (j_compress_ptr cinfo, jpeg_component_info * compptr,
FAST_FLOAT * divisors = fdct->float_divisors[compptr->quant_tbl_no];
FAST_FLOAT * workspace;
JDIMENSION bi;
float v;
int x;
/* Make sure the compiler doesn't look up these every pass */
@@ -527,6 +562,26 @@ forward_DCT_float (j_compress_ptr cinfo, jpeg_component_info * compptr,
/* Perform the DCT */
(*do_dct) (workspace);
/* Save unquantized transform coefficients for later trellis quantization */
/* Currently save as integer values. Could save float values but would require */
/* modifications to memory allocation and trellis quantization */
if (dst) {
int i;
static const double aanscalefactor[DCTSIZE] = {
1.0, 1.387039845, 1.306562965, 1.175875602,
1.0, 0.785694958, 0.541196100, 0.275899379
};
for (i = 0; i < DCTSIZE2; i++) {
v = workspace[i];
v /= aanscalefactor[i%8];
v /= aanscalefactor[i/8];
x = (v >= 0.0) ? (int)(v + 0.5) : (int)(v - 0.5);
dst[bi][i] = x;
}
}
/* Quantize/descale the coefficients, and store into coef_blocks[] */
(*do_quantize) (coef_blocks[bi], divisors, workspace);
}
@@ -534,6 +589,283 @@ forward_DCT_float (j_compress_ptr cinfo, jpeg_component_info * compptr,
#endif /* DCT_FLOAT_SUPPORTED */
#include "jchuff.h"
#include "jpeg_nbits_table.h"
static const float jpeg_lambda_weights_flat[64] = {
1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f,
1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f,
1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f,
1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f,
1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f,
1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f,
1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f,
1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f
};
static const float jpeg_lambda_weights_csf_luma[64] = {
3.35630f, 3.59892f, 3.20921f, 2.28102f, 1.42378f, 0.88079f, 0.58190f, 0.43454f,
3.59893f, 3.21284f, 2.71282f, 1.98092f, 1.30506f, 0.83852f, 0.56346f, 0.42146f,
3.20921f, 2.71282f, 2.12574f, 1.48616f, 0.99660f, 0.66132f, 0.45610f, 0.34609f,
2.28102f, 1.98092f, 1.48616f, 0.97492f, 0.64622f, 0.43812f, 0.31074f, 0.24072f,
1.42378f, 1.30506f, 0.99660f, 0.64623f, 0.42051f, 0.28446f, 0.20380f, 0.15975f,
0.88079f, 0.83852f, 0.66132f, 0.43812f, 0.28446f, 0.19092f, 0.13635f, 0.10701f,
0.58190f, 0.56346f, 0.45610f, 0.31074f, 0.20380f, 0.13635f, 0.09674f, 0.07558f,
0.43454f, 0.42146f, 0.34609f, 0.24072f, 0.15975f, 0.10701f, 0.07558f, 0.05875f,
};
GLOBAL(void)
quantize_trellis(j_compress_ptr cinfo, c_derived_tbl *actbl, JBLOCKROW coef_blocks, JBLOCKROW src, JDIMENSION num_blocks,
JQUANT_TBL * qtbl, double *norm_src, double *norm_coef)
{
int i, j, k;
float accumulated_zero_dist[DCTSIZE2];
float accumulated_cost[DCTSIZE2];
int run_start[DCTSIZE2];
int bi;
float best_cost;
int last_coeff_idx; /* position of last nonzero coefficient */
float norm = 0.0;
float lambda_base;
float lambda;
const float *lambda_tbl = (cinfo->use_lambda_weight_tbl) ? jpeg_lambda_weights_csf_luma : jpeg_lambda_weights_flat;
int Ss, Se;
float *accumulated_zero_block_cost = NULL;
float *accumulated_block_cost = NULL;
int *block_run_start = NULL;
int *requires_eob = NULL;
int has_eob;
float cost_all_zeros;
float best_cost_skip;
float cost;
int zero_run;
int run_bits;
int rate;
Ss = cinfo->Ss;
Se = cinfo->Se;
if (Ss == 0)
Ss = 1;
if (Se < Ss)
return;
if (cinfo->trellis_eob_opt) {
accumulated_zero_block_cost = (float *)malloc((num_blocks + 1) * SIZEOF(float));
accumulated_block_cost = (float *)malloc((num_blocks + 1) * SIZEOF(float));
block_run_start = (int *)malloc(num_blocks * SIZEOF(int));
requires_eob = (int *)malloc((num_blocks + 1) * SIZEOF(int));
accumulated_zero_block_cost[0] = 0;
accumulated_block_cost[0] = 0;
requires_eob[0] = 0;
}
norm = 0.0;
for (i = 1; i < DCTSIZE2; i++) {
norm += qtbl->quantval[i] * qtbl->quantval[i];
}
norm /= 63.0;
lambda_base = 1.0 / norm;
for (bi = 0; bi < num_blocks; bi++) {
norm = 0.0;
for (i = 1; i < DCTSIZE2; i++) {
norm += src[bi][i] * src[bi][i];
}
norm /= 63.0;
if (cinfo->lambda_log_scale2 > 0.0)
lambda = pow(2.0, cinfo->lambda_log_scale1) * lambda_base / (pow(2.0, cinfo->lambda_log_scale2) + norm);
else
lambda = pow(2.0, cinfo->lambda_log_scale1-12.0) * lambda_base;
accumulated_zero_dist[Ss-1] = 0.0;
accumulated_cost[Ss-1] = 0.0;
for (i = Ss; i <= Se; i++) {
int z = jpeg_natural_order[i];
int sign = src[bi][z] >> 31;
int x = abs(src[bi][z]);
int q = 8 * qtbl->quantval[z];
int candidate[16];
int candidate_bits[16];
float candidate_dist[16];
int num_candidates;
int qval;
accumulated_zero_dist[i] = x * x * lambda * lambda_tbl[z] + accumulated_zero_dist[i-1];
qval = (x + q/2) / q; /* quantized value (round nearest) */
if (qval == 0) {
coef_blocks[bi][z] = 0;
accumulated_cost[i] = 1e38; /* Shouldn't be needed */
continue;
}
num_candidates = jpeg_nbits_table[qval];
for (k = 0; k < num_candidates; k++) {
int delta;
candidate[k] = (k < num_candidates - 1) ? (2 << k) - 1 : qval;
delta = candidate[k] * q - x;
candidate_bits[k] = k+1;
candidate_dist[k] = delta * delta * lambda * lambda_tbl[z];
}
accumulated_cost[i] = 1e38;
for (j = Ss-1; j < i; j++) {
int zz = jpeg_natural_order[j];
if (j != Ss-1 && coef_blocks[bi][zz] == 0)
continue;
zero_run = i - 1 - j;
if ((zero_run >> 4) && actbl->ehufsi[0xf0] == 0)
continue;
run_bits = (zero_run >> 4) * actbl->ehufsi[0xf0];
zero_run &= 15;
for (k = 0; k < num_candidates; k++) {
int coef_bits = actbl->ehufsi[16 * zero_run + candidate_bits[k]];
if (coef_bits == 0)
continue;
rate = coef_bits + candidate_bits[k] + run_bits;
cost = rate + candidate_dist[k];
cost += accumulated_zero_dist[i-1] - accumulated_zero_dist[j] + accumulated_cost[j];
if (cost < accumulated_cost[i]) {
coef_blocks[bi][z] = (candidate[k] ^ sign) - sign;
accumulated_cost[i] = cost;
run_start[i] = j;
}
}
}
}
last_coeff_idx = Ss-1;
best_cost = accumulated_zero_dist[Se] + actbl->ehufsi[0];
cost_all_zeros = accumulated_zero_dist[Se];
best_cost_skip = cost_all_zeros;
for (i = Ss; i <= Se; i++) {
int z = jpeg_natural_order[i];
if (coef_blocks[bi][z] != 0) {
float cost = accumulated_cost[i] + accumulated_zero_dist[Se] - accumulated_zero_dist[i];
float cost_wo_eob = cost;
if (i < Se)
cost += actbl->ehufsi[0];
if (cost < best_cost) {
best_cost = cost;
last_coeff_idx = i;
best_cost_skip = cost_wo_eob;
}
}
}
has_eob = (last_coeff_idx < Se) + (last_coeff_idx == Ss-1);
/* Zero out coefficients that are part of runs */
i = Se;
while (i >= Ss)
{
while (i > last_coeff_idx) {
int z = jpeg_natural_order[i];
coef_blocks[bi][z] = 0;
i--;
}
last_coeff_idx = run_start[i];
i--;
}
if (cinfo->trellis_eob_opt) {
accumulated_zero_block_cost[bi+1] = accumulated_zero_block_cost[bi];
accumulated_zero_block_cost[bi+1] += cost_all_zeros;
requires_eob[bi+1] = has_eob;
best_cost = 1e38;
if (has_eob != 2) {
for (i = 0; i <= bi; i++) {
int zero_block_run;
int nbits;
float cost;
if (requires_eob[i] == 2)
continue;
cost = best_cost_skip; /* cost of coding a nonzero block */
cost += accumulated_zero_block_cost[bi];
cost -= accumulated_zero_block_cost[i];
cost += accumulated_block_cost[i];
zero_block_run = bi - i + requires_eob[i];
nbits = jpeg_nbits_table[zero_block_run];
cost += actbl->ehufsi[16*nbits] + nbits;
if (cost < best_cost) {
block_run_start[bi] = i;
best_cost = cost;
accumulated_block_cost[bi+1] = cost;
}
}
}
}
}
if (cinfo->trellis_eob_opt) {
int last_block = num_blocks;
best_cost = 1e38;
for (i = 0; i <= num_blocks; i++) {
int zero_block_run;
int nbits;
float cost = 0.0;
if (requires_eob[i] == 2)
continue;
cost += accumulated_zero_block_cost[num_blocks];
cost -= accumulated_zero_block_cost[i];
zero_block_run = num_blocks - i + requires_eob[i];
nbits = jpeg_nbits_table[zero_block_run];
cost += actbl->ehufsi[16*nbits] + nbits;
if (cost < best_cost) {
best_cost = cost;
last_block = i;
}
}
last_block--;
bi = num_blocks - 1;
while (bi >= 0) {
while (bi > last_block) {
for (j = Ss; j <= Se; j++) {
int z = jpeg_natural_order[j];
coef_blocks[bi][z] = 0;
}
bi--;
}
last_block = block_run_start[bi]-1;
bi--;
}
free(accumulated_zero_block_cost);
free(accumulated_block_cost);
free(block_run_start);
free(requires_eob);
}
if (cinfo->trellis_q_opt) {
for (bi = 0; bi < num_blocks; bi++) {
for (i = 1; i < DCTSIZE2; i++) {
norm_src[i] += src[bi][i] * coef_blocks[bi][i];
norm_coef[i] += 8 * coef_blocks[bi][i] * coef_blocks[bi][i];
}
}
}
}
/*
* Initialize FDCT manager.

View File

@@ -22,8 +22,7 @@
#include "jchuff.h" /* Declarations shared with jcphuff.c */
#include <limits.h>
static unsigned char jpeg_nbits_table[65536];
static int jpeg_nbits_table_init = 0;
#include "jpeg_nbits_table.h"
#ifndef min
#define min(a,b) ((a)<(b)?(a):(b))
@@ -271,15 +270,6 @@ jpeg_make_c_derived_tbl (j_compress_ptr cinfo, boolean isDC, int tblno,
dtbl->ehufco[i] = huffcode[p];
dtbl->ehufsi[i] = huffsize[p];
}
if(!jpeg_nbits_table_init) {
for(i = 0; i < 65536; i++) {
int nbits = 0, temp = i;
while (temp) {temp >>= 1; nbits++;}
jpeg_nbits_table[i] = nbits;
}
jpeg_nbits_table_init = 1;
}
}

View File

@@ -2,6 +2,8 @@
* jchuff.h
*
* Copyright (C) 1991-1997, 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.
*
@@ -45,3 +47,7 @@ EXTERN(void) jpeg_make_c_derived_tbl
/* Generate an optimal table definition given the specified counts */
EXTERN(void) jpeg_gen_optimal_table
JPP((j_compress_ptr cinfo, JHUFF_TBL * htbl, long freq[]));
EXTERN(void) quantize_trellis
JPP((j_compress_ptr cinfo, c_derived_tbl *actbl, JBLOCKROW coef_blocks, JBLOCKROW src, JDIMENSION num_blocks,
JQUANT_TBL * qtbl, double *norm_src, double *norm_coef));

View File

@@ -27,7 +27,8 @@
typedef enum {
main_pass, /* input data, also do first output step */
huff_opt_pass, /* Huffman code optimization pass */
output_pass /* data output pass */
output_pass, /* data output pass */
trellis_pass /* trellis quantization pass */
} c_pass_type;
typedef struct {
@@ -41,6 +42,7 @@ typedef struct {
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 */
unsigned long best_cost; /* bit count for best frequency split */
@@ -326,9 +328,21 @@ select_scan_parameters (j_compress_ptr cinfo)
int ci;
#ifdef C_MULTISCAN_FILES_SUPPORTED
if (cinfo->scan_info != NULL) {
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->use_scans_in_trellis) {
cinfo->cur_comp_info[0] = &cinfo->comp_info[master->pass_number/(4*cinfo->trellis_num_loops)];
cinfo->Ss = (master->pass_number%4 < 2) ? 1 : cinfo->trellis_freq_split+1;
cinfo->Se = (master->pass_number%4 < 2) ? cinfo->trellis_freq_split : DCTSIZE2-1;
} else {
cinfo->cur_comp_info[0] = &cinfo->comp_info[master->pass_number/(2*cinfo->trellis_num_loops)];
cinfo->Ss = 1;
cinfo->Se = DCTSIZE2-1;
}
}
else if (cinfo->scan_info != NULL) {
/* Prepare for current scan --- the script is already validated */
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;
@@ -467,6 +481,7 @@ METHODDEF(void)
prepare_for_pass (j_compress_ptr cinfo)
{
my_master_ptr master = (my_master_ptr) cinfo->master;
cinfo->trellis_passes = master->pass_number < master->pass_number_scan_opt_base;
switch (master->pass_type) {
case main_pass:
@@ -534,6 +549,22 @@ 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->use_scans_in_trellis?4:2)) == 1 && cinfo->trellis_q_opt) {
int i, j;
for (i = 0; i < NUM_QUANT_TBLS; i++) {
for (j = 1; j < DCTSIZE2; j++) {
cinfo->norm_src[i][j] = 0.0;
cinfo->norm_coef[i][j] = 0.0;
}
}
}
(*cinfo->entropy->start_pass) (cinfo, TRUE);
(*cinfo->coef->start_pass) (cinfo, JBUF_REQUANT);
master->pub.call_pass_startup = FALSE;
break;
default:
ERREXIT(cinfo, JERR_NOT_COMPILED);
}
@@ -575,6 +606,16 @@ copy_buffer (j_compress_ptr cinfo, int scan_idx)
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, cinfo->scan_info[scan_idx].Al);
fprintf(stderr, "\n");
}
while (size >= cinfo->dest->free_in_buffer)
{
@@ -596,8 +637,7 @@ select_scans (j_compress_ptr cinfo, int next_scan_number)
{
my_master_ptr master = (my_master_ptr) cinfo->master;
unsigned long size[8];
int base_scan_idx;
int base_scan_idx = 0;
int luma_freq_split_scan_start = cinfo->num_scans_luma_dc + 3 * cinfo->Al_max_luma + 2;
int chroma_freq_split_scan_start = cinfo->num_scans_luma+cinfo->num_scans_chroma_dc+(6*cinfo->Al_max_chroma+4);
@@ -616,7 +656,7 @@ select_scans (j_compress_ptr cinfo, int next_scan_number)
master->best_Al_luma = Al;
} else {
master->scan_number = luma_freq_split_scan_start - 1;
master->pass_number = 2 * master->scan_number + 1;
master->pass_number = 2 * master->scan_number + 1 + master->pass_number_scan_opt_base;
}
}
@@ -641,7 +681,7 @@ select_scans (j_compress_ptr cinfo, int next_scan_number)
(idx == 3 && master->best_freq_split_idx_luma != 2) ||
(idx == 4 && master->best_freq_split_idx_luma != 4)) {
master->scan_number = cinfo->num_scans_luma - 1;
master->pass_number = 2 * master->scan_number + 1;
master->pass_number = 2 * master->scan_number + 1 + master->pass_number_scan_opt_base;
master->pub.is_last_pass = (master->pass_number == master->total_passes - 1);
}
}
@@ -673,7 +713,7 @@ select_scans (j_compress_ptr cinfo, int next_scan_number)
master->best_Al_chroma = Al;
} else {
master->scan_number = chroma_freq_split_scan_start - 1;
master->pass_number = 2 * master->scan_number + 1;
master->pass_number = 2 * master->scan_number + 1 + master->pass_number_scan_opt_base;
}
}
@@ -701,7 +741,7 @@ select_scans (j_compress_ptr cinfo, int next_scan_number)
(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 = 2 * master->scan_number + 1;
master->pass_number = 2 * master->scan_number + 1 + master->pass_number_scan_opt_base;
master->pub.is_last_pass = (master->pass_number == master->total_passes - 1);
}
}
@@ -714,7 +754,7 @@ select_scans (j_compress_ptr cinfo, int next_scan_number)
copy_buffer(cinfo, 0);
if (cinfo->num_scans > cinfo->num_scans_luma) {
if (cinfo->num_scans > cinfo->num_scans_luma && !cinfo->one_dc_scan) {
base_scan_idx = cinfo->num_scans_luma;
if (master->interleave_chroma_dc)
@@ -792,13 +832,17 @@ 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).
*/
master->pass_type = output_pass;
if (! cinfo->optimize_coding)
master->scan_number++;
if (cinfo->trellis_quant)
master->pass_type = trellis_pass;
else {
master->pass_type = output_pass;
if (! cinfo->optimize_coding)
master->scan_number++;
}
break;
case huff_opt_pass:
/* next pass is always output of current scan */
master->pass_type = output_pass;
master->pass_type = (master->pass_number < master->pass_number_scan_opt_base-1) ? trellis_pass : output_pass;
break;
case output_pass:
/* next pass is either optimization or output of next scan */
@@ -812,6 +856,24 @@ finish_pass_master (j_compress_ptr cinfo)
master->scan_number++;
break;
case trellis_pass:
master->pass_type = (cinfo->optimize_coding || master->pass_number < master->pass_number_scan_opt_base-1) ? huff_opt_pass : output_pass;
if ((master->pass_number+1)%(cinfo->num_components*(cinfo->use_scans_in_trellis?4:2)) == 0 && cinfo->trellis_q_opt) {
int i, j;
for (i = 0; i < NUM_QUANT_TBLS; i++) {
for (j = 1; j < DCTSIZE2; j++) {
if (cinfo->norm_coef[i][j] != 0.0) {
int q = (int)(cinfo->norm_src[i][j] / cinfo->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++;
@@ -871,6 +933,12 @@ jinit_c_master_control (j_compress_ptr cinfo, boolean transcode_only)
else
master->total_passes = cinfo->num_scans;
master->pass_number_scan_opt_base = 0;
if (cinfo->trellis_quant) {
master->pass_number_scan_opt_base = ((cinfo->use_scans_in_trellis) ? 4 : 2) * cinfo->num_components * cinfo->trellis_num_loops;
master->total_passes += master->pass_number_scan_opt_base;
}
if (cinfo->optimize_scans) {
int i;
master->best_Al_chroma = 0;

View File

@@ -90,6 +90,16 @@ static const unsigned int std_chrominance_quant_tbl[DCTSIZE2] = {
99, 99, 99, 99, 99, 99, 99, 99
};
static const unsigned int flat_quant_tbl[DCTSIZE2] = {
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
};
#if JPEG_LIB_VERSION >= 70
GLOBAL(void)
@@ -100,10 +110,17 @@ jpeg_default_qtables (j_compress_ptr cinfo, boolean force_baseline)
*/
{
/* Set up two quantization tables using the specified scaling */
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->q_scale_factor[1], force_baseline);
if (cinfo->use_flat_quant_tbl) {
jpeg_add_quant_table(cinfo, 0, flat_quant_tbl,
cinfo->q_scale_factor[0], force_baseline);
jpeg_add_quant_table(cinfo, 1, flat_quant_tbl,
cinfo->q_scale_factor[1], force_baseline);
} else {
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->q_scale_factor[1], force_baseline);
}
}
#endif
@@ -118,10 +135,17 @@ 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,
scale_factor, force_baseline);
jpeg_add_quant_table(cinfo, 1, std_chrominance_quant_tbl,
scale_factor, force_baseline);
if (cinfo->use_flat_quant_tbl) {
jpeg_add_quant_table(cinfo, 0, flat_quant_tbl,
scale_factor, force_baseline);
jpeg_add_quant_table(cinfo, 1, flat_quant_tbl,
scale_factor, force_baseline);
} else {
jpeg_add_quant_table(cinfo, 0, std_luminance_quant_tbl,
scale_factor, force_baseline);
jpeg_add_quant_table(cinfo, 1, std_chrominance_quant_tbl,
scale_factor, force_baseline);
}
}
@@ -325,6 +349,8 @@ jpeg_set_defaults (j_compress_ptr cinfo)
}
#ifdef C_PROGRESSIVE_SUPPORTED
cinfo->scan_info = NULL;
cinfo->num_scans = 0;
if (!cinfo->use_moz_defaults) {
/* Default is no multiple-scan output */
cinfo->scan_info = NULL;
@@ -399,6 +425,8 @@ jpeg_set_defaults (j_compress_ptr cinfo)
jpeg_default_colorspace(cinfo);
cinfo->one_dc_scan = TRUE;
#ifdef C_PROGRESSIVE_SUPPORTED
if (cinfo->use_moz_defaults) {
cinfo->optimize_scans = TRUE;
@@ -406,6 +434,16 @@ jpeg_set_defaults (j_compress_ptr cinfo)
} else
cinfo->optimize_scans = FALSE;
#endif
cinfo->trellis_quant = cinfo->use_moz_defaults;
cinfo->lambda_log_scale1 = 16.0;
cinfo->lambda_log_scale2 = 15.5;
cinfo->use_lambda_weight_tbl = TRUE;
cinfo->use_scans_in_trellis = FALSE;
cinfo->trellis_freq_split = 8;
cinfo->trellis_num_loops = 1;
cinfo->trellis_q_opt = FALSE;
}
@@ -673,7 +711,10 @@ jpeg_search_progression (j_compress_ptr cinfo)
/* last 4 done conditionally */
/* luma DC by itself */
scanptr = fill_dc_scans(scanptr, 1, 0, 0);
if (cinfo->one_dc_scan)
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);
@@ -761,7 +802,7 @@ jpeg_simple_progression (j_compress_ptr cinfo)
nscans = 10;
} else {
/* All-purpose script for other color spaces. */
if (cinfo->use_moz_defaults) {
if (cinfo->use_moz_defaults == TRUE) {
if (ncomps > MAX_COMPS_IN_SCAN)
nscans = 5 * ncomps; /* 2 DC + 4 AC scans per component */
else
@@ -793,11 +834,15 @@ jpeg_simple_progression (j_compress_ptr cinfo)
if (ncomps == 3 && cinfo->jpeg_color_space == JCS_YCbCr) {
/* Custom script for YCbCr color images. */
if (cinfo->use_moz_defaults) {
if (cinfo->use_moz_defaults == TRUE) {
/* scan defined in jpeg_scan_rgb.txt in jpgcrush */
/* Initial DC scan */
scanptr = fill_dc_scans(scanptr, 1, 0, 0);
scanptr = fill_a_scan_pair(scanptr, 1, 0, 0, 0, 0);
if (cinfo->one_dc_scan)
scanptr = fill_dc_scans(scanptr, ncomps, 0, 0);
else {
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);
@@ -832,7 +877,7 @@ jpeg_simple_progression (j_compress_ptr cinfo)
}
} else {
/* All-purpose script for other color spaces. */
if (cinfo->use_moz_defaults) {
if (cinfo->use_moz_defaults == TRUE) {
/* scan defined in jpeg_scan_bw.txt in jpgcrush */
/* DC component, no successive approximation */
scanptr = fill_dc_scans(scanptr, ncomps, 0, 0);

View File

@@ -2,6 +2,8 @@
* jcphuff.c
*
* Copyright (C) 1995-1997, 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.
*
@@ -167,6 +169,14 @@ start_pass_phuff (j_compress_ptr cinfo, boolean gather_statistics)
(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
257 * SIZEOF(long));
MEMZERO(entropy->count_ptrs[tbl], 257 * SIZEOF(long));
if (cinfo->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 */
@@ -468,6 +478,8 @@ encode_mcu_AC_first (j_compress_ptr cinfo, JBLOCKROW *MCU_data)
int Se = cinfo->Se;
int Al = cinfo->Al;
JBLOCKROW block;
int deadzone = (1 << Al) - 1;
int sign;
entropy->next_output_byte = cinfo->dest->next_output_byte;
entropy->free_in_buffer = cinfo->dest->free_in_buffer;
@@ -485,29 +497,24 @@ encode_mcu_AC_first (j_compress_ptr cinfo, JBLOCKROW *MCU_data)
r = 0; /* r = run length of zeros */
for (k = cinfo->Ss; k <= Se; k++) {
if ((temp = (*block)[jpeg_natural_order[k]]) == 0) {
temp = (*block)[jpeg_natural_order[k]];
if ((unsigned)(temp + deadzone) <= 2*deadzone) {
r++;
continue;
}
/* We must apply the point transform by Al. For AC coefficients this
* is an integer division with rounding towards 0. To do this portably
* in C, we shift after obtaining the absolute value; so the code is
* is an integer division with rounding towards 0. The code is
* interwoven with finding the abs value (temp) and output bits (temp2).
*/
if (temp < 0) {
temp = -temp; /* temp is abs value of input */
temp >>= Al; /* apply the point transform */
/* For a negative coef, want temp2 = bitwise complement of abs(coef) */
temp2 = ~temp;
} else {
temp >>= Al; /* apply the point transform */
temp2 = temp;
}
/* Watch out for case that nonzero coef is zero after point transform */
if (temp == 0) {
r++;
continue;
}
#ifdef RIGHT_SHIFT_IS_UNSIGNED
sign = (temp < 0) ? ~0 : 0;
#else
sign = temp >> (8*sizeof(temp)-1);
#endif
temp += sign;
temp = (temp ^ sign) >> Al;
temp2 = temp ^ sign;
/* Emit any pending EOBRUN */
if (entropy->EOBRUN > 0)

View File

@@ -89,6 +89,8 @@ jpeg_copy_critical_parameters (j_decompress_ptr srcinfo,
#endif
/* Initialize all parameters to default values */
jpeg_set_defaults(dstinfo);
dstinfo->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.
*/

View File

@@ -1,9 +1,12 @@
/*
* jidctflt.c
*
* This file was part of the Independent JPEG Group's software:
* Copyright (C) 1994-1998, Thomas G. Lane.
* This file is part of the Independent JPEG Group's software.
* For conditions of distribution and use, see the accompanying README file.
* Modified 2010 by Guido Vollbeding.
* libjpeg-turbo Modifications:
* Copyright (C) 2014, D. R. Commander.
* For conditions of distribution and use, see the accompanying README file.
*
* This file contains a floating-point implementation of the
* inverse DCT (Discrete Cosine Transform). In the IJG code, this routine
@@ -76,10 +79,10 @@ jpeg_idct_float (j_decompress_ptr cinfo, jpeg_component_info * compptr,
FLOAT_MULT_TYPE * quantptr;
FAST_FLOAT * wsptr;
JSAMPROW outptr;
JSAMPLE *range_limit = IDCT_range_limit(cinfo);
JSAMPLE *range_limit = cinfo->sample_range_limit;
int ctr;
FAST_FLOAT workspace[DCTSIZE2]; /* buffers data between passes */
SHIFT_TEMPS
#define _0_125 ((FLOAT_MULT_TYPE)0.125)
/* Pass 1: process columns from input, store into work array. */
@@ -101,7 +104,8 @@ jpeg_idct_float (j_decompress_ptr cinfo, jpeg_component_info * compptr,
inptr[DCTSIZE*5] == 0 && inptr[DCTSIZE*6] == 0 &&
inptr[DCTSIZE*7] == 0) {
/* AC terms all zero */
FAST_FLOAT dcval = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]);
FAST_FLOAT dcval = DEQUANTIZE(inptr[DCTSIZE*0],
quantptr[DCTSIZE*0] * _0_125);
wsptr[DCTSIZE*0] = dcval;
wsptr[DCTSIZE*1] = dcval;
@@ -120,10 +124,10 @@ jpeg_idct_float (j_decompress_ptr cinfo, jpeg_component_info * compptr,
/* Even part */
tmp0 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]);
tmp1 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]);
tmp2 = DEQUANTIZE(inptr[DCTSIZE*4], quantptr[DCTSIZE*4]);
tmp3 = DEQUANTIZE(inptr[DCTSIZE*6], quantptr[DCTSIZE*6]);
tmp0 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0] * _0_125);
tmp1 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2] * _0_125);
tmp2 = DEQUANTIZE(inptr[DCTSIZE*4], quantptr[DCTSIZE*4] * _0_125);
tmp3 = DEQUANTIZE(inptr[DCTSIZE*6], quantptr[DCTSIZE*6] * _0_125);
tmp10 = tmp0 + tmp2; /* phase 3 */
tmp11 = tmp0 - tmp2;
@@ -138,10 +142,10 @@ jpeg_idct_float (j_decompress_ptr cinfo, jpeg_component_info * compptr,
/* Odd part */
tmp4 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]);
tmp5 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]);
tmp6 = DEQUANTIZE(inptr[DCTSIZE*5], quantptr[DCTSIZE*5]);
tmp7 = DEQUANTIZE(inptr[DCTSIZE*7], quantptr[DCTSIZE*7]);
tmp4 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1] * _0_125);
tmp5 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3] * _0_125);
tmp6 = DEQUANTIZE(inptr[DCTSIZE*5], quantptr[DCTSIZE*5] * _0_125);
tmp7 = DEQUANTIZE(inptr[DCTSIZE*7], quantptr[DCTSIZE*7] * _0_125);
z13 = tmp6 + tmp5; /* phase 6 */
z10 = tmp6 - tmp5;
@@ -152,12 +156,12 @@ jpeg_idct_float (j_decompress_ptr cinfo, jpeg_component_info * compptr,
tmp11 = (z11 - z13) * ((FAST_FLOAT) 1.414213562); /* 2*c4 */
z5 = (z10 + z12) * ((FAST_FLOAT) 1.847759065); /* 2*c2 */
tmp10 = ((FAST_FLOAT) 1.082392200) * z12 - z5; /* 2*(c2-c6) */
tmp12 = ((FAST_FLOAT) -2.613125930) * z10 + z5; /* -2*(c2+c6) */
tmp10 = z5 - z12 * ((FAST_FLOAT) 1.082392200); /* 2*(c2-c6) */
tmp12 = z5 - z10 * ((FAST_FLOAT) 2.613125930); /* 2*(c2+c6) */
tmp6 = tmp12 - tmp7; /* phase 2 */
tmp5 = tmp11 - tmp6;
tmp4 = tmp10 + tmp5;
tmp4 = tmp10 - tmp5;
wsptr[DCTSIZE*0] = tmp0 + tmp7;
wsptr[DCTSIZE*7] = tmp0 - tmp7;
@@ -165,8 +169,8 @@ jpeg_idct_float (j_decompress_ptr cinfo, jpeg_component_info * compptr,
wsptr[DCTSIZE*6] = tmp1 - tmp6;
wsptr[DCTSIZE*2] = tmp2 + tmp5;
wsptr[DCTSIZE*5] = tmp2 - tmp5;
wsptr[DCTSIZE*4] = tmp3 + tmp4;
wsptr[DCTSIZE*3] = tmp3 - tmp4;
wsptr[DCTSIZE*3] = tmp3 + tmp4;
wsptr[DCTSIZE*4] = tmp3 - tmp4;
inptr++; /* advance pointers to next column */
quantptr++;
@@ -174,7 +178,6 @@ jpeg_idct_float (j_decompress_ptr cinfo, jpeg_component_info * compptr,
}
/* Pass 2: process rows from work array, store into output array. */
/* Note that we must descale the results by a factor of 8 == 2**3. */
wsptr = workspace;
for (ctr = 0; ctr < DCTSIZE; ctr++) {
@@ -187,8 +190,10 @@ jpeg_idct_float (j_decompress_ptr cinfo, jpeg_component_info * compptr,
/* Even part */
tmp10 = wsptr[0] + wsptr[4];
tmp11 = wsptr[0] - wsptr[4];
/* Apply signed->unsigned and prepare float->int conversion */
z5 = wsptr[0] + ((FAST_FLOAT) CENTERJSAMPLE + (FAST_FLOAT) 0.5);
tmp10 = z5 + wsptr[4];
tmp11 = z5 - wsptr[4];
tmp13 = wsptr[2] + wsptr[6];
tmp12 = (wsptr[2] - wsptr[6]) * ((FAST_FLOAT) 1.414213562) - tmp13;
@@ -209,31 +214,23 @@ jpeg_idct_float (j_decompress_ptr cinfo, jpeg_component_info * compptr,
tmp11 = (z11 - z13) * ((FAST_FLOAT) 1.414213562);
z5 = (z10 + z12) * ((FAST_FLOAT) 1.847759065); /* 2*c2 */
tmp10 = ((FAST_FLOAT) 1.082392200) * z12 - z5; /* 2*(c2-c6) */
tmp12 = ((FAST_FLOAT) -2.613125930) * z10 + z5; /* -2*(c2+c6) */
tmp10 = z5 - z12 * ((FAST_FLOAT) 1.082392200); /* 2*(c2-c6) */
tmp12 = z5 - z10 * ((FAST_FLOAT) 2.613125930); /* 2*(c2+c6) */
tmp6 = tmp12 - tmp7;
tmp5 = tmp11 - tmp6;
tmp4 = tmp10 + tmp5;
tmp4 = tmp10 - tmp5;
/* Final output stage: scale down by a factor of 8 and range-limit */
/* Final output stage: float->int conversion and range-limit */
outptr[0] = range_limit[(int) DESCALE((INT32) (tmp0 + tmp7), 3)
& RANGE_MASK];
outptr[7] = range_limit[(int) DESCALE((INT32) (tmp0 - tmp7), 3)
& RANGE_MASK];
outptr[1] = range_limit[(int) DESCALE((INT32) (tmp1 + tmp6), 3)
& RANGE_MASK];
outptr[6] = range_limit[(int) DESCALE((INT32) (tmp1 - tmp6), 3)
& RANGE_MASK];
outptr[2] = range_limit[(int) DESCALE((INT32) (tmp2 + tmp5), 3)
& RANGE_MASK];
outptr[5] = range_limit[(int) DESCALE((INT32) (tmp2 - tmp5), 3)
& RANGE_MASK];
outptr[4] = range_limit[(int) DESCALE((INT32) (tmp3 + tmp4), 3)
& RANGE_MASK];
outptr[3] = range_limit[(int) DESCALE((INT32) (tmp3 - tmp4), 3)
& RANGE_MASK];
outptr[0] = range_limit[((int) (tmp0 + tmp7)) & RANGE_MASK];
outptr[7] = range_limit[((int) (tmp0 - tmp7)) & RANGE_MASK];
outptr[1] = range_limit[((int) (tmp1 + tmp6)) & RANGE_MASK];
outptr[6] = range_limit[((int) (tmp1 - tmp6)) & RANGE_MASK];
outptr[2] = range_limit[((int) (tmp2 + tmp5)) & RANGE_MASK];
outptr[5] = range_limit[((int) (tmp2 - tmp5)) & RANGE_MASK];
outptr[3] = range_limit[((int) (tmp3 + tmp4)) & RANGE_MASK];
outptr[4] = range_limit[((int) (tmp3 - tmp4)) & RANGE_MASK];
wsptr += DCTSIZE; /* advance pointer to next row */
}

4098
jpeg_nbits_table.h Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -3,6 +3,8 @@
*
* Copyright (C) 1991-1997, Thomas G. Lane.
* Modified 1997-2009 by Guido Vollbeding.
* 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.
*
@@ -19,7 +21,9 @@ 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_SAVE_AND_PASS, /* Run both subobjects, save output */
JBUF_REQUANT /* Requantize */
} J_BUF_MODE;
/* Values of global_state field (jdapi.c has some dependencies on ordering!) */
@@ -107,7 +111,7 @@ struct jpeg_forward_dct {
jpeg_component_info * compptr,
JSAMPARRAY sample_data, JBLOCKROW coef_blocks,
JDIMENSION start_row, JDIMENSION start_col,
JDIMENSION num_blocks));
JDIMENSION num_blocks, JBLOCKROW dst));
};
/* Entropy encoding */

View File

@@ -376,8 +376,22 @@ struct jpeg_compress_struct {
int smoothing_factor; /* 1..100, or 0 for no input smoothing */
J_DCT_METHOD dct_method; /* DCT algorithm selector */
boolean use_moz_defaults; /* TRUE if using Mozilla defaults */
boolean use_moz_defaults; /* TRUE=use Mozilla defaults */
boolean optimize_scans; /* TRUE=optimize progressive coding scans */
boolean one_dc_scan; /* TRUE=use a single DC scan interleaving all components */
boolean trellis_quant; /* TRUE=use trellis quantization */
boolean trellis_eob_opt; /* TRUE=optimize for sequences of EOB */
boolean use_flat_quant_tbl; /* TRUE=use flat quantization table */
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 */
boolean trellis_q_opt; /* TRUE=optimize quant table in trellis loop */
double norm_src[NUM_QUANT_TBLS][DCTSIZE2];
double norm_coef[NUM_QUANT_TBLS][DCTSIZE2];
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;
@@ -387,6 +401,9 @@ struct jpeg_compress_struct {
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;
/* The restart interval can be specified in absolute MCUs by setting
* restart_interval, or in MCU rows by setting restart_in_rows
* (in which case the correct restart_interval will be figured

View File

@@ -48,14 +48,20 @@ int main(int argc, char *argv[]) {
struct jpeg_decompress_struct cinfo;
struct jpeg_error_mgr jerr;
FILE *jpg_fd;
int width;
int height;
int luma_width;
int luma_height;
int chroma_width;
int chroma_height;
int frame_width;
int frame_height;
int yuv_size;
JSAMPLE *image_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;
@@ -90,32 +96,54 @@ int main(int argc, char *argv[]) {
jpeg_start_decompress(&cinfo);
width = cinfo.output_width;
height = cinfo.output_height;
/* Right now we only support dimensions that are multiples of 16. */
if ((width % 16) != 0 || (height % 16) != 0) {
fprintf(stderr, "Image dimensions must be multiples of 16!\n");
return 1;
}
luma_width = cinfo.output_width;
luma_height = cinfo.output_height;
yuv_size = (width * height) + (((width >> 1) * (height >> 1)) * 2);
image_buffer = malloc(yuv_size);
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);
frame_width = (cinfo.output_width + (16 - 1)) & ~(16 - 1);
frame_height = (cinfo.output_height + (16 - 1)) & ~(16 - 1);
image_buffer = malloc(frame_width*16 + 2*(frame_width/2)*8);
plane_pointer[0] = yrow_pointer;
plane_pointer[1] = cbrow_pointer;
plane_pointer[2] = crrow_pointer;
for (y = 0; y < 16; y++) {
yrow_pointer[y] = &image_buffer[frame_width*y];
}
for (y = 0; y < 8; y++) {
cbrow_pointer[y] = &image_buffer[frame_width*16 + (frame_width/2)*y];
crrow_pointer[y] = &image_buffer[frame_width*16 + (frame_width/2)*(8 + y)];
}
while (cinfo.output_scanline < cinfo.output_height) {
for (y = 0; y < 16; y++) {
yrow_pointer[y] = image_buffer + cinfo.image_width * (cinfo.output_scanline + y);
}
for (y = 0; y < 8; y++) {
cbrow_pointer[y] = image_buffer + width * height +
((width + 1) >> 1) * ((cinfo.output_scanline >> 1) + y);
crrow_pointer[y] = image_buffer + width * height +
((width + 1) >> 1) * ((height + 1) >> 1) +
((width + 1) >> 1) * ((cinfo.output_scanline >> 1) + y);
}
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);
@@ -124,15 +152,19 @@ int main(int argc, char *argv[]) {
fclose(jpg_fd);
free(image_buffer);
yuv_fd = fopen(yuv_path, "wb");
if (!yuv_fd) {
fprintf(stderr, "Invalid path to YUV file!");
return 1;
}
if (fwrite(image_buffer, yuv_size, 1, yuv_fd)!=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,6 +5,8 @@
* Copyright (C) 1991-2012, Thomas G. Lane, Guido Vollbeding.
* Modifications:
* Copyright (C) 2010, 2012-2013, D. R. Commander.
* mozjpeg Modifications:
* Copyright (C) 2014, Mozilla Corporation.
* For conditions of distribution and use, see the accompanying README file.
*
* This file contains software version identification.
@@ -29,4 +31,6 @@
"Copyright (C) 1999-2006 MIYASAKA Masaru\n" \
"Copyright (C) 2009 Pierre Ossman for Cendio AB\n" \
"Copyright (C) 2009-2013 D. R. Commander\n" \
"Copyright (C) 2009-2011 Nokia Corporation and/or its subsidiary(-ies)"
"Copyright (C) 2009-2011 Nokia Corporation and/or its subsidiary(-ies)\n" \
"Copyright (C) 2014 Mozilla Corporation\n"

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-2011, Thomas G. Lane, Guido Vollbeding.
Modifications:
Copyright (C) 2010, D. R. Commander.
Copyright (C) 2010, 2014, D. R. Commander.
For conditions of distribution and use, see the accompanying README file.
@@ -886,14 +886,23 @@ J_DCT_METHOD dct_method
JDCT_FLOAT: floating-point method
JDCT_DEFAULT: default method (normally JDCT_ISLOW)
JDCT_FASTEST: fastest method (normally JDCT_IFAST)
The FLOAT method is very slightly more accurate than the ISLOW method,
but may give different results on different machines due to varying
roundoff behavior. The integer methods should give the same results
on all machines. On machines with sufficiently fast FP hardware, the
floating-point method may also be the fastest. The IFAST method is
considerably less accurate than the other two; its use is not
recommended if high quality is a concern. JDCT_DEFAULT and
JDCT_FASTEST are macros configurable by each installation.
In libjpeg-turbo, JDCT_IFAST is generally about 5-15% faster than
JDCT_ISLOW when using the x86/x86-64 SIMD extensions (results may vary
with other SIMD implementations, or when using libjpeg-turbo without
SIMD extensions.) For quality levels of 90 and below, there should be
little or no perceptible difference between the two algorithms. For
quality levels above 90, however, the difference between JDCT_IFAST and
JDCT_ISLOW becomes more pronounced. With quality=97, for instance,
JDCT_IFAST incurs generally about a 1-3 dB loss (in PSNR) relative to
JDCT_ISLOW, but this can be larger for some images. Do not use
JDCT_IFAST with quality levels above 97. The algorithm often
degenerates at quality=98 and above and can actually produce a more
lossy image than if lower quality levels had been used. JDCT_FLOAT is
mostly a legacy feature. It does not produce significantly more
accurate results than the ISLOW method, and it is much slower. The
FLOAT method may also give different results on different machines due
to varying roundoff behavior, whereas the integer methods should give
the same results on all machines.
J_COLOR_SPACE jpeg_color_space
int num_components
@@ -1170,8 +1179,32 @@ int actual_number_of_colors
Additional decompression parameters that the application may set include:
J_DCT_METHOD dct_method
Selects the algorithm used for the DCT step. Choices are the same
as described above for compression.
Selects the algorithm used for the DCT step. Choices are:
JDCT_ISLOW: slow but accurate integer algorithm
JDCT_IFAST: faster, less accurate integer method
JDCT_FLOAT: floating-point method
JDCT_DEFAULT: default method (normally JDCT_ISLOW)
JDCT_FASTEST: fastest method (normally JDCT_IFAST)
In libjpeg-turbo, JDCT_IFAST is generally about 5-15% faster than
JDCT_ISLOW when using the x86/x86-64 SIMD extensions (results may vary
with other SIMD implementations, or when using libjpeg-turbo without
SIMD extensions.) If the JPEG image was compressed using a quality
level of 85 or below, then there should be little or no perceptible
difference between the two algorithms. When decompressing images that
were compressed using quality levels above 85, however, the difference
between JDCT_IFAST and JDCT_ISLOW becomes more pronounced. With images
compressed using quality=97, for instance, JDCT_IFAST incurs generally
about a 4-6 dB loss (in PSNR) relative to JDCT_ISLOW, but this can be
larger for some images. If you can avoid it, do not use JDCT_IFAST
when decompressing images that were compressed using quality levels
above 97. The algorithm often degenerates for such images and can
actually produce a more lossy output image than if the JPEG image had
been compressed using lower quality levels. JDCT_FLOAT is mostly a
legacy feature. It does not produce significantly more accurate
results than the ISLOW method, and it is much slower. The FLOAT method
may also give different results on different machines due to varying
roundoff behavior, whereas the integer methods should give the same
results on all machines.
boolean do_fancy_upsampling
If TRUE, do careful upsampling of chroma components. If FALSE,

160
rdjpeg.c Normal file
View File

@@ -0,0 +1,160 @@
/*
* 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

@@ -300,14 +300,31 @@ static const unsigned int std_chrominance_quant_tbl[DCTSIZE2] = {
99, 99, 99, 99, 99, 99, 99, 99
};
static const unsigned int flat_quant_tbl[DCTSIZE2] = {
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
};
LOCAL(void)
jpeg_default_qtables (j_compress_ptr cinfo, boolean 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);
if (cinfo->use_flat_quant_tbl) {
jpeg_add_quant_table(cinfo, 0, flat_quant_tbl,
q_scale_factor[0], force_baseline);
jpeg_add_quant_table(cinfo, 1, flat_quant_tbl,
q_scale_factor[1], force_baseline);
} else {
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

View File

@@ -16,7 +16,7 @@ if(MSVC)
endif()
foreach(src ${JPEG_SOURCES})
set(JPEG_SRCS ${JPEG_SRCS} ${CMAKE_SOURCE_DIR}/${src})
list(APPEND JPEG_SRCS "${CMAKE_SOURCE_DIR}/${src}")
endforeach()
if(WITH_SIMD)
@@ -26,10 +26,10 @@ endif()
if(WITH_MEM_SRCDST AND NOT WITH_JPEG8)
add_library(jpeg SHARED ${JPEG_SRCS} ${SIMD_OBJS}
${CMAKE_SOURCE_DIR}/win/jpeg${DLL_VERSION}-memsrcdst.def)
"${CMAKE_SOURCE_DIR}/win/jpeg${DLL_VERSION}-memsrcdst.def")
else()
add_library(jpeg SHARED ${JPEG_SRCS} ${SIMD_OBJS}
${CMAKE_SOURCE_DIR}/win/jpeg${DLL_VERSION}.def)
"${CMAKE_SOURCE_DIR}/win/jpeg${DLL_VERSION}.def")
endif()
set_target_properties(jpeg PROPERTIES SOVERSION ${DLL_VERSION}
VERSION ${FULLVERSION})
@@ -43,7 +43,7 @@ if(WITH_SIMD)
endif()
add_executable(cjpeg ../cjpeg.c ../cdjpeg.c ../rdbmp.c ../rdgif.c ../rdppm.c
../rdswitch.c ../rdtarga.c)
../rdswitch.c ../rdtarga.c ../rdjpeg.c)
set_property(TARGET cjpeg PROPERTY COMPILE_FLAGS
"-DBMP_SUPPORTED -DGIF_SUPPORTED -DPPM_SUPPORTED -DTARGA_SUPPORTED -DUSE_SETMODE")
target_link_libraries(cjpeg jpeg)

View File

@@ -3,11 +3,11 @@ if(NOT DEFINED NASM)
endif()
if(SIMD_X86_64)
set(NAFLAGS -fwin64 -DWIN64 -D__x86_64__ -I${CMAKE_SOURCE_DIR}/win/
-I${CMAKE_CURRENT_SOURCE_DIR}/)
set(NAFLAGS -fwin64 -DWIN64 -D__x86_64__ "-I${CMAKE_SOURCE_DIR}/win/"
"-I${CMAKE_CURRENT_SOURCE_DIR}/")
else()
set(NAFLAGS -fwin32 -DWIN32 -I${CMAKE_SOURCE_DIR}/win/
-I${CMAKE_CURRENT_SOURCE_DIR}/)
set(NAFLAGS -fwin32 -DWIN32 "-I${CMAKE_SOURCE_DIR}/win/"
"-I${CMAKE_CURRENT_SOURCE_DIR}/")
endif()
# This only works if building from the command line. There is currently no way
@@ -34,34 +34,35 @@ endif()
if(MSVC_IDE)
set(OBJDIR "${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}")
else()
set(OBJDIR ${CMAKE_CURRENT_BINARY_DIR})
set(OBJDIR "${CMAKE_CURRENT_BINARY_DIR}")
endif()
file(GLOB INC_FILES *.inc)
foreach(file ${SIMD_BASENAMES})
set(DEPFILE "")
set(SIMD_SRC ${CMAKE_CURRENT_SOURCE_DIR}/${file}.asm)
if(${file} MATCHES col)
set(DEPFILE ${file})
string(REGEX REPLACE "col" "clr" DEPFILE ${DEPFILE})
set(DEPFILE ${CMAKE_CURRENT_SOURCE_DIR}/${DEPFILE}.asm)
set(SIMD_SRC "${CMAKE_CURRENT_SOURCE_DIR}/${file}.asm")
if("${file}" MATCHES col)
set(DEPFILE "${file}")
string(REGEX REPLACE "col" "clr" DEPFILE "${DEPFILE}")
set(DEPFILE "${CMAKE_CURRENT_SOURCE_DIR}/${DEPFILE}.asm")
endif()
if(${file} MATCHES mer)
set(DEPFILE ${file})
string(REGEX REPLACE "mer" "mrg" DEPFILE ${DEPFILE})
set(DEPFILE ${CMAKE_CURRENT_SOURCE_DIR}/${DEPFILE}.asm)
if("${file}" MATCHES mer)
set(DEPFILE "${file}")
string(REGEX REPLACE "mer" "mrg" DEPFILE "${DEPFILE}")
set(DEPFILE "${CMAKE_CURRENT_SOURCE_DIR}/${DEPFILE}.asm")
endif()
if(${file} MATCHES gra)
set(DEPFILE ${file})
string(REGEX REPLACE "gra" "gry" DEPFILE ${DEPFILE})
set(DEPFILE ${CMAKE_CURRENT_SOURCE_DIR}/${DEPFILE}.asm)
if("${file}" MATCHES gra)
set(DEPFILE "${file}")
string(REGEX REPLACE "gra" "gry" DEPFILE "${DEPFILE}")
set(DEPFILE "${CMAKE_CURRENT_SOURCE_DIR}/${DEPFILE}.asm")
endif()
set(SIMD_OBJ ${OBJDIR}/${file}.obj)
add_custom_command(OUTPUT ${SIMD_OBJ}
DEPENDS ${SIMD_SRC} ${DEPFILE} ${INC_FILES}
COMMAND ${NASM} ${NAFLAGS} ${SIMD_SRC} -o${SIMD_OBJ})
set(SIMD_OBJS ${SIMD_OBJS} ${SIMD_OBJ})
set(SIMD_OBJ "${OBJDIR}/${file}.obj")
add_custom_command(OUTPUT "${SIMD_OBJ}"
DEPENDS "${SIMD_SRC}" "${DEPFILE}" ${INC_FILES}
COMMAND "${NASM}" ${NAFLAGS} "${SIMD_SRC}" "-o${SIMD_OBJ}"
VERBATIM)
list(APPEND SIMD_OBJS "${SIMD_OBJ}")
endforeach()
set(SIMD_OBJS ${SIMD_OBJS} PARENT_SCOPE)

View File

@@ -67,7 +67,7 @@ endif
AM_CPPFLAGS = -I$(top_srcdir)
.asm.lo:
$(LIBTOOL) --mode=compile --tag NASM $(srcdir)/nasm_lt.sh $(NASM) $(NAFLAGS) -I$(srcdir) -I. $< -o $@
$(AM_V_GEN) $(LIBTOOL) $(AM_V_lt) --mode=compile $(srcdir)/nasm_lt.sh $(AM_V_lt) $(NASM) $(NAFLAGS) -I$(srcdir) -I. $< -o $@
jsimdcfg.inc: $(srcdir)/jsimdcfg.inc.h ../jpeglib.h ../jconfig.h ../jmorecfg.h
$(CPP) -I$(top_builddir) -I$(top_builddir)/simd $(srcdir)/jsimdcfg.inc.h | $(EGREP) "^[\;%]|^\ %" | sed 's%_cpp_protection_%%' | sed 's@% define@%define@g' > $@
$(AM_V_GEN) $(CPP) -I$(top_builddir) -I$(top_builddir)/simd $(srcdir)/jsimdcfg.inc.h | $(EGREP) "^[\;%]|^\ %" | sed 's%_cpp_protection_%%' | sed 's@% define@%define@g' > $@

View File

@@ -5,6 +5,9 @@ o_opt=no
pic=no
while [ $# -gt 0 ]; do
case "$1" in
--silent)
exec > /dev/null
;;
-DPIC|-fPIC|-fpic|-Kpic|-KPIC)
if [ "$pic" != "yes" ] ; then
command="$command -DPIC"

View File

@@ -256,7 +256,7 @@ int decomptest(unsigned char *srcbuf, unsigned char **jpegbuf,
}
void dotestyuv(unsigned char *srcbuf, int w, int h, int subsamp,
int dotestyuv(unsigned char *srcbuf, int w, int h, int subsamp,
char *filename)
{
char tempstr[1024], tempstr2[80];
@@ -328,11 +328,11 @@ void dotestyuv(unsigned char *srcbuf, int w, int h, int subsamp,
if(file) {fclose(file); file=NULL;}
if(dstbuf) {free(dstbuf); dstbuf=NULL;}
if(handle) {tjDestroy(handle); handle=NULL;}
return;
return retval;
}
void dotest(unsigned char *srcbuf, int w, int h, int subsamp, int jpegqual,
int dotest(unsigned char *srcbuf, int w, int h, int subsamp, int jpegqual,
char *filename)
{
char tempstr[1024], tempstr2[80];
@@ -345,7 +345,7 @@ void dotest(unsigned char *srcbuf, int w, int h, int subsamp, int jpegqual,
int ntilesw=1, ntilesh=1, pitch=w*ps;
const char *pfStr=(yuv==YUVCOMPRESS)? "YUV":pixFormatStr[pf];
if(yuv==YUVENCODE) {dotestyuv(srcbuf, w, h, subsamp, filename); return;}
if(yuv==YUVENCODE) {dotestyuv(srcbuf, w, h, subsamp, filename); return retval;}
if((tmpbuf=(unsigned char *)malloc(pitch*h)) == NULL)
_throwunix("allocating temporary image buffer");
@@ -498,11 +498,11 @@ void dotest(unsigned char *srcbuf, int w, int h, int subsamp, int jpegqual,
if(jpegsize) {free(jpegsize); jpegsize=NULL;}
if(tmpbuf) {free(tmpbuf); tmpbuf=NULL;}
if(handle) {tjDestroy(handle); handle=NULL;}
return;
return retval;
}
void dodecomptest(char *filename)
int dodecomptest(char *filename)
{
FILE *file=NULL; tjhandle handle=NULL;
unsigned char **jpegbuf=NULL, *srcbuf=NULL;
@@ -706,7 +706,7 @@ void dodecomptest(char *filename)
if(srcbuf) {free(srcbuf); srcbuf=NULL;}
if(t) {free(t); t=NULL;}
if(handle) {tjDestroy(handle); handle=NULL;}
return;
return retval;
}

View File

@@ -1171,6 +1171,7 @@ transpose_critical_parameters (j_compress_ptr dstinfo)
}
#if JPEG_LIB_VERSION >= 70
/* Adjust Exif image parameters.
*
* We try to adjust the Tags ExifImageWidth and ExifImageHeight if possible.
@@ -1325,6 +1326,7 @@ adjust_exif_parameters (JOCTET FAR * data, unsigned int length,
offset += 12;
} while (--number_of_tags);
}
#endif
/* Adjust output image parameters as needed.

View File

@@ -123,7 +123,10 @@ static const tjscalingfactor sf[NUMSF]={
j_compress_ptr cinfo=NULL; j_decompress_ptr dinfo=NULL; \
if(!this) {snprintf(errStr, JMSG_LENGTH_MAX, "Invalid handle"); \
return -1;} \
cinfo=&this->cinfo; dinfo=&this->dinfo;
cinfo=&this->cinfo; \
(void)cinfo; \
dinfo=&this->dinfo; \
(void)dinfo
static int getPixelFormat(int pixelSize, int flags)
{
@@ -612,7 +615,7 @@ DLLEXPORT int DLLCALL tjCompress2(tjhandle handle, unsigned char *srcBuf,
unsigned char *rgbBuf=NULL;
#endif
getinstance(handle)
getinstance(handle);
if((this->init&COMPRESS)==0)
_throw("tjCompress2(): Instance has not been initialized for compression");
@@ -878,7 +881,7 @@ DLLEXPORT int DLLCALL tjCompressFromYUV(tjhandle handle, unsigned char *srcBuf,
tmpbufsize=0, usetmpbuf=0, th[MAX_COMPONENTS];
JSAMPLE *_tmpbuf=NULL, *ptr=srcBuf; JSAMPROW *tmpbuf[MAX_COMPONENTS];
getinstance(handle)
getinstance(handle);
for(i=0; i<MAX_COMPONENTS; i++)
{

View File

@@ -172,13 +172,28 @@ Switches for advanced users:
-dct int Use integer DCT method (default).
-dct fast Use fast integer DCT (less accurate).
-dct float Use floating-point DCT method.
The float method is very slightly more accurate than
the int method, but is much slower unless your machine
has very fast floating-point hardware. Also note that
results of the floating-point method may vary slightly
across machines, while the integer methods should give
the same results everywhere. The fast integer method
is much less accurate than the other two.
In libjpeg-turbo, the fast method is generally about
5-15% faster than the int method when using the
x86/x86-64 SIMD extensions (results may vary with other
SIMD implementations, or when using libjpeg-turbo
without SIMD extensions.) For quality levels of 90 and
below, there should be little or no perceptible
difference between the two algorithms. For quality
levels above 90, however, the difference between
the fast and the int methods becomes more pronounced.
With quality=97, for instance, the fast method incurs
generally about a 1-3 dB loss (in PSNR) relative to
the int method, but this can be larger for some images.
Do not use the fast method with quality levels above
97. The algorithm often degenerates at quality=98 and
above and can actually produce a more lossy image than
if lower quality levels had been used. The float
method is mostly a legacy feature. It does not produce
significantly more accurate results than the int
method, and it is much slower. The float method may
also give different results on different machines due
to varying roundoff behavior, whereas the integer
methods should give the same results on all machines.
-restart N Emit a JPEG restart marker every N MCU rows, or every
N MCU blocks if "B" is attached to the number.
@@ -296,13 +311,32 @@ Switches for advanced users:
-dct int Use integer DCT method (default).
-dct fast Use fast integer DCT (less accurate).
-dct float Use floating-point DCT method.
The float method is very slightly more accurate than
the int method, but is much slower unless your machine
has very fast floating-point hardware. Also note that
results of the floating-point method may vary slightly
across machines, while the integer methods should give
the same results everywhere. The fast integer method
is much less accurate than the other two.
In libjpeg-turbo, the fast method is generally about
5-15% faster than the int method when using the
x86/x86-64 SIMD extensions (results may vary with other
SIMD implementations, or when using libjpeg-turbo
without SIMD extensions.) If the JPEG image was
compressed using a quality level of 85 or below, then
there should be little or no perceptible difference
between the two algorithms. When decompressing images
that were compressed using quality levels above 85,
however, the difference between the fast and int
methods becomes more pronounced. With images
compressed using quality=97, for instance, the fast
method incurs generally about a 4-6 dB loss (in PSNR)
relative to the int method, but this can be larger for
some images. If you can avoid it, do not use the fast
method when decompressing images that were compressed
using quality levels above 97. The algorithm often
degenerates for such images and can actually produce
a more lossy output image than if the JPEG image had
been compressed using lower quality levels. The float
method is mostly a legacy feature. It does not produce
significantly more accurate results than the int
method, and it is much slower. The float method may
also give different results on different machines due
to varying roundoff behavior, whereas the integer
methods should give the same results on all machines.
-dither fs Use Floyd-Steinberg dithering in color quantization.
-dither ordered Use ordered dithering in color quantization.
@@ -381,12 +415,6 @@ When producing a color-quantized image, "-onepass -dither ordered" is fast but
much lower quality than the default behavior. "-dither none" may give
acceptable results in two-pass mode, but is seldom tolerable in one-pass mode.
If you are fortunate enough to have very fast floating point hardware,
"-dct float" may be even faster than "-dct fast". But on most machines
"-dct float" is slower than "-dct int"; in this case it is not worth using,
because its theoretical accuracy advantage is too small to be significant
in practice.
Two-pass color quantization requires a good deal of memory; on MS-DOS machines
it may run out of memory even with -maxmemory 0. In that case you can still
decompress, with some loss of image quality, by specifying -onepass for

View File

@@ -2,6 +2,8 @@
* wrjpgcom.c
*
* Copyright (C) 1994-1997, Thomas G. Lane.
* libjpeg-turbo Modifications:
* Copyright (C) 2014, D. R. Commander
* This file is part of the Independent JPEG Group's software.
* For conditions of distribution and use, see the accompanying README file.
*
@@ -453,6 +455,11 @@ main (int argc, char **argv)
comment_arg = (char *) malloc((size_t) MAX_COM_LENGTH);
if (comment_arg == NULL)
ERREXIT("Insufficient memory");
if (strlen(argv[argn]) + 2 >= (size_t) MAX_COM_LENGTH) {
fprintf(stderr, "Comment text may not exceed %u bytes\n",
(unsigned int) MAX_COM_LENGTH);
exit(EXIT_FAILURE);
}
strcpy(comment_arg, argv[argn]+1);
for (;;) {
comment_length = (unsigned int) strlen(comment_arg);
@@ -462,9 +469,19 @@ main (int argc, char **argv)
}
if (++argn >= argc)
ERREXIT("Missing ending quote mark");
if (strlen(comment_arg) + strlen(argv[argn]) + 2 >=
(size_t) MAX_COM_LENGTH) {
fprintf(stderr, "Comment text may not exceed %u bytes\n",
(unsigned int) MAX_COM_LENGTH);
exit(EXIT_FAILURE);
}
strcat(comment_arg, " ");
strcat(comment_arg, argv[argn]);
}
} else if (strlen(argv[argn]) >= (size_t) MAX_COM_LENGTH) {
fprintf(stderr, "Comment text may not exceed %u bytes\n",
(unsigned int) MAX_COM_LENGTH);
exit(EXIT_FAILURE);
}
comment_length = (unsigned int) strlen(comment_arg);
} else

121
yuvjpeg.c
View File

@@ -41,16 +41,71 @@
#include "jpeglib.h"
void extend_edge(JSAMPLE *image, int width, int height, unsigned char *yuv,
int luma_width, int luma_height, int chroma_width, int chroma_height) {
int x;
int y;
for (y = 0; y < luma_height; y++) {
for (x = 0; x < luma_width; x++) {
image[width*y + x] = yuv[luma_width*y + x];
}
}
for (y = 0; y < chroma_height; y++) {
for (x = 0; x < chroma_width; x++) {
image[width*height + (width/2)*y + x] =
yuv[luma_width*luma_height + chroma_width*y + x];
image[width*height + (width/2)*((height/2) + y) + x] =
yuv[luma_width*luma_height + chroma_width*(chroma_height + y) + x];
}
}
/* Perform right edge extension. */
for (y = 0; y < luma_height; y++) {
for (x = luma_width; x < width; x++) {
image[width*y + x] = image[width*y + (x - 1)];
}
}
for (y = 0; y < chroma_height; y++) {
for (x = chroma_width; x < width/2; x++) {
image[width*height + (width/2)*y + x] =
image[width*height + (width/2)*y + (x - 1)];
image[width*height + (width/2)*((height/2) + y) + x] =
image[width*height + (width/2)*((height/2) + y) + (x - 1)];
}
}
/* Perform bottom edge extension. */
for (x = 0; x < width; x++) {
for (y = luma_height; y < height; y++) {
image[width*y + x] = image[width*(y - 1) + x];
}
}
for (x = 0; x < width/2; x++) {
for (y = chroma_height; y < height/2; y++) {
image[width*height + (width/2)*y + x] =
image[width*height + (width/2)*(y - 1) + x];
image[width*height + (width/2)*((height/2) + y) + x] =
image[width*height + (width/2)*((height/2) + (y - 1)) + x];
}
}
}
int main(int argc, char *argv[]) {
long quality;
const char *size;
char *x;
long width;
long height;
int luma_width;
int luma_height;
int chroma_width;
int chroma_height;
int frame_width;
int frame_height;
const char *yuv_path;
const char *jpg_path;
FILE *yuv_fd;
size_t yuv_size;
unsigned char *yuv_buffer;
JSAMPLE *image_buffer;
struct jpeg_compress_struct cinfo;
struct jpeg_error_mgr jerr;
@@ -64,7 +119,7 @@ int main(int argc, char *argv[]) {
if (argc != 5) {
fprintf(stderr, "Required arguments:\n");
fprintf(stderr, "1. JPEG quality value, 0-100\n");
fprintf(stderr, "2. Image size (e.g. '512x512'\n");
fprintf(stderr, "2. Image size (e.g. '512x512')\n");
fprintf(stderr, "3. Path to YUV input file\n");
fprintf(stderr, "4. Path to JPG output file\n");
return 1;
@@ -84,22 +139,24 @@ int main(int argc, char *argv[]) {
fprintf(stderr, "Invalid image size input!\n");
return 1;
}
width = strtol(size, NULL, 10);
luma_width = (int)strtol(size, NULL, 10);
if (errno != 0) {
fprintf(stderr, "Invalid image size input!\n");
return 1;
}
height = strtol(x + 1, NULL, 10);
luma_height = (int)strtol(x + 1, NULL, 10);
if (errno != 0) {
fprintf(stderr, "Invalid image size input!\n");
return 1;
}
/* Right now we only support dimensions that are multiples of 16. */
if ((width % 16) != 0 || (height % 16) != 0) {
fprintf(stderr, "Image dimensions must be multiples of 16!\n");
if (luma_width <= 0 || luma_height <= 0) {
fprintf(stderr, "Invalid image size input!\n");
return 1;
}
chroma_width = (luma_width + 1) >> 1;
chroma_height = (luma_height + 1) >> 1;
/* Will check these for validity when opening via 'fopen'. */
yuv_path = argv[3];
jpg_path = argv[4];
@@ -113,13 +170,32 @@ int main(int argc, char *argv[]) {
fseek(yuv_fd, 0, SEEK_END);
yuv_size = ftell(yuv_fd);
fseek(yuv_fd, 0, SEEK_SET);
image_buffer = malloc(yuv_size);
if (fread(image_buffer, yuv_size, 1, yuv_fd)!=1) {
/* Check that the file size matches 4:2:0 yuv. */
if (yuv_size !=
(size_t)luma_width*luma_height + 2*chroma_width*chroma_height) {
fprintf(stderr, "Unexpected input format!\n");
return 1;
}
yuv_buffer = malloc(yuv_size);
if (fread(yuv_buffer, yuv_size, 1, yuv_fd) != 1) {
fprintf(stderr, "Error reading yuv file\n");
};
fclose(yuv_fd);
frame_width = (luma_width + (16 - 1)) & ~(16 - 1);
frame_height = (luma_height + (16 - 1)) & ~(16 - 1);
image_buffer =
malloc(frame_width*frame_height + 2*(frame_width/2)*(frame_height/2));
extend_edge(image_buffer, frame_width, frame_height,
yuv_buffer, luma_width, luma_height, chroma_width, chroma_height);
free(yuv_buffer);
cinfo.err = jpeg_std_error(&jerr);
jpeg_create_compress(&cinfo);
@@ -131,18 +207,16 @@ int main(int argc, char *argv[]) {
jpeg_stdio_dest(&cinfo, jpg_fd);
cinfo.image_width = width;
cinfo.image_height = height;
cinfo.use_moz_defaults = TRUE;
cinfo.image_width = luma_width;
cinfo.image_height = luma_height;
cinfo.input_components = 3;
cinfo.in_color_space = JCS_YCbCr;
cinfo.use_moz_defaults = TRUE;
jpeg_set_defaults(&cinfo);
cinfo.raw_data_in = TRUE;
#if JPEG_LIB_VERSION >= 70
cinfo.do_fancy_downsampling = FALSE;
#endif
cinfo.comp_info[0].h_samp_factor = 2;
cinfo.comp_info[0].v_samp_factor = 2;
@@ -170,16 +244,19 @@ int main(int argc, char *argv[]) {
plane_pointer[0] = yrow_pointer;
plane_pointer[1] = cbrow_pointer;
plane_pointer[2] = crrow_pointer;
while (cinfo.next_scanline < cinfo.image_height) {
int scanline;
scanline = cinfo.next_scanline;
for (y = 0; y < 16; y++) {
yrow_pointer[y] = image_buffer + cinfo.image_width * (cinfo.next_scanline + y);
yrow_pointer[y] = &image_buffer[frame_width*(scanline + y)];
}
for (y = 0; y < 8; y++) {
cbrow_pointer[y] = image_buffer + width * height +
((width + 1) >> 1) * ((cinfo.next_scanline >> 1) + y);
crrow_pointer[y] = image_buffer + width * height +
((width + 1) >> 1) * ((height + 1) >> 1) +
((width + 1) >> 1) * ((cinfo.next_scanline >> 1) + y);
cbrow_pointer[y] = &image_buffer[frame_width*frame_height +
(frame_width/2)*((scanline/2) + y)];
crrow_pointer[y] = &image_buffer[frame_width*frame_height +
(frame_width/2)*(frame_height/2) + (frame_width/2)*((scanline/2) + y)];
}
jpeg_write_raw_data(&cinfo, plane_pointer, 16);
}