mirror of
https://github.com/webmproject/libwebp.git
synced 2025-07-06 19:14:31 +02:00
Compare commits
57 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
6a2209aa36 | ||
|
36cad6abe8 | ||
|
e2ecae62f0 | ||
|
243e68df60 | ||
|
eec5f5f121 | ||
|
0c1b98d28c | ||
|
69b0fc9492 | ||
|
857578a811 | ||
|
9129deb5b1 | ||
|
f17b95e992 | ||
|
9c56c8a12e | ||
|
a008902320 | ||
|
cc6de53b3b | ||
|
740d765aea | ||
|
403023f500 | ||
|
b65727b55d | ||
|
8de0debcec | ||
|
f8b7d94daa | ||
|
9102a7b63d | ||
|
e407b5d516 | ||
|
3e70e64153 | ||
|
be38f1af47 | ||
|
94dadcb1a1 | ||
|
40b3a618ec | ||
|
b7d209a448 | ||
|
bf0eb74829 | ||
|
3740f7d4c6 | ||
|
3ab0a377d2 | ||
|
2e4312b14f | ||
|
e6609ac6b9 | ||
|
5692eae1f3 | ||
|
6ecd5bf682 | ||
|
4206ac6bbf | ||
|
d40e885931 | ||
|
4aaf463449 | ||
|
4c82ff76c1 | ||
|
23d4fb3362 | ||
|
5af7719047 | ||
|
90d112466b | ||
|
ee78e7801d | ||
|
c9ac2041e9 | ||
|
f4497a1ef5 | ||
|
e2159fdff7 | ||
|
21abaa05e3 | ||
|
1a161e20a4 | ||
|
55b10de73f | ||
|
76d2192206 | ||
|
29a9db1f7c | ||
|
245c4a6737 | ||
|
40aa8b69b0 | ||
|
2ddcca5efe | ||
|
f40dd7c6de | ||
|
4610c9c55a | ||
|
fc3c1750dc | ||
|
c1a7955d59 | ||
|
57a7e73d27 | ||
|
6c83157524 |
1
AUTHORS
1
AUTHORS
@ -20,5 +20,6 @@ Contributors:
|
|||||||
- Scott Talbot (s at chikachow dot org)
|
- Scott Talbot (s at chikachow dot org)
|
||||||
- Slobodan Prijic (slobodan dot prijic at imgtec dot com)
|
- Slobodan Prijic (slobodan dot prijic at imgtec dot com)
|
||||||
- Somnath Banerjee (somnath dot banerjee at gmail dot com)
|
- Somnath Banerjee (somnath dot banerjee at gmail dot com)
|
||||||
|
- Timothy Gu (timothygu99 at gmail dot com)
|
||||||
- Urvang Joshi (urvang at google dot com)
|
- Urvang Joshi (urvang at google dot com)
|
||||||
- Vikas Arora (vikasa at google dot com)
|
- Vikas Arora (vikasa at google dot com)
|
||||||
|
@ -33,6 +33,7 @@ LOCAL_SRC_FILES := \
|
|||||||
src/dec/vp8l.c \
|
src/dec/vp8l.c \
|
||||||
src/dec/webp.c \
|
src/dec/webp.c \
|
||||||
src/dsp/alpha_processing.c \
|
src/dsp/alpha_processing.c \
|
||||||
|
src/dsp/alpha_processing_sse2.c \
|
||||||
src/dsp/cpu.c \
|
src/dsp/cpu.c \
|
||||||
src/dsp/dec.c \
|
src/dsp/dec.c \
|
||||||
src/dsp/dec_clip_tables.c \
|
src/dsp/dec_clip_tables.c \
|
||||||
|
59
ChangeLog
59
ChangeLog
@ -1,3 +1,60 @@
|
|||||||
|
36cad6a bit_reader.h: cosmetics: fix a typo
|
||||||
|
e2ecae6 enc_mips32: workaround gcc-4.9 bug
|
||||||
|
243e68d update ChangeLog (tag: v0.4.2-rc2)
|
||||||
|
eec5f5f enc/vp8enci.h: update version number
|
||||||
|
0c1b98d update NEWS
|
||||||
|
69b0fc9 update AUTHORS
|
||||||
|
857578a bump version to 0.4.2
|
||||||
|
9129deb restore encode API compatibility
|
||||||
|
f17b95e AssignSegments: quiet -Warray-bounds warning
|
||||||
|
9c56c8a enc_neon: initialize vectors w/vdup_n_u32
|
||||||
|
a008902 iosbuild: cleanup
|
||||||
|
cc6de53 iosbuild: output autoconf req. on failure
|
||||||
|
740d765 iosbuild: make iOS 6 the minimum requirement
|
||||||
|
403023f iobuild.sh: only install .h files in Headers
|
||||||
|
b65727b Premultiply with alpha during U/V downsampling
|
||||||
|
8de0deb gif2webp: Background color correction
|
||||||
|
f8b7d94 Amend the lossless spec according to issue #205, #206 and #224
|
||||||
|
9102a7b Add a WebPExtractAlpha function to dsp
|
||||||
|
e407b5d webpmux: simplify InitializeConfig()
|
||||||
|
3e70e64 webpmux: fix indent
|
||||||
|
be38f1a webpmux: fix exit status on numeric value parse error
|
||||||
|
94dadcb webpmux: fix loop_count range check
|
||||||
|
40b3a61 examples: warn on invalid numeric parameters
|
||||||
|
b7d209a gif2webp: Handle frames with missing graphic control extension
|
||||||
|
bf0eb74 configure: simplify libpng-config invocation
|
||||||
|
3740f7d Rectify bug in lossless incremental decoding.
|
||||||
|
3ab0a37 make VP8LSetBitPos() set br->eos_ flag
|
||||||
|
2e4312b Lossless decoding: fix eos_ flag condition
|
||||||
|
e6609ac fix erroneous dec->status_ setting
|
||||||
|
5692eae add a fallback to ALPHA_NO_COMPRESSION
|
||||||
|
6ecd5bf ExUtilReadFromStdin: (windows) open stdin in bin mode
|
||||||
|
4206ac6 webpmux: (windows) open stdout in binary mode
|
||||||
|
d40e885 cwebp: (windows) open stdout in binary mode
|
||||||
|
4aaf463 example_util: add ExUtilSetBinaryMode
|
||||||
|
4c82ff7 webpmux man page: Clarify some title, descriptions and examples
|
||||||
|
23d4fb3 dsp/lossless: workaround gcc-4.9 bug on arm
|
||||||
|
5af7719 dsp.h: collect gcc/clang version test macros
|
||||||
|
90d1124 enc_neon: enable QuantizeBlock for aarch64
|
||||||
|
ee78e78 SmartRGBYUV: fix odd-width problem with pixel replication
|
||||||
|
c9ac204 fix some MSVC64 warning about float conversion
|
||||||
|
f4497a1 cpu: check for _MSC_VER before using msvc inline asm
|
||||||
|
e2159fd faster RGB->YUV conversion function (~7% speedup)
|
||||||
|
21abaa0 Add smart RGB->YUV conversion option -pre 4
|
||||||
|
1a161e2 configure: add work around for gcc-4.9 aarch64 bug
|
||||||
|
55b10de MIPS: mips32r2: added optimization for BSwap32
|
||||||
|
76d2192 Update PATENTS to reflect s/VP8/WebM/g
|
||||||
|
29a9db1 MIPS: detect mips32r6 and disable mips32r1 code
|
||||||
|
245c4a6 Correctly use the AC_CANONICAL_* macros
|
||||||
|
40aa8b6 cosmetics
|
||||||
|
2ddcca5 cosmetics: remove some extraneous 'extern's
|
||||||
|
f40dd7c vp8enci.h: cosmetics: fix '*' placement
|
||||||
|
4610c9c bit_writer: cosmetics: rename kFlush() -> Flush()
|
||||||
|
fc3c175 dsp: detect mips64 & disable mips32 code
|
||||||
|
c1a7955 cwebp.1: restore quality description
|
||||||
|
57a7e73 correct alpha_dithering_strength ABI check
|
||||||
|
6c83157 correct WebPMemoryWriterClear ABI check
|
||||||
|
8af2771 update ChangeLog (tag: v0.4.1, origin/0.4.1, 0.4.1)
|
||||||
f59c0b4 iosbuild.sh: specify optimization flags
|
f59c0b4 iosbuild.sh: specify optimization flags
|
||||||
8d34ea3 update ChangeLog (tag: v0.4.1-rc1)
|
8d34ea3 update ChangeLog (tag: v0.4.1-rc1)
|
||||||
dbc3da6 makefile.unix: add vwebp.1 to the dist target
|
dbc3da6 makefile.unix: add vwebp.1 to the dist target
|
||||||
@ -17,7 +74,7 @@ c2fc52e restore encode API compatibility
|
|||||||
793368e restore decode API compatibility
|
793368e restore decode API compatibility
|
||||||
b8984f3 gif2webp: fix compile with giflib 5.1.0
|
b8984f3 gif2webp: fix compile with giflib 5.1.0
|
||||||
222f9b1 gif2webp: simplify giflib version checking
|
222f9b1 gif2webp: simplify giflib version checking
|
||||||
d2cc61b Extend MakeARGB32() to accept Alpha channel.
|
d2cc61b Extend MakeARGB32() to accept Alpha channel. (master)
|
||||||
4595b62 Merge "use explicit size of kErrorMessages[] arrays"
|
4595b62 Merge "use explicit size of kErrorMessages[] arrays"
|
||||||
157de01 Merge "Actuate memory stats for PRINT_MEMORY_INFO"
|
157de01 Merge "Actuate memory stats for PRINT_MEMORY_INFO"
|
||||||
fbda2f4 JPEG decoder: delay conversion to YUV to WebPEncode() call
|
fbda2f4 JPEG decoder: delay conversion to YUV to WebPEncode() call
|
||||||
|
@ -172,6 +172,7 @@ DEMUX_OBJS = \
|
|||||||
|
|
||||||
DSP_DEC_OBJS = \
|
DSP_DEC_OBJS = \
|
||||||
$(DIROBJ)\dsp\alpha_processing.obj \
|
$(DIROBJ)\dsp\alpha_processing.obj \
|
||||||
|
$(DIROBJ)\dsp\alpha_processing_sse2.obj \
|
||||||
$(DIROBJ)\dsp\cpu.obj \
|
$(DIROBJ)\dsp\cpu.obj \
|
||||||
$(DIROBJ)\dsp\dec.obj \
|
$(DIROBJ)\dsp\dec.obj \
|
||||||
$(DIROBJ)\dsp\dec_clip_tables.obj \
|
$(DIROBJ)\dsp\dec_clip_tables.obj \
|
||||||
|
8
NEWS
8
NEWS
@ -1,3 +1,11 @@
|
|||||||
|
- 10/13/14: version 0.4.2
|
||||||
|
This is a binary compatible release.
|
||||||
|
* Android / gcc build fixes
|
||||||
|
* (Windows) fix reading from stdin and writing to stdout
|
||||||
|
* gif2webp: miscellaneous fixes
|
||||||
|
* fix 'alpha-leak' with lossy compression (issue #220)
|
||||||
|
* the lossless bitstream spec has been amended to reflect the current code
|
||||||
|
|
||||||
- 7/24/14: version 0.4.1
|
- 7/24/14: version 0.4.1
|
||||||
This is a binary compatible release.
|
This is a binary compatible release.
|
||||||
* AArch64 (arm64) & MIPS support/optimizations
|
* AArch64 (arm64) & MIPS support/optimizations
|
||||||
|
39
PATENTS
39
PATENTS
@ -1,22 +1,23 @@
|
|||||||
Additional IP Rights Grant (Patents)
|
Additional IP Rights Grant (Patents)
|
||||||
|
------------------------------------
|
||||||
|
|
||||||
"This implementation" means the copyrightable works distributed by
|
"These implementations" means the copyrightable works that implement the WebM
|
||||||
Google as part of the WebM Project.
|
codecs distributed by Google as part of the WebM Project.
|
||||||
|
|
||||||
Google hereby grants to you a perpetual, worldwide, non-exclusive,
|
Google hereby grants to you a perpetual, worldwide, non-exclusive, no-charge,
|
||||||
no-charge, royalty-free, irrevocable (except as stated in this section)
|
royalty-free, irrevocable (except as stated in this section) patent license to
|
||||||
patent license to make, have made, use, offer to sell, sell, import,
|
make, have made, use, offer to sell, sell, import, transfer, and otherwise
|
||||||
transfer, and otherwise run, modify and propagate the contents of this
|
run, modify and propagate the contents of these implementations of WebM, where
|
||||||
implementation of VP8, where such license applies only to those patent
|
such license applies only to those patent claims, both currently owned by
|
||||||
claims, both currently owned by Google and acquired in the future,
|
Google and acquired in the future, licensable by Google that are necessarily
|
||||||
licensable by Google that are necessarily infringed by this
|
infringed by these implementations of WebM. This grant does not include claims
|
||||||
implementation of VP8. This grant does not include claims that would be
|
that would be infringed only as a consequence of further modification of these
|
||||||
infringed only as a consequence of further modification of this
|
implementations. If you or your agent or exclusive licensee institute or order
|
||||||
implementation. If you or your agent or exclusive licensee institute or
|
or agree to the institution of patent litigation or any other patent
|
||||||
order or agree to the institution of patent litigation against any
|
enforcement activity against any entity (including a cross-claim or
|
||||||
entity (including a cross-claim or counterclaim in a lawsuit) alleging
|
counterclaim in a lawsuit) alleging that any of these implementations of WebM
|
||||||
that this implementation of VP8 or any code incorporated within this
|
or any code incorporated within any of these implementations of WebM
|
||||||
implementation of VP8 constitutes direct or contributory patent
|
constitutes direct or contributory patent infringement, or inducement of
|
||||||
infringement, or inducement of patent infringement, then any patent
|
patent infringement, then any patent rights granted to you under this License
|
||||||
rights granted to you under this License for this implementation of VP8
|
for these implementations of WebM shall terminate as of the date such
|
||||||
shall terminate as of the date such litigation is filed.
|
litigation is filed.
|
||||||
|
2
README
2
README
@ -4,7 +4,7 @@
|
|||||||
\__\__/\____/\_____/__/ ____ ___
|
\__\__/\____/\_____/__/ ____ ___
|
||||||
/ _/ / \ \ / _ \/ _/
|
/ _/ / \ \ / _ \/ _/
|
||||||
/ \_/ / / \ \ __/ \__
|
/ \_/ / / \ \ __/ \__
|
||||||
\____/____/\_____/_____/____/v0.4.1
|
\____/____/\_____/_____/____/v0.4.2
|
||||||
|
|
||||||
Description:
|
Description:
|
||||||
============
|
============
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
__ __ ____ ____ ____ __ __ _ __ __
|
__ __ ____ ____ ____ __ __ _ __ __
|
||||||
/ \\/ \/ _ \/ _ \/ _ \/ \ \/ \___/_ / _\
|
/ \\/ \/ _ \/ _ \/ _ \/ \ \/ \___/_ / _\
|
||||||
\ / __/ _ \ __/ / / (_/ /__
|
\ / __/ _ \ __/ / / (_/ /__
|
||||||
\__\__/\_____/_____/__/ \__//_/\_____/__/___/v0.2.1
|
\__\__/\_____/_____/__/ \__//_/\_____/__/___/v0.2.2
|
||||||
|
|
||||||
|
|
||||||
Description:
|
Description:
|
||||||
|
34
configure.ac
34
configure.ac
@ -1,7 +1,7 @@
|
|||||||
AC_INIT([libwebp], [0.4.1],
|
AC_INIT([libwebp], [0.4.2],
|
||||||
[http://code.google.com/p/webp/issues],,
|
[http://code.google.com/p/webp/issues],,
|
||||||
[http://developers.google.com/speed/webp])
|
[http://developers.google.com/speed/webp])
|
||||||
AC_CANONICAL_TARGET
|
AC_CANONICAL_HOST
|
||||||
AC_PREREQ([2.60])
|
AC_PREREQ([2.60])
|
||||||
AM_INIT_AUTOMAKE([-Wall foreign subdir-objects])
|
AM_INIT_AUTOMAKE([-Wall foreign subdir-objects])
|
||||||
|
|
||||||
@ -62,6 +62,19 @@ TEST_AND_ADD_CFLAGS([AM_CFLAGS], [-Wshadow])
|
|||||||
TEST_AND_ADD_CFLAGS([AM_CFLAGS], [-Wunused-but-set-variable])
|
TEST_AND_ADD_CFLAGS([AM_CFLAGS], [-Wunused-but-set-variable])
|
||||||
TEST_AND_ADD_CFLAGS([AM_CFLAGS], [-Wunused])
|
TEST_AND_ADD_CFLAGS([AM_CFLAGS], [-Wunused])
|
||||||
TEST_AND_ADD_CFLAGS([AM_CFLAGS], [-Wvla])
|
TEST_AND_ADD_CFLAGS([AM_CFLAGS], [-Wvla])
|
||||||
|
# https://gcc.gnu.org/bugzilla/show_bug.cgi?id=62040
|
||||||
|
# https://gcc.gnu.org/bugzilla/show_bug.cgi?id=61622
|
||||||
|
AS_IF([test "$GCC" = "yes" ], [
|
||||||
|
gcc_version=`$CC -dumpversion`
|
||||||
|
gcc_wht_bug=""
|
||||||
|
case "$host_cpu" in
|
||||||
|
aarch64|arm64)
|
||||||
|
case "$gcc_version" in
|
||||||
|
4.9|4.9.0|4.9.1) gcc_wht_bug=yes ;;
|
||||||
|
esac
|
||||||
|
esac
|
||||||
|
AS_IF([test "$gcc_wht_bug" = "yes"], [
|
||||||
|
TEST_AND_ADD_CFLAGS([AM_CFLAGS], [-frename-registers])])])
|
||||||
AC_SUBST([AM_CFLAGS])
|
AC_SUBST([AM_CFLAGS])
|
||||||
|
|
||||||
dnl === Check for machine specific flags
|
dnl === Check for machine specific flags
|
||||||
@ -283,15 +296,12 @@ AC_ARG_ENABLE([png], AS_HELP_STRING([--disable-png],
|
|||||||
@<:@default=auto@:>@]))
|
@<:@default=auto@:>@]))
|
||||||
AS_IF([test "x$enable_png" != "xno"], [
|
AS_IF([test "x$enable_png" != "xno"], [
|
||||||
CLEAR_LIBVARS([PNG])
|
CLEAR_LIBVARS([PNG])
|
||||||
AC_PATH_PROGS(LIBPNG_CONFIG,
|
AC_PATH_PROGS([LIBPNG_CONFIG],
|
||||||
[libpng-config libpng15-config libpng14-config libpng12-config])
|
[libpng-config libpng16-config libpng15-config libpng14-config \
|
||||||
|
libpng12-config])
|
||||||
if test -n "$LIBPNG_CONFIG"; then
|
if test -n "$LIBPNG_CONFIG"; then
|
||||||
PNG_INCLUDES=`$LIBPNG_CONFIG --cflags`
|
PNG_INCLUDES=`$LIBPNG_CONFIG --cflags`
|
||||||
PNG_PREFIX=`$LIBPNG_CONFIG --prefix`
|
PNG_LIBS="`$LIBPNG_CONFIG --ldflags`"
|
||||||
if test "${PNG_PREFIX}/lib" != "/usr/lib" ; then
|
|
||||||
PNG_LIBS="-L${PNG_PREFIX}/lib"
|
|
||||||
fi
|
|
||||||
PNG_LIBS="$PNG_LIBS `$LIBPNG_CONFIG --libs`"
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
WITHLIB_OPTION([png], [PNG])
|
WITHLIB_OPTION([png], [PNG])
|
||||||
@ -409,8 +419,9 @@ AC_ARG_ENABLE([wic],
|
|||||||
@<:@default=auto@:>@]),,
|
@<:@default=auto@:>@]),,
|
||||||
[enable_wic=yes])
|
[enable_wic=yes])
|
||||||
|
|
||||||
if test \( "$target_os" = "mingw32" -o "$target_os" = "mingw64" \) \
|
case $host_os in
|
||||||
-a "$enable_wic" = "yes"; then
|
mingw*)
|
||||||
|
if test "$enable_wic" = "yes"; then
|
||||||
AC_CHECK_HEADERS([wincodec.h shlwapi.h windows.h])
|
AC_CHECK_HEADERS([wincodec.h shlwapi.h windows.h])
|
||||||
if test "$ac_cv_header_wincodec_h" = "yes"; then
|
if test "$ac_cv_header_wincodec_h" = "yes"; then
|
||||||
AC_MSG_CHECKING(for Windows Imaging Component support)
|
AC_MSG_CHECKING(for Windows Imaging Component support)
|
||||||
@ -450,6 +461,7 @@ if test \( "$target_os" = "mingw32" -o "$target_os" = "mingw64" \) \
|
|||||||
AC_MSG_RESULT(${wic_support-no})
|
AC_MSG_RESULT(${wic_support-no})
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
esac
|
||||||
|
|
||||||
dnl === If --enable-aligned is defined, define WEBP_FORCE_ALIGNED
|
dnl === If --enable-aligned is defined, define WEBP_FORCE_ALIGNED
|
||||||
|
|
||||||
|
@ -14,6 +14,7 @@ Specification for WebP Lossless Bitstream
|
|||||||
|
|
||||||
_Jyrki Alakuijala, Ph.D., Google, Inc., 2012-06-19_
|
_Jyrki Alakuijala, Ph.D., Google, Inc., 2012-06-19_
|
||||||
|
|
||||||
|
Paragraphs marked as \[AMENDED\] were amended on 2014-09-16.
|
||||||
|
|
||||||
Abstract
|
Abstract
|
||||||
--------
|
--------
|
||||||
@ -172,8 +173,8 @@ It should be set to 0 when all alpha values are 255 in the picture, and
|
|||||||
int alpha_is_used = ReadBits(1);
|
int alpha_is_used = ReadBits(1);
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
The version_number is a 3 bit code that must be discarded by the decoder
|
The version_number is a 3 bit code that must be set to 0. Any other value
|
||||||
at this time. Complying encoders write a 3-bit value 0.
|
should be treated as an error. \[AMENDED\]
|
||||||
|
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
int version_number = ReadBits(3);
|
int version_number = ReadBits(3);
|
||||||
@ -330,7 +331,7 @@ uint32 Select(uint32 L, uint32 T, uint32 TL) {
|
|||||||
abs(pGreen - GREEN(T)) + abs(pBlue - BLUE(T));
|
abs(pGreen - GREEN(T)) + abs(pBlue - BLUE(T));
|
||||||
|
|
||||||
// Return either left or top, the one closer to the prediction.
|
// Return either left or top, the one closer to the prediction.
|
||||||
if (pL <= pT) {
|
if (pL < pT) { // \[AMENDED\]
|
||||||
return L;
|
return L;
|
||||||
} else {
|
} else {
|
||||||
return T;
|
return T;
|
||||||
@ -542,6 +543,9 @@ color.
|
|||||||
argb = color_table[GREEN(argb)];
|
argb = color_table[GREEN(argb)];
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
If the index is equal or larger than color_table_size, the argb color value
|
||||||
|
should be set to 0x00000000 (transparent black). \[AMENDED\]
|
||||||
|
|
||||||
When the color table is small (equal to or less than 16 colors), several
|
When the color table is small (equal to or less than 16 colors), several
|
||||||
pixels are bundled into a single pixel. The pixel bundling packs several
|
pixels are bundled into a single pixel. The pixel bundling packs several
|
||||||
(2, 4, or 8) pixels into a single pixel, reducing the image width
|
(2, 4, or 8) pixels into a single pixel, reducing the image width
|
||||||
|
@ -22,6 +22,7 @@
|
|||||||
|
|
||||||
#include "webp/encode.h"
|
#include "webp/encode.h"
|
||||||
|
|
||||||
|
#include "./example_util.h"
|
||||||
#include "./metadata.h"
|
#include "./metadata.h"
|
||||||
#include "./stopwatch.h"
|
#include "./stopwatch.h"
|
||||||
|
|
||||||
@ -709,6 +710,7 @@ int main(int argc, const char *argv[]) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (c = 1; c < argc; ++c) {
|
for (c = 1; c < argc; ++c) {
|
||||||
|
int parse_error = 0;
|
||||||
if (!strcmp(argv[c], "-h") || !strcmp(argv[c], "-help")) {
|
if (!strcmp(argv[c], "-h") || !strcmp(argv[c], "-help")) {
|
||||||
HelpShort();
|
HelpShort();
|
||||||
return 0;
|
return 0;
|
||||||
@ -732,30 +734,31 @@ int main(int argc, const char *argv[]) {
|
|||||||
} else if (!strcmp(argv[c], "-short")) {
|
} else if (!strcmp(argv[c], "-short")) {
|
||||||
++short_output;
|
++short_output;
|
||||||
} else if (!strcmp(argv[c], "-s") && c < argc - 2) {
|
} else if (!strcmp(argv[c], "-s") && c < argc - 2) {
|
||||||
picture.width = strtol(argv[++c], NULL, 0);
|
picture.width = ExUtilGetInt(argv[++c], 0, &parse_error);
|
||||||
picture.height = strtol(argv[++c], NULL, 0);
|
picture.height = ExUtilGetInt(argv[++c], 0, &parse_error);
|
||||||
} else if (!strcmp(argv[c], "-m") && c < argc - 1) {
|
} else if (!strcmp(argv[c], "-m") && c < argc - 1) {
|
||||||
config.method = strtol(argv[++c], NULL, 0);
|
config.method = ExUtilGetInt(argv[++c], 0, &parse_error);
|
||||||
#if WEBP_ENCODER_ABI_VERSION > 0x0202
|
#if WEBP_ENCODER_ABI_VERSION > 0x0202
|
||||||
use_lossless_preset = 0; // disable -z option
|
use_lossless_preset = 0; // disable -z option
|
||||||
#endif
|
#endif
|
||||||
} else if (!strcmp(argv[c], "-q") && c < argc - 1) {
|
} else if (!strcmp(argv[c], "-q") && c < argc - 1) {
|
||||||
config.quality = (float)strtod(argv[++c], NULL);
|
config.quality = ExUtilGetFloat(argv[++c], &parse_error);
|
||||||
#if WEBP_ENCODER_ABI_VERSION > 0x0202
|
#if WEBP_ENCODER_ABI_VERSION > 0x0202
|
||||||
use_lossless_preset = 0; // disable -z option
|
use_lossless_preset = 0; // disable -z option
|
||||||
} else if (!strcmp(argv[c], "-z") && c < argc - 1) {
|
} else if (!strcmp(argv[c], "-z") && c < argc - 1) {
|
||||||
lossless_preset = strtol(argv[++c], NULL, 0);
|
lossless_preset = ExUtilGetInt(argv[++c], 0, &parse_error);
|
||||||
if (use_lossless_preset != 0) use_lossless_preset = 1;
|
if (use_lossless_preset != 0) use_lossless_preset = 1;
|
||||||
#endif
|
#endif
|
||||||
} else if (!strcmp(argv[c], "-alpha_q") && c < argc - 1) {
|
} else if (!strcmp(argv[c], "-alpha_q") && c < argc - 1) {
|
||||||
config.alpha_quality = strtol(argv[++c], NULL, 0);
|
config.alpha_quality = ExUtilGetInt(argv[++c], 0, &parse_error);
|
||||||
} else if (!strcmp(argv[c], "-alpha_method") && c < argc - 1) {
|
} else if (!strcmp(argv[c], "-alpha_method") && c < argc - 1) {
|
||||||
config.alpha_compression = strtol(argv[++c], NULL, 0);
|
config.alpha_compression = ExUtilGetInt(argv[++c], 0, &parse_error);
|
||||||
} else if (!strcmp(argv[c], "-alpha_cleanup")) {
|
} else if (!strcmp(argv[c], "-alpha_cleanup")) {
|
||||||
keep_alpha = keep_alpha ? 2 : 0;
|
keep_alpha = keep_alpha ? 2 : 0;
|
||||||
} else if (!strcmp(argv[c], "-blend_alpha") && c < argc - 1) {
|
} else if (!strcmp(argv[c], "-blend_alpha") && c < argc - 1) {
|
||||||
blend_alpha = 1;
|
blend_alpha = 1;
|
||||||
background_color = strtol(argv[++c], NULL, 16); // <- parses '0x' prefix
|
// background color is given in hex with an optional '0x' prefix
|
||||||
|
background_color = ExUtilGetInt(argv[++c], 16, &parse_error);
|
||||||
background_color = background_color & 0x00ffffffu;
|
background_color = background_color & 0x00ffffffu;
|
||||||
} else if (!strcmp(argv[c], "-alpha_filter") && c < argc - 1) {
|
} else if (!strcmp(argv[c], "-alpha_filter") && c < argc - 1) {
|
||||||
++c;
|
++c;
|
||||||
@ -786,13 +789,13 @@ int main(int argc, const char *argv[]) {
|
|||||||
goto Error;
|
goto Error;
|
||||||
}
|
}
|
||||||
} else if (!strcmp(argv[c], "-size") && c < argc - 1) {
|
} else if (!strcmp(argv[c], "-size") && c < argc - 1) {
|
||||||
config.target_size = strtol(argv[++c], NULL, 0);
|
config.target_size = ExUtilGetInt(argv[++c], 0, &parse_error);
|
||||||
} else if (!strcmp(argv[c], "-psnr") && c < argc - 1) {
|
} else if (!strcmp(argv[c], "-psnr") && c < argc - 1) {
|
||||||
config.target_PSNR = (float)strtod(argv[++c], NULL);
|
config.target_PSNR = ExUtilGetFloat(argv[++c], &parse_error);
|
||||||
} else if (!strcmp(argv[c], "-sns") && c < argc - 1) {
|
} else if (!strcmp(argv[c], "-sns") && c < argc - 1) {
|
||||||
config.sns_strength = strtol(argv[++c], NULL, 0);
|
config.sns_strength = ExUtilGetInt(argv[++c], 0, &parse_error);
|
||||||
} else if (!strcmp(argv[c], "-f") && c < argc - 1) {
|
} else if (!strcmp(argv[c], "-f") && c < argc - 1) {
|
||||||
config.filter_strength = strtol(argv[++c], NULL, 0);
|
config.filter_strength = ExUtilGetInt(argv[++c], 0, &parse_error);
|
||||||
} else if (!strcmp(argv[c], "-af")) {
|
} else if (!strcmp(argv[c], "-af")) {
|
||||||
config.autofilter = 1;
|
config.autofilter = 1;
|
||||||
} else if (!strcmp(argv[c], "-jpeg_like")) {
|
} else if (!strcmp(argv[c], "-jpeg_like")) {
|
||||||
@ -806,26 +809,26 @@ int main(int argc, const char *argv[]) {
|
|||||||
} else if (!strcmp(argv[c], "-nostrong")) {
|
} else if (!strcmp(argv[c], "-nostrong")) {
|
||||||
config.filter_type = 0;
|
config.filter_type = 0;
|
||||||
} else if (!strcmp(argv[c], "-sharpness") && c < argc - 1) {
|
} else if (!strcmp(argv[c], "-sharpness") && c < argc - 1) {
|
||||||
config.filter_sharpness = strtol(argv[++c], NULL, 0);
|
config.filter_sharpness = ExUtilGetInt(argv[++c], 0, &parse_error);
|
||||||
} else if (!strcmp(argv[c], "-pass") && c < argc - 1) {
|
} else if (!strcmp(argv[c], "-pass") && c < argc - 1) {
|
||||||
config.pass = strtol(argv[++c], NULL, 0);
|
config.pass = ExUtilGetInt(argv[++c], 0, &parse_error);
|
||||||
} else if (!strcmp(argv[c], "-pre") && c < argc - 1) {
|
} else if (!strcmp(argv[c], "-pre") && c < argc - 1) {
|
||||||
config.preprocessing = strtol(argv[++c], NULL, 0);
|
config.preprocessing = ExUtilGetInt(argv[++c], 0, &parse_error);
|
||||||
} else if (!strcmp(argv[c], "-segments") && c < argc - 1) {
|
} else if (!strcmp(argv[c], "-segments") && c < argc - 1) {
|
||||||
config.segments = strtol(argv[++c], NULL, 0);
|
config.segments = ExUtilGetInt(argv[++c], 0, &parse_error);
|
||||||
} else if (!strcmp(argv[c], "-partition_limit") && c < argc - 1) {
|
} else if (!strcmp(argv[c], "-partition_limit") && c < argc - 1) {
|
||||||
config.partition_limit = strtol(argv[++c], NULL, 0);
|
config.partition_limit = ExUtilGetInt(argv[++c], 0, &parse_error);
|
||||||
} else if (!strcmp(argv[c], "-map") && c < argc - 1) {
|
} else if (!strcmp(argv[c], "-map") && c < argc - 1) {
|
||||||
picture.extra_info_type = strtol(argv[++c], NULL, 0);
|
picture.extra_info_type = ExUtilGetInt(argv[++c], 0, &parse_error);
|
||||||
} else if (!strcmp(argv[c], "-crop") && c < argc - 4) {
|
} else if (!strcmp(argv[c], "-crop") && c < argc - 4) {
|
||||||
crop = 1;
|
crop = 1;
|
||||||
crop_x = strtol(argv[++c], NULL, 0);
|
crop_x = ExUtilGetInt(argv[++c], 0, &parse_error);
|
||||||
crop_y = strtol(argv[++c], NULL, 0);
|
crop_y = ExUtilGetInt(argv[++c], 0, &parse_error);
|
||||||
crop_w = strtol(argv[++c], NULL, 0);
|
crop_w = ExUtilGetInt(argv[++c], 0, &parse_error);
|
||||||
crop_h = strtol(argv[++c], NULL, 0);
|
crop_h = ExUtilGetInt(argv[++c], 0, &parse_error);
|
||||||
} else if (!strcmp(argv[c], "-resize") && c < argc - 2) {
|
} else if (!strcmp(argv[c], "-resize") && c < argc - 2) {
|
||||||
resize_w = strtol(argv[++c], NULL, 0);
|
resize_w = ExUtilGetInt(argv[++c], 0, &parse_error);
|
||||||
resize_h = strtol(argv[++c], NULL, 0);
|
resize_h = ExUtilGetInt(argv[++c], 0, &parse_error);
|
||||||
#ifndef WEBP_DLL
|
#ifndef WEBP_DLL
|
||||||
} else if (!strcmp(argv[c], "-noasm")) {
|
} else if (!strcmp(argv[c], "-noasm")) {
|
||||||
VP8GetCPUInfo = NULL;
|
VP8GetCPUInfo = NULL;
|
||||||
@ -920,6 +923,11 @@ int main(int argc, const char *argv[]) {
|
|||||||
} else {
|
} else {
|
||||||
in_file = argv[c];
|
in_file = argv[c];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (parse_error) {
|
||||||
|
HelpLong();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (in_file == NULL) {
|
if (in_file == NULL) {
|
||||||
fprintf(stderr, "No input file specified!\n");
|
fprintf(stderr, "No input file specified!\n");
|
||||||
@ -981,7 +989,7 @@ int main(int argc, const char *argv[]) {
|
|||||||
// Open the output
|
// Open the output
|
||||||
if (out_file != NULL) {
|
if (out_file != NULL) {
|
||||||
const int use_stdout = !strcmp(out_file, "-");
|
const int use_stdout = !strcmp(out_file, "-");
|
||||||
out = use_stdout ? stdout : fopen(out_file, "wb");
|
out = use_stdout ? ExUtilSetBinaryMode(stdout) : fopen(out_file, "wb");
|
||||||
if (out == NULL) {
|
if (out == NULL) {
|
||||||
fprintf(stderr, "Error! Cannot open output file '%s'\n", out_file);
|
fprintf(stderr, "Error! Cannot open output file '%s'\n", out_file);
|
||||||
goto Error;
|
goto Error;
|
||||||
@ -1126,7 +1134,7 @@ int main(int argc, const char *argv[]) {
|
|||||||
return_value = 0;
|
return_value = 0;
|
||||||
|
|
||||||
Error:
|
Error:
|
||||||
#if WEBP_ENCODER_ABI_VERSION > 0x0202
|
#if WEBP_ENCODER_ABI_VERSION > 0x0203
|
||||||
WebPMemoryWriterClear(&memory_writer);
|
WebPMemoryWriterClear(&memory_writer);
|
||||||
#else
|
#else
|
||||||
free(memory_writer.mem);
|
free(memory_writer.mem);
|
||||||
|
@ -38,11 +38,6 @@
|
|||||||
#include <wincodec.h>
|
#include <wincodec.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(_WIN32)
|
|
||||||
#include <fcntl.h> // for _O_BINARY
|
|
||||||
#include <io.h> // for _setmode()
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "webp/decode.h"
|
#include "webp/decode.h"
|
||||||
#include "./example_util.h"
|
#include "./example_util.h"
|
||||||
#include "./stopwatch.h"
|
#include "./stopwatch.h"
|
||||||
@ -482,15 +477,8 @@ static int SaveOutput(const WebPDecBuffer* const buffer,
|
|||||||
needs_open_file = (format != PNG);
|
needs_open_file = (format != PNG);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(_WIN32)
|
|
||||||
if (use_stdout && _setmode(_fileno(stdout), _O_BINARY) == -1) {
|
|
||||||
fprintf(stderr, "Failed to reopen stdout in O_BINARY mode.\n");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (needs_open_file) {
|
if (needs_open_file) {
|
||||||
fout = use_stdout ? stdout : fopen(out_file, "wb");
|
fout = use_stdout ? ExUtilSetBinaryMode(stdout) : fopen(out_file, "wb");
|
||||||
if (fout == NULL) {
|
if (fout == NULL) {
|
||||||
fprintf(stderr, "Error opening output file %s\n", out_file);
|
fprintf(stderr, "Error opening output file %s\n", out_file);
|
||||||
return 0;
|
return 0;
|
||||||
@ -557,7 +545,7 @@ static void Help(void) {
|
|||||||
" -nofilter .... disable in-loop filtering\n"
|
" -nofilter .... disable in-loop filtering\n"
|
||||||
" -nodither .... disable dithering\n"
|
" -nodither .... disable dithering\n"
|
||||||
" -dither <d> .. dithering strength (in 0..100)\n"
|
" -dither <d> .. dithering strength (in 0..100)\n"
|
||||||
#if WEBP_DECODER_ABI_VERSION > 0x0203
|
#if WEBP_DECODER_ABI_VERSION > 0x0204
|
||||||
" -alpha_dither use alpha-plane dithering if needed\n"
|
" -alpha_dither use alpha-plane dithering if needed\n"
|
||||||
#endif
|
#endif
|
||||||
" -mt .......... use multi-threading\n"
|
" -mt .......... use multi-threading\n"
|
||||||
@ -598,6 +586,7 @@ int main(int argc, const char *argv[]) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (c = 1; c < argc; ++c) {
|
for (c = 1; c < argc; ++c) {
|
||||||
|
int parse_error = 0;
|
||||||
if (!strcmp(argv[c], "-h") || !strcmp(argv[c], "-help")) {
|
if (!strcmp(argv[c], "-h") || !strcmp(argv[c], "-help")) {
|
||||||
Help();
|
Help();
|
||||||
return 0;
|
return 0;
|
||||||
@ -628,24 +617,25 @@ int main(int argc, const char *argv[]) {
|
|||||||
format = YUV;
|
format = YUV;
|
||||||
} else if (!strcmp(argv[c], "-mt")) {
|
} else if (!strcmp(argv[c], "-mt")) {
|
||||||
config.options.use_threads = 1;
|
config.options.use_threads = 1;
|
||||||
#if WEBP_DECODER_ABI_VERSION > 0x0203
|
#if WEBP_DECODER_ABI_VERSION > 0x0204
|
||||||
} else if (!strcmp(argv[c], "-alpha_dither")) {
|
} else if (!strcmp(argv[c], "-alpha_dither")) {
|
||||||
config.options.alpha_dithering_strength = 100;
|
config.options.alpha_dithering_strength = 100;
|
||||||
#endif
|
#endif
|
||||||
} else if (!strcmp(argv[c], "-nodither")) {
|
} else if (!strcmp(argv[c], "-nodither")) {
|
||||||
config.options.dithering_strength = 0;
|
config.options.dithering_strength = 0;
|
||||||
} else if (!strcmp(argv[c], "-dither") && c < argc - 1) {
|
} else if (!strcmp(argv[c], "-dither") && c < argc - 1) {
|
||||||
config.options.dithering_strength = strtol(argv[++c], NULL, 0);
|
config.options.dithering_strength =
|
||||||
|
ExUtilGetInt(argv[++c], 0, &parse_error);
|
||||||
} else if (!strcmp(argv[c], "-crop") && c < argc - 4) {
|
} else if (!strcmp(argv[c], "-crop") && c < argc - 4) {
|
||||||
config.options.use_cropping = 1;
|
config.options.use_cropping = 1;
|
||||||
config.options.crop_left = strtol(argv[++c], NULL, 0);
|
config.options.crop_left = ExUtilGetInt(argv[++c], 0, &parse_error);
|
||||||
config.options.crop_top = strtol(argv[++c], NULL, 0);
|
config.options.crop_top = ExUtilGetInt(argv[++c], 0, &parse_error);
|
||||||
config.options.crop_width = strtol(argv[++c], NULL, 0);
|
config.options.crop_width = ExUtilGetInt(argv[++c], 0, &parse_error);
|
||||||
config.options.crop_height = strtol(argv[++c], NULL, 0);
|
config.options.crop_height = ExUtilGetInt(argv[++c], 0, &parse_error);
|
||||||
} else if (!strcmp(argv[c], "-scale") && c < argc - 2) {
|
} else if (!strcmp(argv[c], "-scale") && c < argc - 2) {
|
||||||
config.options.use_scaling = 1;
|
config.options.use_scaling = 1;
|
||||||
config.options.scaled_width = strtol(argv[++c], NULL, 0);
|
config.options.scaled_width = ExUtilGetInt(argv[++c], 0, &parse_error);
|
||||||
config.options.scaled_height = strtol(argv[++c], NULL, 0);
|
config.options.scaled_height = ExUtilGetInt(argv[++c], 0, &parse_error);
|
||||||
#if WEBP_DECODER_ABI_VERSION > 0x0203
|
#if WEBP_DECODER_ABI_VERSION > 0x0203
|
||||||
} else if (!strcmp(argv[c], "-flip")) {
|
} else if (!strcmp(argv[c], "-flip")) {
|
||||||
config.options.flip = 1;
|
config.options.flip = 1;
|
||||||
@ -668,6 +658,11 @@ int main(int argc, const char *argv[]) {
|
|||||||
} else {
|
} else {
|
||||||
in_file = argv[c];
|
in_file = argv[c];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (parse_error) {
|
||||||
|
Help();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (in_file == NULL) {
|
if (in_file == NULL) {
|
||||||
|
@ -11,6 +11,11 @@
|
|||||||
//
|
//
|
||||||
|
|
||||||
#include "./example_util.h"
|
#include "./example_util.h"
|
||||||
|
|
||||||
|
#if defined(_WIN32)
|
||||||
|
#include <fcntl.h> // for _O_BINARY
|
||||||
|
#include <io.h> // for _setmode()
|
||||||
|
#endif
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
@ -18,12 +23,50 @@
|
|||||||
#include "webp/decode.h"
|
#include "webp/decode.h"
|
||||||
#include "./stopwatch.h"
|
#include "./stopwatch.h"
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// String parsing
|
||||||
|
|
||||||
|
uint32_t ExUtilGetUInt(const char* const v, int base, int* const error) {
|
||||||
|
char* end = NULL;
|
||||||
|
const uint32_t n = (v != NULL) ? (uint32_t)strtoul(v, &end, base) : 0u;
|
||||||
|
if (end == v && error != NULL && !*error) {
|
||||||
|
*error = 1;
|
||||||
|
fprintf(stderr, "Error! '%s' is not an integer.\n",
|
||||||
|
(v != NULL) ? v : "(null)");
|
||||||
|
}
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ExUtilGetInt(const char* const v, int base, int* const error) {
|
||||||
|
return (int)ExUtilGetUInt(v, base, error);
|
||||||
|
}
|
||||||
|
|
||||||
|
float ExUtilGetFloat(const char* const v, int* const error) {
|
||||||
|
char* end = NULL;
|
||||||
|
const float f = (v != NULL) ? (float)strtod(v, &end) : 0.f;
|
||||||
|
if (end == v && error != NULL && !*error) {
|
||||||
|
*error = 1;
|
||||||
|
fprintf(stderr, "Error! '%s' is not a floating point number.\n",
|
||||||
|
(v != NULL) ? v : "(null)");
|
||||||
|
}
|
||||||
|
return f;
|
||||||
|
}
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
// File I/O
|
// File I/O
|
||||||
|
|
||||||
static const size_t kBlockSize = 16384; // default initial size
|
FILE* ExUtilSetBinaryMode(FILE* file) {
|
||||||
|
#if defined(_WIN32)
|
||||||
|
if (_setmode(_fileno(file), _O_BINARY) == -1) {
|
||||||
|
fprintf(stderr, "Failed to reopen file in O_BINARY mode.\n");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
return file;
|
||||||
|
}
|
||||||
|
|
||||||
int ExUtilReadFromStdin(const uint8_t** data, size_t* data_size) {
|
int ExUtilReadFromStdin(const uint8_t** data, size_t* data_size) {
|
||||||
|
static const size_t kBlockSize = 16384; // default initial size
|
||||||
size_t max_size = 0;
|
size_t max_size = 0;
|
||||||
size_t size = 0;
|
size_t size = 0;
|
||||||
uint8_t* input = NULL;
|
uint8_t* input = NULL;
|
||||||
@ -32,6 +75,8 @@ int ExUtilReadFromStdin(const uint8_t** data, size_t* data_size) {
|
|||||||
*data = NULL;
|
*data = NULL;
|
||||||
*data_size = 0;
|
*data_size = 0;
|
||||||
|
|
||||||
|
if (!ExUtilSetBinaryMode(stdin)) return 0;
|
||||||
|
|
||||||
while (!feof(stdin)) {
|
while (!feof(stdin)) {
|
||||||
// We double the buffer size each time and read as much as possible.
|
// We double the buffer size each time and read as much as possible.
|
||||||
const size_t extra_size = (max_size == 0) ? kBlockSize : max_size;
|
const size_t extra_size = (max_size == 0) ? kBlockSize : max_size;
|
||||||
|
@ -13,12 +13,30 @@
|
|||||||
#ifndef WEBP_EXAMPLES_EXAMPLE_UTIL_H_
|
#ifndef WEBP_EXAMPLES_EXAMPLE_UTIL_H_
|
||||||
#define WEBP_EXAMPLES_EXAMPLE_UTIL_H_
|
#define WEBP_EXAMPLES_EXAMPLE_UTIL_H_
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
#include "webp/decode.h"
|
#include "webp/decode.h"
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// String parsing
|
||||||
|
|
||||||
|
// Parses 'v' using strto(ul|l|d)(). If error is non-NULL, '*error' is set to
|
||||||
|
// true on failure while on success it is left unmodified to allow chaining of
|
||||||
|
// calls. An error is only printed on the first occurrence.
|
||||||
|
uint32_t ExUtilGetUInt(const char* const v, int base, int* const error);
|
||||||
|
int ExUtilGetInt(const char* const v, int base, int* const error);
|
||||||
|
float ExUtilGetFloat(const char* const v, int* const error);
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// File I/O
|
||||||
|
|
||||||
|
// Reopen file in binary (O_BINARY) mode.
|
||||||
|
// Returns 'file' on success, NULL otherwise.
|
||||||
|
FILE* ExUtilSetBinaryMode(FILE* file);
|
||||||
|
|
||||||
// Allocates storage for entire file 'file_name' and returns contents and size
|
// Allocates storage for entire file 'file_name' and returns contents and size
|
||||||
// in 'data' and 'data_size'. Returns 1 on success, 0 otherwise. '*data' should
|
// in 'data' and 'data_size'. Returns 1 on success, 0 otherwise. '*data' should
|
||||||
// be deleted using free().
|
// be deleted using free().
|
||||||
|
@ -46,7 +46,18 @@
|
|||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
static int transparent_index = -1; // Index of transparent color in the map.
|
static int transparent_index; // Index of transparent color in the map.
|
||||||
|
|
||||||
|
static void ResetFrameInfo(WebPMuxFrameInfo* const info) {
|
||||||
|
WebPDataInit(&info->bitstream);
|
||||||
|
info->x_offset = 0;
|
||||||
|
info->y_offset = 0;
|
||||||
|
info->duration = 0;
|
||||||
|
info->id = WEBP_CHUNK_ANMF;
|
||||||
|
info->dispose_method = WEBP_MUX_DISPOSE_NONE;
|
||||||
|
info->blend_method = WEBP_MUX_BLEND;
|
||||||
|
transparent_index = -1; // Opaque frame by default.
|
||||||
|
}
|
||||||
|
|
||||||
static void SanitizeKeyFrameIntervals(size_t* const kmin_ptr,
|
static void SanitizeKeyFrameIntervals(size_t* const kmin_ptr,
|
||||||
size_t* const kmax_ptr) {
|
size_t* const kmax_ptr) {
|
||||||
@ -163,21 +174,22 @@ static int ReadFrame(GifFileType* const gif, WebPFrameRect* const gif_rect,
|
|||||||
return ok;
|
return ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int GetBackgroundColor(const ColorMapObject* const color_map,
|
static void GetBackgroundColor(const ColorMapObject* const color_map,
|
||||||
int bgcolor_idx, uint32_t* const bgcolor) {
|
int bgcolor_idx, uint32_t* const bgcolor) {
|
||||||
if (transparent_index != -1 && bgcolor_idx == transparent_index) {
|
if (transparent_index != -1 && bgcolor_idx == transparent_index) {
|
||||||
*bgcolor = WEBP_UTIL_TRANSPARENT_COLOR; // Special case.
|
*bgcolor = WEBP_UTIL_TRANSPARENT_COLOR; // Special case.
|
||||||
return 1;
|
|
||||||
} else if (color_map == NULL || color_map->Colors == NULL
|
} else if (color_map == NULL || color_map->Colors == NULL
|
||||||
|| bgcolor_idx >= color_map->ColorCount) {
|
|| bgcolor_idx >= color_map->ColorCount) {
|
||||||
return 0; // Invalid color map or index.
|
*bgcolor = WHITE_COLOR;
|
||||||
|
fprintf(stderr,
|
||||||
|
"GIF decode warning: invalid background color index. Assuming "
|
||||||
|
"white background.\n");
|
||||||
} else {
|
} else {
|
||||||
const GifColorType color = color_map->Colors[bgcolor_idx];
|
const GifColorType color = color_map->Colors[bgcolor_idx];
|
||||||
*bgcolor = (0xff << 24)
|
*bgcolor = (0xff << 24)
|
||||||
| (color.Red << 16)
|
| (color.Red << 16)
|
||||||
| (color.Green << 8)
|
| (color.Green << 8)
|
||||||
| (color.Blue << 0);
|
| (color.Blue << 0);
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -278,10 +290,7 @@ int main(int argc, const char *argv[]) {
|
|||||||
size_t kmax = 0;
|
size_t kmax = 0;
|
||||||
int allow_mixed = 0; // If true, each frame can be lossy or lossless.
|
int allow_mixed = 0; // If true, each frame can be lossy or lossless.
|
||||||
|
|
||||||
memset(&info, 0, sizeof(info));
|
ResetFrameInfo(&info);
|
||||||
info.id = WEBP_CHUNK_ANMF;
|
|
||||||
info.dispose_method = WEBP_MUX_DISPOSE_BACKGROUND;
|
|
||||||
info.blend_method = WEBP_MUX_BLEND;
|
|
||||||
|
|
||||||
if (!WebPConfigInit(&config) || !WebPPictureInit(&frame)) {
|
if (!WebPConfigInit(&config) || !WebPPictureInit(&frame)) {
|
||||||
fprintf(stderr, "Error! Version mismatch!\n");
|
fprintf(stderr, "Error! Version mismatch!\n");
|
||||||
@ -296,6 +305,7 @@ int main(int argc, const char *argv[]) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (c = 1; c < argc; ++c) {
|
for (c = 1; c < argc; ++c) {
|
||||||
|
int parse_error = 0;
|
||||||
if (!strcmp(argv[c], "-h") || !strcmp(argv[c], "-help")) {
|
if (!strcmp(argv[c], "-h") || !strcmp(argv[c], "-help")) {
|
||||||
Help();
|
Help();
|
||||||
return 0;
|
return 0;
|
||||||
@ -307,17 +317,17 @@ int main(int argc, const char *argv[]) {
|
|||||||
allow_mixed = 1;
|
allow_mixed = 1;
|
||||||
config.lossless = 0;
|
config.lossless = 0;
|
||||||
} else if (!strcmp(argv[c], "-q") && c < argc - 1) {
|
} else if (!strcmp(argv[c], "-q") && c < argc - 1) {
|
||||||
config.quality = (float)strtod(argv[++c], NULL);
|
config.quality = ExUtilGetFloat(argv[++c], &parse_error);
|
||||||
} else if (!strcmp(argv[c], "-m") && c < argc - 1) {
|
} else if (!strcmp(argv[c], "-m") && c < argc - 1) {
|
||||||
config.method = strtol(argv[++c], NULL, 0);
|
config.method = ExUtilGetInt(argv[++c], 0, &parse_error);
|
||||||
} else if (!strcmp(argv[c], "-kmax") && c < argc - 1) {
|
} else if (!strcmp(argv[c], "-kmax") && c < argc - 1) {
|
||||||
kmax = strtoul(argv[++c], NULL, 0);
|
kmax = ExUtilGetUInt(argv[++c], 0, &parse_error);
|
||||||
default_kmax = 0;
|
default_kmax = 0;
|
||||||
} else if (!strcmp(argv[c], "-kmin") && c < argc - 1) {
|
} else if (!strcmp(argv[c], "-kmin") && c < argc - 1) {
|
||||||
kmin = strtoul(argv[++c], NULL, 0);
|
kmin = ExUtilGetUInt(argv[++c], 0, &parse_error);
|
||||||
default_kmin = 0;
|
default_kmin = 0;
|
||||||
} else if (!strcmp(argv[c], "-f") && c < argc - 1) {
|
} else if (!strcmp(argv[c], "-f") && c < argc - 1) {
|
||||||
config.filter_strength = strtol(argv[++c], NULL, 0);
|
config.filter_strength = ExUtilGetInt(argv[++c], 0, &parse_error);
|
||||||
} else if (!strcmp(argv[c], "-metadata") && c < argc - 1) {
|
} else if (!strcmp(argv[c], "-metadata") && c < argc - 1) {
|
||||||
static const struct {
|
static const struct {
|
||||||
const char* option;
|
const char* option;
|
||||||
@ -381,6 +391,11 @@ int main(int argc, const char *argv[]) {
|
|||||||
} else {
|
} else {
|
||||||
in_file = argv[c];
|
in_file = argv[c];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (parse_error) {
|
||||||
|
Help();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Appropriate default kmin, kmax values for lossy and lossless.
|
// Appropriate default kmin, kmax values for lossy and lossless.
|
||||||
@ -469,6 +484,10 @@ int main(int argc, const char *argv[]) {
|
|||||||
cache = WebPFrameCacheNew(frame.width, frame.height,
|
cache = WebPFrameCacheNew(frame.width, frame.height,
|
||||||
kmin, kmax, allow_mixed);
|
kmin, kmax, allow_mixed);
|
||||||
if (cache == NULL) goto End;
|
if (cache == NULL) goto End;
|
||||||
|
|
||||||
|
// Background color.
|
||||||
|
GetBackgroundColor(gif->SColorMap, gif->SBackGroundColor,
|
||||||
|
&anim.bgcolor);
|
||||||
}
|
}
|
||||||
// Some even more broken GIF can have sub-rect with zero width/height.
|
// Some even more broken GIF can have sub-rect with zero width/height.
|
||||||
if (image_desc->Width == 0 || image_desc->Height == 0) {
|
if (image_desc->Width == 0 || image_desc->Height == 0) {
|
||||||
@ -492,6 +511,11 @@ int main(int argc, const char *argv[]) {
|
|||||||
goto End;
|
goto End;
|
||||||
}
|
}
|
||||||
is_first_frame = 0;
|
is_first_frame = 0;
|
||||||
|
|
||||||
|
// In GIF, graphic control extensions are optional for a frame, so we
|
||||||
|
// may not get one before reading the next frame. To handle this case,
|
||||||
|
// we reset frame properties to reasonable defaults for the next frame.
|
||||||
|
ResetFrameInfo(&info);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case EXTENSION_RECORD_TYPE: {
|
case EXTENSION_RECORD_TYPE: {
|
||||||
@ -525,13 +549,6 @@ int main(int argc, const char *argv[]) {
|
|||||||
: WEBP_MUX_DISPOSE_NONE;
|
: WEBP_MUX_DISPOSE_NONE;
|
||||||
}
|
}
|
||||||
transparent_index = (flags & GIF_TRANSPARENT_MASK) ? data[4] : -1;
|
transparent_index = (flags & GIF_TRANSPARENT_MASK) ? data[4] : -1;
|
||||||
if (is_first_frame) {
|
|
||||||
if (!GetBackgroundColor(gif->SColorMap, gif->SBackGroundColor,
|
|
||||||
&anim.bgcolor)) {
|
|
||||||
fprintf(stderr, "GIF decode warning: invalid background color "
|
|
||||||
"index. Assuming white background.\n");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case PLAINTEXT_EXT_FUNC_CODE: {
|
case PLAINTEXT_EXT_FUNC_CODE: {
|
||||||
|
@ -475,7 +475,7 @@ static WebPEncodingError SetFrame(const WebPConfig* const config,
|
|||||||
// TODO(later): Perhaps a rough SSIM/PSNR produced by the encoder should
|
// TODO(later): Perhaps a rough SSIM/PSNR produced by the encoder should
|
||||||
// also be a criteria, in addition to sizes.
|
// also be a criteria, in addition to sizes.
|
||||||
if (mem1.size <= mem2.size) {
|
if (mem1.size <= mem2.size) {
|
||||||
#if WEBP_ENCODER_ABI_VERSION > 0x0202
|
#if WEBP_ENCODER_ABI_VERSION > 0x0203
|
||||||
WebPMemoryWriterClear(&mem2);
|
WebPMemoryWriterClear(&mem2);
|
||||||
#else
|
#else
|
||||||
free(mem2.mem);
|
free(mem2.mem);
|
||||||
@ -483,7 +483,7 @@ static WebPEncodingError SetFrame(const WebPConfig* const config,
|
|||||||
#endif
|
#endif
|
||||||
GetEncodedData(&mem1, encoded_data);
|
GetEncodedData(&mem1, encoded_data);
|
||||||
} else {
|
} else {
|
||||||
#if WEBP_ENCODER_ABI_VERSION > 0x0202
|
#if WEBP_ENCODER_ABI_VERSION > 0x0203
|
||||||
WebPMemoryWriterClear(&mem1);
|
WebPMemoryWriterClear(&mem1);
|
||||||
#else
|
#else
|
||||||
free(mem1.mem);
|
free(mem1.mem);
|
||||||
@ -497,7 +497,7 @@ static WebPEncodingError SetFrame(const WebPConfig* const config,
|
|||||||
return error_code;
|
return error_code;
|
||||||
|
|
||||||
Err:
|
Err:
|
||||||
#if WEBP_ENCODER_ABI_VERSION > 0x0202
|
#if WEBP_ENCODER_ABI_VERSION > 0x0203
|
||||||
WebPMemoryWriterClear(&mem1);
|
WebPMemoryWriterClear(&mem1);
|
||||||
WebPMemoryWriterClear(&mem2);
|
WebPMemoryWriterClear(&mem2);
|
||||||
#else
|
#else
|
||||||
|
@ -377,7 +377,7 @@ static void Help(void) {
|
|||||||
" -nofancy ..... don't use the fancy YUV420 upscaler\n"
|
" -nofancy ..... don't use the fancy YUV420 upscaler\n"
|
||||||
" -nofilter .... disable in-loop filtering\n"
|
" -nofilter .... disable in-loop filtering\n"
|
||||||
" -dither <int> dithering strength (0..100), default=50\n"
|
" -dither <int> dithering strength (0..100), default=50\n"
|
||||||
#if WEBP_DECODER_ABI_VERSION > 0x0203
|
#if WEBP_DECODER_ABI_VERSION > 0x0204
|
||||||
" -noalphadither disable alpha plane dithering\n"
|
" -noalphadither disable alpha plane dithering\n"
|
||||||
#endif
|
#endif
|
||||||
" -mt .......... use multi-threading\n"
|
" -mt .......... use multi-threading\n"
|
||||||
@ -402,12 +402,13 @@ int main(int argc, char *argv[]) {
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
config->options.dithering_strength = 50;
|
config->options.dithering_strength = 50;
|
||||||
#if WEBP_DECODER_ABI_VERSION > 0x0203
|
#if WEBP_DECODER_ABI_VERSION > 0x0204
|
||||||
config->options.alpha_dithering_strength = 100;
|
config->options.alpha_dithering_strength = 100;
|
||||||
#endif
|
#endif
|
||||||
kParams.use_color_profile = 1;
|
kParams.use_color_profile = 1;
|
||||||
|
|
||||||
for (c = 1; c < argc; ++c) {
|
for (c = 1; c < argc; ++c) {
|
||||||
|
int parse_error = 0;
|
||||||
if (!strcmp(argv[c], "-h") || !strcmp(argv[c], "-help")) {
|
if (!strcmp(argv[c], "-h") || !strcmp(argv[c], "-help")) {
|
||||||
Help();
|
Help();
|
||||||
return 0;
|
return 0;
|
||||||
@ -417,12 +418,13 @@ int main(int argc, char *argv[]) {
|
|||||||
config->options.no_fancy_upsampling = 1;
|
config->options.no_fancy_upsampling = 1;
|
||||||
} else if (!strcmp(argv[c], "-nofilter")) {
|
} else if (!strcmp(argv[c], "-nofilter")) {
|
||||||
config->options.bypass_filtering = 1;
|
config->options.bypass_filtering = 1;
|
||||||
#if WEBP_DECODER_ABI_VERSION > 0x0203
|
#if WEBP_DECODER_ABI_VERSION > 0x0204
|
||||||
} else if (!strcmp(argv[c], "-noalphadither")) {
|
} else if (!strcmp(argv[c], "-noalphadither")) {
|
||||||
config->options.alpha_dithering_strength = 0;
|
config->options.alpha_dithering_strength = 0;
|
||||||
#endif
|
#endif
|
||||||
} else if (!strcmp(argv[c], "-dither") && c + 1 < argc) {
|
} else if (!strcmp(argv[c], "-dither") && c + 1 < argc) {
|
||||||
config->options.dithering_strength = strtol(argv[++c], NULL, 0);
|
config->options.dithering_strength =
|
||||||
|
ExUtilGetInt(argv[++c], 0, &parse_error);
|
||||||
} else if (!strcmp(argv[c], "-info")) {
|
} else if (!strcmp(argv[c], "-info")) {
|
||||||
kParams.print_info = 1;
|
kParams.print_info = 1;
|
||||||
} else if (!strcmp(argv[c], "-version")) {
|
} else if (!strcmp(argv[c], "-version")) {
|
||||||
@ -445,6 +447,11 @@ int main(int argc, char *argv[]) {
|
|||||||
} else {
|
} else {
|
||||||
kParams.file_name = argv[c];
|
kParams.file_name = argv[c];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (parse_error) {
|
||||||
|
Help();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (kParams.file_name == NULL) {
|
if (kParams.file_name == NULL) {
|
||||||
|
@ -402,8 +402,9 @@ static int CreateMux(const char* const filename, WebPMux** mux) {
|
|||||||
|
|
||||||
static int WriteData(const char* filename, const WebPData* const webpdata) {
|
static int WriteData(const char* filename, const WebPData* const webpdata) {
|
||||||
int ok = 0;
|
int ok = 0;
|
||||||
FILE* fout = strcmp(filename, "-") ? fopen(filename, "wb") : stdout;
|
FILE* fout = strcmp(filename, "-") ? fopen(filename, "wb")
|
||||||
if (!fout) {
|
: ExUtilSetBinaryMode(stdout);
|
||||||
|
if (fout == NULL) {
|
||||||
fprintf(stderr, "Error opening output WebP file %s!\n", filename);
|
fprintf(stderr, "Error opening output WebP file %s!\n", filename);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -487,7 +488,7 @@ static int ParseBgcolorArgs(const char* args, uint32_t* const bgcolor) {
|
|||||||
static void DeleteConfig(WebPMuxConfig* config) {
|
static void DeleteConfig(WebPMuxConfig* config) {
|
||||||
if (config != NULL) {
|
if (config != NULL) {
|
||||||
free(config->feature_.args_);
|
free(config->feature_.args_);
|
||||||
free(config);
|
memset(config, 0, sizeof(*config));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -790,33 +791,27 @@ static int ValidateConfig(WebPMuxConfig* config) {
|
|||||||
|
|
||||||
// Create config object from command-line arguments.
|
// Create config object from command-line arguments.
|
||||||
static int InitializeConfig(int argc, const char* argv[],
|
static int InitializeConfig(int argc, const char* argv[],
|
||||||
WebPMuxConfig** config) {
|
WebPMuxConfig* config) {
|
||||||
int num_feature_args = 0;
|
int num_feature_args = 0;
|
||||||
int ok = 1;
|
int ok = 1;
|
||||||
|
|
||||||
assert(config != NULL);
|
assert(config != NULL);
|
||||||
*config = NULL;
|
memset(config, 0, sizeof(*config));
|
||||||
|
|
||||||
// Validate command-line arguments.
|
// Validate command-line arguments.
|
||||||
if (!ValidateCommandLine(argc, argv, &num_feature_args)) {
|
if (!ValidateCommandLine(argc, argv, &num_feature_args)) {
|
||||||
ERROR_GOTO1("Exiting due to command-line parsing error.\n", Err1);
|
ERROR_GOTO1("Exiting due to command-line parsing error.\n", Err1);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Allocate memory.
|
config->feature_.arg_count_ = num_feature_args;
|
||||||
*config = (WebPMuxConfig*)calloc(1, sizeof(**config));
|
config->feature_.args_ =
|
||||||
if (*config == NULL) {
|
(FeatureArg*)calloc(num_feature_args, sizeof(*config->feature_.args_));
|
||||||
ERROR_GOTO1("ERROR: Memory allocation error.\n", Err1);
|
if (config->feature_.args_ == NULL) {
|
||||||
}
|
|
||||||
(*config)->feature_.arg_count_ = num_feature_args;
|
|
||||||
(*config)->feature_.args_ =
|
|
||||||
(FeatureArg*)calloc(num_feature_args, sizeof(FeatureArg));
|
|
||||||
if ((*config)->feature_.args_ == NULL) {
|
|
||||||
ERROR_GOTO1("ERROR: Memory allocation error.\n", Err1);
|
ERROR_GOTO1("ERROR: Memory allocation error.\n", Err1);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Parse command-line.
|
// Parse command-line.
|
||||||
if (!ParseCommandLine(argc, argv, *config) ||
|
if (!ParseCommandLine(argc, argv, config) || !ValidateConfig(config)) {
|
||||||
!ValidateConfig(*config)) {
|
|
||||||
ERROR_GOTO1("Exiting due to command-line parsing error.\n", Err1);
|
ERROR_GOTO1("Exiting due to command-line parsing error.\n", Err1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -838,14 +833,16 @@ static int GetFrameFragment(const WebPMux* mux,
|
|||||||
WebPMux* mux_single = NULL;
|
WebPMux* mux_single = NULL;
|
||||||
long num = 0;
|
long num = 0;
|
||||||
int ok = 1;
|
int ok = 1;
|
||||||
|
int parse_error = 0;
|
||||||
const WebPChunkId id = is_frame ? WEBP_CHUNK_ANMF : WEBP_CHUNK_FRGM;
|
const WebPChunkId id = is_frame ? WEBP_CHUNK_ANMF : WEBP_CHUNK_FRGM;
|
||||||
WebPMuxFrameInfo info;
|
WebPMuxFrameInfo info;
|
||||||
WebPDataInit(&info.bitstream);
|
WebPDataInit(&info.bitstream);
|
||||||
|
|
||||||
num = strtol(config->feature_.args_[0].params_, NULL, 10);
|
num = ExUtilGetInt(config->feature_.args_[0].params_, 10, &parse_error);
|
||||||
if (num < 0) {
|
if (num < 0) {
|
||||||
ERROR_GOTO1("ERROR: Frame/Fragment index must be non-negative.\n", ErrGet);
|
ERROR_GOTO1("ERROR: Frame/Fragment index must be non-negative.\n", ErrGet);
|
||||||
}
|
}
|
||||||
|
if (parse_error) goto ErrGet;
|
||||||
|
|
||||||
err = WebPMuxGetFrame(mux, num, &info);
|
err = WebPMuxGetFrame(mux, num, &info);
|
||||||
if (err == WEBP_MUX_OK && info.id != id) err = WEBP_MUX_NOT_FOUND;
|
if (err == WEBP_MUX_OK && info.id != id) err = WEBP_MUX_NOT_FOUND;
|
||||||
@ -871,7 +868,7 @@ static int GetFrameFragment(const WebPMux* mux,
|
|||||||
ErrGet:
|
ErrGet:
|
||||||
WebPDataClear(&info.bitstream);
|
WebPDataClear(&info.bitstream);
|
||||||
WebPMuxDelete(mux_single);
|
WebPMuxDelete(mux_single);
|
||||||
return ok;
|
return ok && !parse_error;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Read and process config.
|
// Read and process config.
|
||||||
@ -933,16 +930,19 @@ static int Process(const WebPMuxConfig* config) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case SUBTYPE_LOOP: {
|
case SUBTYPE_LOOP: {
|
||||||
const long loop_count =
|
int parse_error = 0;
|
||||||
strtol(feature->args_[i].params_, NULL, 10);
|
const int loop_count =
|
||||||
if (loop_count != (int)loop_count) {
|
ExUtilGetInt(feature->args_[i].params_, 10, &parse_error);
|
||||||
|
if (loop_count < 0 || loop_count > 65535) {
|
||||||
// Note: This is only a 'necessary' condition for loop_count
|
// Note: This is only a 'necessary' condition for loop_count
|
||||||
// to be valid. The 'sufficient' conditioned in checked in
|
// to be valid. The 'sufficient' conditioned in checked in
|
||||||
// WebPMuxSetAnimationParams() method called later.
|
// WebPMuxSetAnimationParams() method called later.
|
||||||
ERROR_GOTO1("ERROR: Loop count must be in the range 0 to "
|
ERROR_GOTO1("ERROR: Loop count must be in the range 0 to "
|
||||||
"65535.\n", Err2);
|
"65535.\n", Err2);
|
||||||
}
|
}
|
||||||
params.loop_count = (int)loop_count;
|
ok = !parse_error;
|
||||||
|
if (!ok) goto Err2;
|
||||||
|
params.loop_count = loop_count;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case SUBTYPE_ANMF: {
|
case SUBTYPE_ANMF: {
|
||||||
@ -1042,8 +1042,8 @@ static int Process(const WebPMuxConfig* config) {
|
|||||||
ErrorString(err), kDescriptions[feature->type_], Err2);
|
ErrorString(err), kDescriptions[feature->type_], Err2);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
ERROR_GOTO1("ERROR: Invalid feature for action 'strip'.\n", Err2);
|
ERROR_GOTO1("ERROR: Invalid feature for action 'strip'.\n", Err2);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
ok = WriteWebP(mux, config->output_);
|
ok = WriteWebP(mux, config->output_);
|
||||||
break;
|
break;
|
||||||
@ -1069,14 +1069,14 @@ static int Process(const WebPMuxConfig* config) {
|
|||||||
// Main.
|
// Main.
|
||||||
|
|
||||||
int main(int argc, const char* argv[]) {
|
int main(int argc, const char* argv[]) {
|
||||||
WebPMuxConfig* config;
|
WebPMuxConfig config;
|
||||||
int ok = InitializeConfig(argc - 1, argv + 1, &config);
|
int ok = InitializeConfig(argc - 1, argv + 1, &config);
|
||||||
if (ok) {
|
if (ok) {
|
||||||
ok = Process(config);
|
ok = Process(&config);
|
||||||
} else {
|
} else {
|
||||||
PrintHelp();
|
PrintHelp();
|
||||||
}
|
}
|
||||||
DeleteConfig(config);
|
DeleteConfig(&config);
|
||||||
return !ok;
|
return !ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
70
iosbuild.sh
70
iosbuild.sh
@ -12,31 +12,35 @@
|
|||||||
set -e
|
set -e
|
||||||
|
|
||||||
# Extract the latest SDK version from the final field of the form: iphoneosX.Y
|
# Extract the latest SDK version from the final field of the form: iphoneosX.Y
|
||||||
declare -r SDK=$(xcodebuild -showsdks \
|
readonly SDK=$(xcodebuild -showsdks \
|
||||||
| grep iphoneos | sort | tail -n 1 | awk '{print substr($NF, 9)}'
|
| grep iphoneos | sort | tail -n 1 | awk '{print substr($NF, 9)}'
|
||||||
)
|
)
|
||||||
# Extract Xcode version.
|
# Extract Xcode version.
|
||||||
declare -r XCODE=$(xcodebuild -version | grep Xcode | cut -d " " -f2)
|
readonly XCODE=$(xcodebuild -version | grep Xcode | cut -d " " -f2)
|
||||||
|
if [[ -z "${XCODE}" ]]; then
|
||||||
|
echo "Xcode not available"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
declare -r OLDPATH=${PATH}
|
readonly OLDPATH=${PATH}
|
||||||
|
|
||||||
# Add iPhoneOS-V6 to the list of platforms below if you need armv6 support.
|
# Add iPhoneOS-V6 to the list of platforms below if you need armv6 support.
|
||||||
# Note that iPhoneOS-V6 support is not available with the iOS6 SDK.
|
# Note that iPhoneOS-V6 support is not available with the iOS6 SDK.
|
||||||
declare -r PLATFORMS="iPhoneSimulator iPhoneOS-V7 iPhoneOS-V7s iPhoneOS-V7-arm64"
|
readonly PLATFORMS="iPhoneSimulator iPhoneOS-V7 iPhoneOS-V7s iPhoneOS-V7-arm64"
|
||||||
declare -r SRCDIR=$(dirname $0)
|
readonly SRCDIR=$(dirname $0)
|
||||||
declare -r TOPDIR=$(pwd)
|
readonly TOPDIR=$(pwd)
|
||||||
declare -r BUILDDIR="${TOPDIR}/iosbuild"
|
readonly BUILDDIR="${TOPDIR}/iosbuild"
|
||||||
declare -r TARGETDIR="${TOPDIR}/WebP.framework"
|
readonly TARGETDIR="${TOPDIR}/WebP.framework"
|
||||||
declare -r DEVELOPER=$(xcode-select --print-path)
|
readonly DEVELOPER=$(xcode-select --print-path)
|
||||||
declare -r PLATFORMSROOT="${DEVELOPER}/Platforms"
|
readonly PLATFORMSROOT="${DEVELOPER}/Platforms"
|
||||||
declare -r LIPO=$(xcrun -sdk iphoneos${SDK} -find lipo)
|
readonly LIPO=$(xcrun -sdk iphoneos${SDK} -find lipo)
|
||||||
LIBLIST=''
|
LIBLIST=''
|
||||||
|
|
||||||
if [[ -z "${SDK}" ]]; then
|
if [[ -z "${SDK}" ]]; then
|
||||||
echo "iOS SDK not available"
|
echo "iOS SDK not available"
|
||||||
exit 1
|
exit 1
|
||||||
elif [[ ${SDK} < 4.0 ]]; then
|
elif [[ ${SDK} < 6.0 ]]; then
|
||||||
echo "You need iOS SDK version 4.0 or above"
|
echo "You need iOS SDK version 6.0 or above"
|
||||||
exit 1
|
exit 1
|
||||||
else
|
else
|
||||||
echo "iOS SDK Version ${SDK}"
|
echo "iOS SDK Version ${SDK}"
|
||||||
@ -47,7 +51,17 @@ rm -rf ${TARGETDIR}
|
|||||||
mkdir -p ${BUILDDIR}
|
mkdir -p ${BUILDDIR}
|
||||||
mkdir -p ${TARGETDIR}/Headers/
|
mkdir -p ${TARGETDIR}/Headers/
|
||||||
|
|
||||||
[[ -e ${SRCDIR}/configure ]] || (cd ${SRCDIR} && sh autogen.sh)
|
if [[ ! -e ${SRCDIR}/configure ]]; then
|
||||||
|
if ! (cd ${SRCDIR} && sh autogen.sh); then
|
||||||
|
cat <<EOT
|
||||||
|
Error creating configure script!
|
||||||
|
This script requires the autoconf/automake and libtool to build. MacPorts can
|
||||||
|
be used to obtain these:
|
||||||
|
http://www.macports.org/install.php
|
||||||
|
EOT
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
for PLATFORM in ${PLATFORMS}; do
|
for PLATFORM in ${PLATFORMS}; do
|
||||||
ARCH2=""
|
ARCH2=""
|
||||||
@ -71,30 +85,20 @@ for PLATFORM in ${PLATFORMS}; do
|
|||||||
ROOTDIR="${BUILDDIR}/${PLATFORM}-${SDK}-${ARCH}"
|
ROOTDIR="${BUILDDIR}/${PLATFORM}-${SDK}-${ARCH}"
|
||||||
mkdir -p "${ROOTDIR}"
|
mkdir -p "${ROOTDIR}"
|
||||||
|
|
||||||
SDKROOT="${PLATFORMSROOT}/${PLATFORM}.platform/Developer/SDKs/${PLATFORM}${SDK}.sdk/"
|
DEVROOT="${DEVELOPER}/Toolchains/XcodeDefault.xctoolchain"
|
||||||
|
SDKROOT="${PLATFORMSROOT}/"
|
||||||
|
SDKROOT+="${PLATFORM}.platform/Developer/SDKs/${PLATFORM}${SDK}.sdk/"
|
||||||
CFLAGS="-arch ${ARCH2:-${ARCH}} -pipe -isysroot ${SDKROOT} -O3 -DNDEBUG"
|
CFLAGS="-arch ${ARCH2:-${ARCH}} -pipe -isysroot ${SDKROOT} -O3 -DNDEBUG"
|
||||||
LDFLAGS="-arch ${ARCH2:-${ARCH}} -pipe -isysroot ${SDKROOT}"
|
CFLAGS+=" -miphoneos-version-min=6.0"
|
||||||
|
|
||||||
if [[ -z "${XCODE}" ]]; then
|
set -x
|
||||||
echo "XCODE not available"
|
|
||||||
exit 1
|
|
||||||
elif [[ ${SDK} < 5.0.0 ]]; then
|
|
||||||
DEVROOT="${PLATFORMSROOT}/${PLATFORM}.platform/Developer/"
|
|
||||||
else
|
|
||||||
DEVROOT="${DEVELOPER}/Toolchains/XcodeDefault.xctoolchain"
|
|
||||||
CFLAGS+=" -miphoneos-version-min=5.0"
|
|
||||||
LDFLAGS+=" -miphoneos-version-min=5.0"
|
|
||||||
fi
|
|
||||||
|
|
||||||
export CFLAGS
|
|
||||||
export LDFLAGS
|
|
||||||
export CXXFLAGS=${CFLAGS}
|
|
||||||
export PATH="${DEVROOT}/usr/bin:${OLDPATH}"
|
export PATH="${DEVROOT}/usr/bin:${OLDPATH}"
|
||||||
|
|
||||||
${SRCDIR}/configure --host=${ARCH}-apple-darwin --prefix=${ROOTDIR} \
|
${SRCDIR}/configure --host=${ARCH}-apple-darwin --prefix=${ROOTDIR} \
|
||||||
--build=$(${SRCDIR}/config.guess) \
|
--build=$(${SRCDIR}/config.guess) \
|
||||||
--disable-shared --enable-static \
|
--disable-shared --enable-static \
|
||||||
--enable-libwebpdecoder --enable-swap-16bit-csp
|
--enable-libwebpdecoder --enable-swap-16bit-csp \
|
||||||
|
CFLAGS="${CFLAGS}"
|
||||||
|
set +x
|
||||||
|
|
||||||
# run make only in the src/ directory to create libwebpdecoder.a
|
# run make only in the src/ directory to create libwebpdecoder.a
|
||||||
cd src/
|
cd src/
|
||||||
@ -109,5 +113,5 @@ for PLATFORM in ${PLATFORMS}; do
|
|||||||
export PATH=${OLDPATH}
|
export PATH=${OLDPATH}
|
||||||
done
|
done
|
||||||
|
|
||||||
cp -a ${SRCDIR}/src/webp/* ${TARGETDIR}/Headers/
|
cp -a ${SRCDIR}/src/webp/*.h ${TARGETDIR}/Headers/
|
||||||
${LIPO} -create ${LIBLIST} -output ${TARGETDIR}/WebP
|
${LIPO} -create ${LIBLIST} -output ${TARGETDIR}/WebP
|
||||||
|
@ -108,6 +108,7 @@ DEMUX_OBJS = \
|
|||||||
|
|
||||||
DSP_DEC_OBJS = \
|
DSP_DEC_OBJS = \
|
||||||
src/dsp/alpha_processing.o \
|
src/dsp/alpha_processing.o \
|
||||||
|
src/dsp/alpha_processing_sse2.o \
|
||||||
src/dsp/cpu.o \
|
src/dsp/cpu.o \
|
||||||
src/dsp/dec.o \
|
src/dsp/dec.o \
|
||||||
src/dsp/dec_clip_tables.o \
|
src/dsp/dec_clip_tables.o \
|
||||||
|
16
man/cwebp.1
16
man/cwebp.1
@ -1,5 +1,5 @@
|
|||||||
.\" Hey, EMACS: -*- nroff -*-
|
.\" Hey, EMACS: -*- nroff -*-
|
||||||
.TH CWEBP 1 "July 22, 2014"
|
.TH CWEBP 1 "Oct 13, 2014"
|
||||||
.SH NAME
|
.SH NAME
|
||||||
cwebp \- compress an image file to a WebP file
|
cwebp \- compress an image file to a WebP file
|
||||||
.SH SYNOPSIS
|
.SH SYNOPSIS
|
||||||
@ -38,6 +38,13 @@ Print the version number (as major.minor.revision) and exit.
|
|||||||
.BI \-q " float
|
.BI \-q " float
|
||||||
Specify the compression factor for RGB channels between 0 and 100. The default
|
Specify the compression factor for RGB channels between 0 and 100. The default
|
||||||
is 75.
|
is 75.
|
||||||
|
.br
|
||||||
|
In case of lossy compression (default), a small factor produces a smaller file
|
||||||
|
with lower quality. Best quality is achieved by using a value of 100.
|
||||||
|
.br
|
||||||
|
In case of lossless compression (specified by the \-lossless option), a small
|
||||||
|
factor enables faster compression speed, but produces a larger file. Maximum
|
||||||
|
compression is achieved by using a value of 100.
|
||||||
.\" TODO(jzern): restore post-v0.4.1
|
.\" TODO(jzern): restore post-v0.4.1
|
||||||
.\" .TP
|
.\" .TP
|
||||||
.\" .BI \-z " int
|
.\" .BI \-z " int
|
||||||
@ -47,13 +54,6 @@ is 75.
|
|||||||
.\" This option is actually a shortcut for some predefined settings for quality
|
.\" This option is actually a shortcut for some predefined settings for quality
|
||||||
.\" and method. If options \-q or \-m are subsequently used, they will invalidate
|
.\" and method. If options \-q or \-m are subsequently used, they will invalidate
|
||||||
.\" the effect of this \-z option.
|
.\" the effect of this \-z option.
|
||||||
.\" .br
|
|
||||||
.\" In case of lossy compression (default), a small factor produces a smaller file
|
|
||||||
.\" with lower quality. Best quality is achieved by using a value of 100.
|
|
||||||
.\" .br
|
|
||||||
.\" In case of lossless compression (specified by the \-lossless option), a small
|
|
||||||
.\" factor enables faster compression speed, but produces a larger file. Maximum
|
|
||||||
.\" compression is achieved by using a value of 100.
|
|
||||||
.TP
|
.TP
|
||||||
.BI \-alpha_q " int
|
.BI \-alpha_q " int
|
||||||
Specify the compression factor for alpha compression between 0 and 100.
|
Specify the compression factor for alpha compression between 0 and 100.
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
.\" Hey, EMACS: -*- nroff -*-
|
.\" Hey, EMACS: -*- nroff -*-
|
||||||
.TH WEBPMUX 1 "December 17, 2013"
|
.TH WEBPMUX 1 "August 28, 2014"
|
||||||
.SH NAME
|
.SH NAME
|
||||||
webpmux \- command line tool to create WebP Mux/container file.
|
webpmux \- create animated WebP files from non\-animated WebP images, extract
|
||||||
|
frames from animated WebP images, and manage XMP/EXIF metadata and ICC profile.
|
||||||
.SH SYNOPSIS
|
.SH SYNOPSIS
|
||||||
.B webpmux \-get
|
.B webpmux \-get
|
||||||
.I GET_OPTIONS
|
.I GET_OPTIONS
|
||||||
@ -45,8 +46,8 @@ This manual page documents the
|
|||||||
.B webpmux
|
.B webpmux
|
||||||
command.
|
command.
|
||||||
.PP
|
.PP
|
||||||
\fBwebpmux\fP can be used to create a WebP container file
|
\fBwebpmux\fP can be used to create/extract from animated WebP files, as well as
|
||||||
and extract/strip relevant data from the container file.
|
to add/extract/strip XMP/EXIF metadata and ICC profile.
|
||||||
.SH OPTIONS
|
.SH OPTIONS
|
||||||
.SS GET_OPTIONS (\-get):
|
.SS GET_OPTIONS (\-get):
|
||||||
.TP
|
.TP
|
||||||
@ -60,7 +61,7 @@ Get EXIF metadata.
|
|||||||
Get XMP metadata.
|
Get XMP metadata.
|
||||||
.TP
|
.TP
|
||||||
.BI frame " n
|
.BI frame " n
|
||||||
Get nth frame.
|
Get nth frame from an animated image. (n = 0 has a special meaning: last frame).
|
||||||
|
|
||||||
.SS SET_OPTIONS (\-set)
|
.SS SET_OPTIONS (\-set)
|
||||||
.TP
|
.TP
|
||||||
@ -91,12 +92,13 @@ Strip EXIF metadata.
|
|||||||
Strip XMP metadata.
|
Strip XMP metadata.
|
||||||
|
|
||||||
.SS FRAME_OPTIONS (\-frame)
|
.SS FRAME_OPTIONS (\-frame)
|
||||||
|
Create an animated WebP file from multiple (non\-animated) WebP images.
|
||||||
.TP
|
.TP
|
||||||
.I file_i +di[+xi+yi[+mi[bi]]]
|
.I file_i +di[+xi+yi[+mi[bi]]]
|
||||||
Where: 'file_i' is the i'th frame (WebP format), 'xi','yi' specify the image
|
Where: 'file_i' is the i'th frame (WebP format), 'xi','yi' specify the image
|
||||||
offset for this frame, 'di' is the pause duration before next frame, 'mi' is
|
offset for this frame, 'di' is the pause duration before next frame, 'mi' is
|
||||||
the dispose method for this frame (0 for NONE or 1 for BACKGROUND) and 'bi' is
|
the dispose method for this frame (0 for NONE or 1 for BACKGROUND) and 'bi' is
|
||||||
the blending method for this frame (+b for BLEND or -b for NO_BLEND).
|
the blending method for this frame (+b for BLEND or \-b for NO_BLEND).
|
||||||
Argument 'bi' can be omitted and will default to +b (BLEND).
|
Argument 'bi' can be omitted and will default to +b (BLEND).
|
||||||
Also, 'mi' can be omitted if 'bi' is omitted and will default to 0 (NONE).
|
Also, 'mi' can be omitted if 'bi' is omitted and will default to 0 (NONE).
|
||||||
Finally, if 'mi' and 'bi' are omitted then 'xi' and 'yi' can be omitted and will
|
Finally, if 'mi' and 'bi' are omitted then 'xi' and 'yi' can be omitted and will
|
||||||
@ -130,37 +132,61 @@ Please report all bugs to our issue tracker:
|
|||||||
http://code.google.com/p/webp/issues
|
http://code.google.com/p/webp/issues
|
||||||
.br
|
.br
|
||||||
Patches welcome! See this page to get started:
|
Patches welcome! See this page to get started:
|
||||||
http://www.webmproject.org/code/contribute/submitting-patches/
|
http://www.webmproject.org/code/contribute/submitting\-patches/
|
||||||
|
|
||||||
.SH EXAMPLES
|
.SH EXAMPLES
|
||||||
|
.P
|
||||||
|
Add ICC profile:
|
||||||
|
.br
|
||||||
webpmux \-set icc image_profile.icc in.webp \-o icc_container.webp
|
webpmux \-set icc image_profile.icc in.webp \-o icc_container.webp
|
||||||
|
.P
|
||||||
|
Extract ICC profile:
|
||||||
.br
|
.br
|
||||||
webpmux \-get icc icc_container.webp \-o image_profile.icc
|
webpmux \-get icc icc_container.webp \-o image_profile.icc
|
||||||
|
.P
|
||||||
|
Strip ICC profile:
|
||||||
.br
|
.br
|
||||||
webpmux \-strip icc icc_container.webp \-o without_icc.webp
|
webpmux \-strip icc icc_container.webp \-o without_icc.webp
|
||||||
|
.P
|
||||||
|
Add XMP metadata:
|
||||||
.br
|
.br
|
||||||
webpmux \-set xmp image_metadata.xmp in.webp \-o xmp_container.webp
|
webpmux \-set xmp image_metadata.xmp in.webp \-o xmp_container.webp
|
||||||
|
.P
|
||||||
|
Extract XMP metadata:
|
||||||
.br
|
.br
|
||||||
webpmux \-get xmp xmp_container.webp \-o image_metadata.xmp
|
webpmux \-get xmp xmp_container.webp \-o image_metadata.xmp
|
||||||
|
.P
|
||||||
|
Strip XMP metadata:
|
||||||
.br
|
.br
|
||||||
webpmux \-strip xmp xmp_container.webp \-o without_xmp.webp
|
webpmux \-strip xmp xmp_container.webp \-o without_xmp.webp
|
||||||
|
.P
|
||||||
|
Add EXIF metadata:
|
||||||
.br
|
.br
|
||||||
webpmux \-set exif image_metadata.exif in.webp \-o exif_container.webp
|
webpmux \-set exif image_metadata.exif in.webp \-o exif_container.webp
|
||||||
|
.P
|
||||||
|
Extract EXIF metadata:
|
||||||
.br
|
.br
|
||||||
webpmux \-get exif exif_container.webp \-o image_metadata.exif
|
webpmux \-get exif exif_container.webp \-o image_metadata.exif
|
||||||
|
.P
|
||||||
|
Strip EXIF metadata:
|
||||||
.br
|
.br
|
||||||
webpmux \-strip exif exif_container.webp \-o without_exif.webp
|
webpmux \-strip exif exif_container.webp \-o without_exif.webp
|
||||||
|
.P
|
||||||
|
Create an animated WebP file from 3 (non\-animated) WebP images:
|
||||||
.br
|
.br
|
||||||
webpmux \-frame anim_1.webp +100 \-frame anim_2.webp +100+50+50
|
webpmux \-frame 1.webp +100 \-frame 2.webp +100+50+50
|
||||||
.br
|
.br
|
||||||
.RS 8
|
.RS 8
|
||||||
\-frame anim_2.webp +100+50+50+1+b \-loop 10 \-bgcolor 255,255,255,255
|
\-frame 3.webp +100+50+50+1+b \-loop 10 \-bgcolor 255,255,255,255
|
||||||
.br
|
.br
|
||||||
.RS 8
|
|
||||||
\-o anim_container.webp
|
\-o anim_container.webp
|
||||||
.RE
|
.RE
|
||||||
|
.P
|
||||||
|
Get the 2nd frame from an animated WebP file:
|
||||||
.br
|
.br
|
||||||
webpmux \-get frame 2 anim_container.webp \-o frame_2.webp
|
webpmux \-get frame 2 anim_container.webp \-o frame_2.webp
|
||||||
|
.P
|
||||||
|
Using \-get/\-set/\-strip with input file name starting with '\-':
|
||||||
.br
|
.br
|
||||||
webpmux \-set icc image_profile.icc \-o icc_container.webp \-\- \-\-\-in.webp
|
webpmux \-set icc image_profile.icc \-o icc_container.webp \-\- \-\-\-in.webp
|
||||||
.br
|
.br
|
||||||
|
@ -35,7 +35,7 @@ libwebp_la_LIBADD += utils/libwebputils.la
|
|||||||
# other than the ones listed on the command line, i.e., after linking, it will
|
# other than the ones listed on the command line, i.e., after linking, it will
|
||||||
# not have unresolved symbols. Some platforms (Windows among them) require all
|
# not have unresolved symbols. Some platforms (Windows among them) require all
|
||||||
# symbols in shared libraries to be resolved at library creation.
|
# symbols in shared libraries to be resolved at library creation.
|
||||||
libwebp_la_LDFLAGS = -no-undefined -version-info 5:1:0
|
libwebp_la_LDFLAGS = -no-undefined -version-info 5:2:0
|
||||||
libwebpincludedir = $(includedir)/webp
|
libwebpincludedir = $(includedir)/webp
|
||||||
pkgconfig_DATA = libwebp.pc
|
pkgconfig_DATA = libwebp.pc
|
||||||
|
|
||||||
@ -47,7 +47,7 @@ if BUILD_LIBWEBPDECODER
|
|||||||
libwebpdecoder_la_LIBADD += dsp/libwebpdspdecode.la
|
libwebpdecoder_la_LIBADD += dsp/libwebpdspdecode.la
|
||||||
libwebpdecoder_la_LIBADD += utils/libwebputilsdecode.la
|
libwebpdecoder_la_LIBADD += utils/libwebputilsdecode.la
|
||||||
|
|
||||||
libwebpdecoder_la_LDFLAGS = -no-undefined -version-info 1:1:0
|
libwebpdecoder_la_LDFLAGS = -no-undefined -version-info 1:2:0
|
||||||
pkgconfig_DATA += libwebpdecoder.pc
|
pkgconfig_DATA += libwebpdecoder.pc
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
@ -177,7 +177,7 @@ void VP8InitDithering(const WebPDecoderOptions* const options,
|
|||||||
dec->dither_ = 1;
|
dec->dither_ = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#if WEBP_DECODER_ABI_VERSION > 0x0203
|
#if WEBP_DECODER_ABI_VERSION > 0x0204
|
||||||
// potentially allow alpha dithering
|
// potentially allow alpha dithering
|
||||||
dec->alpha_dithering_ = options->alpha_dithering_strength;
|
dec->alpha_dithering_ = options->alpha_dithering_strength;
|
||||||
if (dec->alpha_dithering_ > 100) {
|
if (dec->alpha_dithering_ > 100) {
|
||||||
|
@ -529,6 +529,12 @@ static VP8StatusCode DecodeVP8LData(WebPIDecoder* const idec) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!VP8LDecodeImage(dec)) {
|
if (!VP8LDecodeImage(dec)) {
|
||||||
|
// The decoding is called after all the data-bytes are aggregated. Change
|
||||||
|
// the error to VP8_BITSTREAM_ERROR in case lossless decoder fails to decode
|
||||||
|
// all the pixels (VP8_STATUS_SUSPENDED).
|
||||||
|
if (dec->status_ == VP8_STATUS_SUSPENDED) {
|
||||||
|
dec->status_ = VP8_STATUS_BITSTREAM_ERROR;
|
||||||
|
}
|
||||||
return ErrorStatusLossless(idec, dec->status_);
|
return ErrorStatusLossless(idec, dec->status_);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -11,7 +11,7 @@
|
|||||||
//
|
//
|
||||||
// Author: Skal (pascal.massimino@gmail.com)
|
// Author: Skal (pascal.massimino@gmail.com)
|
||||||
|
|
||||||
#include "vp8i.h"
|
#include "./vp8i.h"
|
||||||
#include "../utils/bit_reader_inl.h"
|
#include "../utils/bit_reader_inl.h"
|
||||||
|
|
||||||
#define USE_GENERIC_TREE
|
#define USE_GENERIC_TREE
|
||||||
|
@ -31,7 +31,7 @@ extern "C" {
|
|||||||
// version numbers
|
// version numbers
|
||||||
#define DEC_MAJ_VERSION 0
|
#define DEC_MAJ_VERSION 0
|
||||||
#define DEC_MIN_VERSION 4
|
#define DEC_MIN_VERSION 4
|
||||||
#define DEC_REV_VERSION 1
|
#define DEC_REV_VERSION 2
|
||||||
|
|
||||||
// intra prediction modes
|
// intra prediction modes
|
||||||
enum { B_DC_PRED = 0, // 4x4 modes
|
enum { B_DC_PRED = 0, // 4x4 modes
|
||||||
|
@ -234,6 +234,7 @@ static int ReadHuffmanCodeLengths(
|
|||||||
|
|
||||||
End:
|
End:
|
||||||
VP8LHuffmanTreeFree(&tree);
|
VP8LHuffmanTreeFree(&tree);
|
||||||
|
if (!ok) dec->status_ = VP8_STATUS_BITSTREAM_ERROR;
|
||||||
return ok;
|
return ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -801,6 +802,7 @@ static int DecodeAlphaData(VP8LDecoder* const dec, uint8_t* const data,
|
|||||||
ok = 0;
|
ok = 0;
|
||||||
goto End;
|
goto End;
|
||||||
}
|
}
|
||||||
|
assert(br->eos_ == VP8LIsEndOfStream(br));
|
||||||
ok = !br->error_;
|
ok = !br->error_;
|
||||||
if (!ok) goto End;
|
if (!ok) goto End;
|
||||||
}
|
}
|
||||||
@ -918,6 +920,7 @@ static int DecodeImageData(VP8LDecoder* const dec, uint32_t* const data,
|
|||||||
ok = 0;
|
ok = 0;
|
||||||
goto End;
|
goto End;
|
||||||
}
|
}
|
||||||
|
assert(br->eos_ == VP8LIsEndOfStream(br));
|
||||||
ok = !br->error_;
|
ok = !br->error_;
|
||||||
if (!ok) goto End;
|
if (!ok) goto End;
|
||||||
}
|
}
|
||||||
@ -1354,6 +1357,10 @@ int VP8LDecodeImage(VP8LDecoder* const dec) {
|
|||||||
// Sanity checks.
|
// Sanity checks.
|
||||||
if (dec == NULL) return 0;
|
if (dec == NULL) return 0;
|
||||||
|
|
||||||
|
dec->status_ = VP8_STATUS_BITSTREAM_ERROR;
|
||||||
|
assert(dec->hdr_.htree_groups_ != NULL);
|
||||||
|
assert(dec->hdr_.num_htree_groups_ > 0);
|
||||||
|
|
||||||
io = dec->io_;
|
io = dec->io_;
|
||||||
assert(io != NULL);
|
assert(io != NULL);
|
||||||
params = (WebPDecParams*)io->opaque;
|
params = (WebPDecParams*)io->opaque;
|
||||||
|
@ -9,6 +9,6 @@ libwebpdemuxinclude_HEADERS += ../webp/mux_types.h
|
|||||||
libwebpdemuxinclude_HEADERS += ../webp/types.h
|
libwebpdemuxinclude_HEADERS += ../webp/types.h
|
||||||
|
|
||||||
libwebpdemux_la_LIBADD = ../libwebp.la
|
libwebpdemux_la_LIBADD = ../libwebp.la
|
||||||
libwebpdemux_la_LDFLAGS = -no-undefined -version-info 1:1:0
|
libwebpdemux_la_LDFLAGS = -no-undefined -version-info 1:2:0
|
||||||
libwebpdemuxincludedir = $(includedir)/webp
|
libwebpdemuxincludedir = $(includedir)/webp
|
||||||
pkgconfig_DATA = libwebpdemux.pc
|
pkgconfig_DATA = libwebpdemux.pc
|
||||||
|
@ -25,7 +25,7 @@
|
|||||||
|
|
||||||
#define DMUX_MAJ_VERSION 0
|
#define DMUX_MAJ_VERSION 0
|
||||||
#define DMUX_MIN_VERSION 2
|
#define DMUX_MIN_VERSION 2
|
||||||
#define DMUX_REV_VERSION 1
|
#define DMUX_REV_VERSION 2
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
size_t start_; // start location of the data
|
size_t start_; // start location of the data
|
||||||
|
@ -38,6 +38,7 @@ libwebpdsp_avx2_la_CPPFLAGS = $(libwebpdsp_la_CPPFLAGS)
|
|||||||
libwebpdsp_avx2_la_CFLAGS = $(AM_CFLAGS) $(AVX2_FLAGS)
|
libwebpdsp_avx2_la_CFLAGS = $(AM_CFLAGS) $(AVX2_FLAGS)
|
||||||
|
|
||||||
libwebpdspdecode_sse2_la_SOURCES =
|
libwebpdspdecode_sse2_la_SOURCES =
|
||||||
|
libwebpdspdecode_sse2_la_SOURCES += alpha_processing_sse2.c
|
||||||
libwebpdspdecode_sse2_la_SOURCES += dec_sse2.c
|
libwebpdspdecode_sse2_la_SOURCES += dec_sse2.c
|
||||||
libwebpdspdecode_sse2_la_SOURCES += lossless_sse2.c
|
libwebpdspdecode_sse2_la_SOURCES += lossless_sse2.c
|
||||||
libwebpdspdecode_sse2_la_SOURCES += upsampling_sse2.c
|
libwebpdspdecode_sse2_la_SOURCES += upsampling_sse2.c
|
||||||
|
@ -284,15 +284,46 @@ static void ApplyAlphaMultiply_16b(uint8_t* rgba4444,
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int ExtractAlpha(const uint8_t* argb, int argb_stride,
|
||||||
|
int width, int height,
|
||||||
|
uint8_t* alpha, int alpha_stride) {
|
||||||
|
uint8_t alpha_mask = 0xff;
|
||||||
|
int i, j;
|
||||||
|
|
||||||
|
for (j = 0; j < height; ++j) {
|
||||||
|
for (i = 0; i < width; ++i) {
|
||||||
|
const uint8_t alpha_value = argb[4 * i];
|
||||||
|
alpha[i] = alpha_value;
|
||||||
|
alpha_mask &= alpha_value;
|
||||||
|
}
|
||||||
|
argb += argb_stride;
|
||||||
|
alpha += alpha_stride;
|
||||||
|
}
|
||||||
|
return (alpha_mask == 0xff);
|
||||||
|
}
|
||||||
|
|
||||||
void (*WebPApplyAlphaMultiply)(uint8_t*, int, int, int, int);
|
void (*WebPApplyAlphaMultiply)(uint8_t*, int, int, int, int);
|
||||||
void (*WebPApplyAlphaMultiply4444)(uint8_t*, int, int, int);
|
void (*WebPApplyAlphaMultiply4444)(uint8_t*, int, int, int);
|
||||||
|
int (*WebPExtractAlpha)(const uint8_t*, int, int, int, uint8_t*, int);
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
// Init function
|
// Init function
|
||||||
|
|
||||||
|
extern void WebPInitAlphaProcessingSSE2(void);
|
||||||
|
|
||||||
void WebPInitAlphaProcessing(void) {
|
void WebPInitAlphaProcessing(void) {
|
||||||
WebPMultARGBRow = MultARGBRow;
|
WebPMultARGBRow = MultARGBRow;
|
||||||
WebPMultRow = MultRow;
|
WebPMultRow = MultRow;
|
||||||
WebPApplyAlphaMultiply = ApplyAlphaMultiply;
|
WebPApplyAlphaMultiply = ApplyAlphaMultiply;
|
||||||
WebPApplyAlphaMultiply4444 = ApplyAlphaMultiply_16b;
|
WebPApplyAlphaMultiply4444 = ApplyAlphaMultiply_16b;
|
||||||
|
WebPExtractAlpha = ExtractAlpha;
|
||||||
|
|
||||||
|
// If defined, use CPUInfo() to overwrite some pointers with faster versions.
|
||||||
|
if (VP8GetCPUInfo != NULL) {
|
||||||
|
#if defined(WEBP_USE_SSE2)
|
||||||
|
if (VP8GetCPUInfo(kSSE2)) {
|
||||||
|
WebPInitAlphaProcessingSSE2();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
77
src/dsp/alpha_processing_sse2.c
Normal file
77
src/dsp/alpha_processing_sse2.c
Normal file
@ -0,0 +1,77 @@
|
|||||||
|
// Copyright 2014 Google Inc. All Rights Reserved.
|
||||||
|
//
|
||||||
|
// Use of this source code is governed by a BSD-style license
|
||||||
|
// that can be found in the COPYING file in the root of the source
|
||||||
|
// tree. An additional intellectual property rights grant can be found
|
||||||
|
// in the file PATENTS. All contributing project authors may
|
||||||
|
// be found in the AUTHORS file in the root of the source tree.
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// Utilities for processing transparent channel.
|
||||||
|
//
|
||||||
|
// Author: Skal (pascal.massimino@gmail.com)
|
||||||
|
|
||||||
|
#include "./dsp.h"
|
||||||
|
|
||||||
|
#if defined(WEBP_USE_SSE2)
|
||||||
|
#include <emmintrin.h>
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
static int ExtractAlpha(const uint8_t* argb, int argb_stride,
|
||||||
|
int width, int height,
|
||||||
|
uint8_t* alpha, int alpha_stride) {
|
||||||
|
// alpha_and stores an 'and' operation of all the alpha[] values. The final
|
||||||
|
// value is not 0xff if any of the alpha[] is not equal to 0xff.
|
||||||
|
uint32_t alpha_and = 0xff;
|
||||||
|
int i, j;
|
||||||
|
const __m128i a_mask = _mm_set1_epi32(0xffu); // to preserve alpha
|
||||||
|
const __m128i all_0xff = _mm_set_epi32(0, 0, ~0u, ~0u);
|
||||||
|
__m128i all_alphas = all_0xff;
|
||||||
|
|
||||||
|
// We must be able to access 3 extra bytes after the last written byte
|
||||||
|
// 'src[4 * width - 4]', because we don't know if alpha is the first or the
|
||||||
|
// last byte of the quadruplet.
|
||||||
|
const int limit = (width - 1) & ~7;
|
||||||
|
|
||||||
|
for (j = 0; j < height; ++j) {
|
||||||
|
const __m128i* src = (const __m128i*)argb;
|
||||||
|
for (i = 0; i < limit; i += 8) {
|
||||||
|
// load 32 argb bytes
|
||||||
|
const __m128i a0 = _mm_loadu_si128(src + 0);
|
||||||
|
const __m128i a1 = _mm_loadu_si128(src + 1);
|
||||||
|
const __m128i b0 = _mm_and_si128(a0, a_mask);
|
||||||
|
const __m128i b1 = _mm_and_si128(a1, a_mask);
|
||||||
|
const __m128i c0 = _mm_packs_epi32(b0, b1);
|
||||||
|
const __m128i d0 = _mm_packus_epi16(c0, c0);
|
||||||
|
// store
|
||||||
|
_mm_storel_epi64((__m128i*)&alpha[i], d0);
|
||||||
|
// accumulate eight alpha 'and' in parallel
|
||||||
|
all_alphas = _mm_and_si128(all_alphas, d0);
|
||||||
|
src += 2;
|
||||||
|
}
|
||||||
|
for (; i < width; ++i) {
|
||||||
|
const uint32_t alpha_value = argb[4 * i];
|
||||||
|
alpha[i] = alpha_value;
|
||||||
|
alpha_and &= alpha_value;
|
||||||
|
}
|
||||||
|
argb += argb_stride;
|
||||||
|
alpha += alpha_stride;
|
||||||
|
}
|
||||||
|
// Combine the eight alpha 'and' into a 8-bit mask.
|
||||||
|
alpha_and &= _mm_movemask_epi8(_mm_cmpeq_epi8(all_alphas, all_0xff));
|
||||||
|
return (alpha_and == 0xff);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // WEBP_USE_SSE2
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// Init function
|
||||||
|
|
||||||
|
extern void WebPInitAlphaProcessingSSE2(void);
|
||||||
|
|
||||||
|
void WebPInitAlphaProcessingSSE2(void) {
|
||||||
|
#if defined(WEBP_USE_SSE2)
|
||||||
|
WebPExtractAlpha = ExtractAlpha;
|
||||||
|
#endif
|
||||||
|
}
|
@ -57,7 +57,7 @@ static WEBP_INLINE uint64_t xgetbv(void) {
|
|||||||
}
|
}
|
||||||
#elif defined(_MSC_FULL_VER) && _MSC_FULL_VER >= 160040219 // >= VS2010 SP1
|
#elif defined(_MSC_FULL_VER) && _MSC_FULL_VER >= 160040219 // >= VS2010 SP1
|
||||||
#define xgetbv() _xgetbv(0)
|
#define xgetbv() _xgetbv(0)
|
||||||
#elif defined(_M_IX86)
|
#elif defined(_MSC_VER) && defined(_M_IX86)
|
||||||
static WEBP_INLINE uint64_t xgetbv(void) {
|
static WEBP_INLINE uint64_t xgetbv(void) {
|
||||||
uint32_t eax_, edx_;
|
uint32_t eax_, edx_;
|
||||||
__asm {
|
__asm {
|
||||||
@ -118,7 +118,7 @@ static int armCPUInfo(CPUFeature feature) {
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
VP8CPUInfo VP8GetCPUInfo = armCPUInfo;
|
VP8CPUInfo VP8GetCPUInfo = armCPUInfo;
|
||||||
#elif defined(__mips__)
|
#elif defined(WEBP_USE_MIPS32)
|
||||||
static int mipsCPUInfo(CPUFeature feature) {
|
static int mipsCPUInfo(CPUFeature feature) {
|
||||||
(void)feature;
|
(void)feature;
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -32,9 +32,19 @@ extern "C" {
|
|||||||
# define LOCAL_GCC_PREREQ(maj, min) \
|
# define LOCAL_GCC_PREREQ(maj, min) \
|
||||||
(LOCAL_GCC_VERSION >= (((maj) << 8) | (min)))
|
(LOCAL_GCC_VERSION >= (((maj) << 8) | (min)))
|
||||||
#else
|
#else
|
||||||
|
# define LOCAL_GCC_VERSION 0
|
||||||
# define LOCAL_GCC_PREREQ(maj, min) 0
|
# define LOCAL_GCC_PREREQ(maj, min) 0
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef __clang__
|
||||||
|
# define LOCAL_CLANG_VERSION ((__clang_major__ << 8) | __clang_minor__)
|
||||||
|
# define LOCAL_CLANG_PREREQ(maj, min) \
|
||||||
|
(LOCAL_CLANG_VERSION >= (((maj) << 8) | (min)))
|
||||||
|
#else
|
||||||
|
# define LOCAL_CLANG_VERSION 0
|
||||||
|
# define LOCAL_CLANG_PREREQ(maj, min) 0
|
||||||
|
#endif // __clang__
|
||||||
|
|
||||||
#if defined(_MSC_VER) && _MSC_VER > 1310 && \
|
#if defined(_MSC_VER) && _MSC_VER > 1310 && \
|
||||||
(defined(_M_X64) || defined(_M_IX86))
|
(defined(_M_X64) || defined(_M_IX86))
|
||||||
#define WEBP_MSC_SSE2 // Visual C++ SSE2 targets
|
#define WEBP_MSC_SSE2 // Visual C++ SSE2 targets
|
||||||
@ -60,8 +70,11 @@ extern "C" {
|
|||||||
#define WEBP_USE_NEON
|
#define WEBP_USE_NEON
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(__mips__)
|
#if defined(__mips__) && !defined(__mips64) && (__mips_isa_rev < 6)
|
||||||
#define WEBP_USE_MIPS32
|
#define WEBP_USE_MIPS32
|
||||||
|
#if (__mips_isa_rev >= 2)
|
||||||
|
#define WEBP_USE_MIPS32_R2
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
@ -244,6 +257,13 @@ extern void (*WebPApplyAlphaMultiply)(
|
|||||||
extern void (*WebPApplyAlphaMultiply4444)(
|
extern void (*WebPApplyAlphaMultiply4444)(
|
||||||
uint8_t* rgba4444, int w, int h, int stride);
|
uint8_t* rgba4444, int w, int h, int stride);
|
||||||
|
|
||||||
|
// Extract the alpha values from 32b values in argb[] and pack them into alpha[]
|
||||||
|
// (this is the opposite of WebPDispatchAlpha).
|
||||||
|
// Returns true if there's only trivial 0xff alpha values.
|
||||||
|
extern int (*WebPExtractAlpha)(const uint8_t* argb, int argb_stride,
|
||||||
|
int width, int height,
|
||||||
|
uint8_t* alpha, int alpha_stride);
|
||||||
|
|
||||||
// Pre-Multiply operation transforms x into x * A / 255 (where x=Y,R,G or B).
|
// Pre-Multiply operation transforms x into x * A / 255 (where x=Y,R,G or B).
|
||||||
// Un-Multiply operation transforms x into x * 255 / A.
|
// Un-Multiply operation transforms x into x * 255 / A.
|
||||||
|
|
||||||
|
@ -20,6 +20,10 @@
|
|||||||
#include "../enc/vp8enci.h"
|
#include "../enc/vp8enci.h"
|
||||||
#include "../enc/cost.h"
|
#include "../enc/cost.h"
|
||||||
|
|
||||||
|
#if defined(__GNUC__) && defined(__ANDROID__) && LOCAL_GCC_VERSION == 0x409
|
||||||
|
#define WORK_AROUND_GCC
|
||||||
|
#endif
|
||||||
|
|
||||||
static const int kC1 = 20091 + (1 << 16);
|
static const int kC1 = 20091 + (1 << 16);
|
||||||
static const int kC2 = 35468;
|
static const int kC2 = 35468;
|
||||||
|
|
||||||
@ -641,6 +645,7 @@ int VP8GetResidualCostMIPS32(int ctx0, const VP8Residual* const res) {
|
|||||||
GET_SSE_INNER(C, C + 1, C + 2, C + 3) \
|
GET_SSE_INNER(C, C + 1, C + 2, C + 3) \
|
||||||
GET_SSE_INNER(D, D + 1, D + 2, D + 3)
|
GET_SSE_INNER(D, D + 1, D + 2, D + 3)
|
||||||
|
|
||||||
|
#if !defined(WORK_AROUND_GCC)
|
||||||
static int SSE16x16(const uint8_t* a, const uint8_t* b) {
|
static int SSE16x16(const uint8_t* a, const uint8_t* b) {
|
||||||
int count;
|
int count;
|
||||||
int temp0, temp1, temp2, temp3, temp4, temp5, temp6, temp7;
|
int temp0, temp1, temp2, temp3, temp4, temp5, temp6, temp7;
|
||||||
@ -742,6 +747,8 @@ static int SSE4x4(const uint8_t* a, const uint8_t* b) {
|
|||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif // WORK_AROUND_GCC
|
||||||
|
|
||||||
#undef GET_SSE_MIPS32
|
#undef GET_SSE_MIPS32
|
||||||
#undef GET_SSE_MIPS32_INNER
|
#undef GET_SSE_MIPS32_INNER
|
||||||
|
|
||||||
@ -759,9 +766,11 @@ void VP8EncDspInitMIPS32(void) {
|
|||||||
VP8TDisto4x4 = Disto4x4;
|
VP8TDisto4x4 = Disto4x4;
|
||||||
VP8TDisto16x16 = Disto16x16;
|
VP8TDisto16x16 = Disto16x16;
|
||||||
VP8FTransform = FTransform;
|
VP8FTransform = FTransform;
|
||||||
|
#if !defined(WORK_AROUND_GCC)
|
||||||
VP8SSE16x16 = SSE16x16;
|
VP8SSE16x16 = SSE16x16;
|
||||||
VP8SSE8x8 = SSE8x8;
|
VP8SSE8x8 = SSE8x8;
|
||||||
VP8SSE16x8 = SSE16x8;
|
VP8SSE16x8 = SSE16x8;
|
||||||
VP8SSE4x4 = SSE4x4;
|
VP8SSE4x4 = SSE4x4;
|
||||||
|
#endif
|
||||||
#endif // WEBP_USE_MIPS32
|
#endif // WEBP_USE_MIPS32
|
||||||
}
|
}
|
||||||
|
@ -253,7 +253,7 @@ static void ITransform(const uint8_t* ref,
|
|||||||
|
|
||||||
// Load all 4x4 pixels into a single uint8x16_t variable.
|
// Load all 4x4 pixels into a single uint8x16_t variable.
|
||||||
static uint8x16_t Load4x4(const uint8_t* src) {
|
static uint8x16_t Load4x4(const uint8_t* src) {
|
||||||
uint32x4_t out = { 0, 0, 0, 0 };
|
uint32x4_t out = vdupq_n_u32(0);
|
||||||
out = vld1q_lane_u32((const uint32_t*)(src + 0 * BPS), out, 0);
|
out = vld1q_lane_u32((const uint32_t*)(src + 0 * BPS), out, 0);
|
||||||
out = vld1q_lane_u32((const uint32_t*)(src + 1 * BPS), out, 1);
|
out = vld1q_lane_u32((const uint32_t*)(src + 1 * BPS), out, 1);
|
||||||
out = vld1q_lane_u32((const uint32_t*)(src + 2 * BPS), out, 2);
|
out = vld1q_lane_u32((const uint32_t*)(src + 2 * BPS), out, 2);
|
||||||
@ -929,7 +929,7 @@ static int SumToInt(uint32x4_t sum) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int SSE16x16(const uint8_t* a, const uint8_t* b) {
|
static int SSE16x16(const uint8_t* a, const uint8_t* b) {
|
||||||
uint32x4_t sum = { 0, 0, 0, 0 };
|
uint32x4_t sum = vdupq_n_u32(0);
|
||||||
int y;
|
int y;
|
||||||
for (y = 0; y < 16; ++y) {
|
for (y = 0; y < 16; ++y) {
|
||||||
AccumulateSSE16(a + y * BPS, b + y * BPS, &sum);
|
AccumulateSSE16(a + y * BPS, b + y * BPS, &sum);
|
||||||
@ -938,7 +938,7 @@ static int SSE16x16(const uint8_t* a, const uint8_t* b) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int SSE16x8(const uint8_t* a, const uint8_t* b) {
|
static int SSE16x8(const uint8_t* a, const uint8_t* b) {
|
||||||
uint32x4_t sum = { 0, 0, 0, 0 };
|
uint32x4_t sum = vdupq_n_u32(0);
|
||||||
int y;
|
int y;
|
||||||
for (y = 0; y < 8; ++y) {
|
for (y = 0; y < 8; ++y) {
|
||||||
AccumulateSSE16(a + y * BPS, b + y * BPS, &sum);
|
AccumulateSSE16(a + y * BPS, b + y * BPS, &sum);
|
||||||
@ -947,7 +947,7 @@ static int SSE16x8(const uint8_t* a, const uint8_t* b) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int SSE8x8(const uint8_t* a, const uint8_t* b) {
|
static int SSE8x8(const uint8_t* a, const uint8_t* b) {
|
||||||
uint32x4_t sum = { 0, 0, 0, 0 };
|
uint32x4_t sum = vdupq_n_u32(0);
|
||||||
int y;
|
int y;
|
||||||
for (y = 0; y < 8; ++y) {
|
for (y = 0; y < 8; ++y) {
|
||||||
const uint8x8_t a0 = vld1_u8(a + y * BPS);
|
const uint8x8_t a0 = vld1_u8(a + y * BPS);
|
||||||
@ -970,9 +970,8 @@ static int SSE4x4(const uint8_t* a, const uint8_t* b) {
|
|||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
// Compilation with gcc-4.6.x is problematic for now and vtbl? are unavailable
|
// Compilation with gcc-4.6.x is problematic for now.
|
||||||
// in iOS/arm64 builds. Disable this function in those cases.
|
#if !defined(WORK_AROUND_GCC)
|
||||||
#if !(defined(WORK_AROUND_GCC) || defined(__aarch64__))
|
|
||||||
|
|
||||||
static int16x8_t Quantize(int16_t* const in,
|
static int16x8_t Quantize(int16_t* const in,
|
||||||
const VP8Matrix* const mtx, int offset) {
|
const VP8Matrix* const mtx, int offset) {
|
||||||
@ -1002,27 +1001,44 @@ static int16x8_t Quantize(int16_t* const in,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static const uint8_t kShuffles[4][8] = {
|
static const uint8_t kShuffles[4][8] = {
|
||||||
{ 0, 1, 2, 3, 8, 9, 16, 17 },
|
{ 0, 1, 2, 3, 8, 9, 16, 17 },
|
||||||
{ 10, 11, 4, 5, 6, 7, 12, 13 },
|
{ 10, 11, 4, 5, 6, 7, 12, 13 },
|
||||||
{ 18, 19, 24, 25, 26, 27, 20, 21 },
|
{ 18, 19, 24, 25, 26, 27, 20, 21 },
|
||||||
{ 14, 15, 22, 23, 28, 29, 30, 31 }
|
{ 14, 15, 22, 23, 28, 29, 30, 31 }
|
||||||
};
|
};
|
||||||
|
|
||||||
static int QuantizeBlock(int16_t in[16], int16_t out[16],
|
static int QuantizeBlock(int16_t in[16], int16_t out[16],
|
||||||
const VP8Matrix* const mtx) {
|
const VP8Matrix* const mtx) {
|
||||||
const int16x8_t out0 = Quantize(in, mtx, 0);
|
const int16x8_t out0 = Quantize(in, mtx, 0);
|
||||||
const int16x8_t out1 = Quantize(in, mtx, 8);
|
const int16x8_t out1 = Quantize(in, mtx, 8);
|
||||||
|
uint8x8x4_t shuffles;
|
||||||
|
// vtbl4_u8 is marked unavailable for iOS arm64, use wider versions there.
|
||||||
|
#if defined(__APPLE__) && defined(__aarch64__)
|
||||||
|
uint8x16x2_t all_out;
|
||||||
|
INIT_VECTOR2(all_out, vreinterpretq_u8_s16(out0), vreinterpretq_u8_s16(out1));
|
||||||
|
INIT_VECTOR4(shuffles,
|
||||||
|
vtbl2q_u8(all_out, vld1_u8(kShuffles[0])),
|
||||||
|
vtbl2q_u8(all_out, vld1_u8(kShuffles[1])),
|
||||||
|
vtbl2q_u8(all_out, vld1_u8(kShuffles[2])),
|
||||||
|
vtbl2q_u8(all_out, vld1_u8(kShuffles[3])));
|
||||||
|
#else
|
||||||
uint8x8x4_t all_out;
|
uint8x8x4_t all_out;
|
||||||
INIT_VECTOR4(all_out,
|
INIT_VECTOR4(all_out,
|
||||||
vreinterpret_u8_s16(vget_low_s16(out0)),
|
vreinterpret_u8_s16(vget_low_s16(out0)),
|
||||||
vreinterpret_u8_s16(vget_high_s16(out0)),
|
vreinterpret_u8_s16(vget_high_s16(out0)),
|
||||||
vreinterpret_u8_s16(vget_low_s16(out1)),
|
vreinterpret_u8_s16(vget_low_s16(out1)),
|
||||||
vreinterpret_u8_s16(vget_high_s16(out1)));
|
vreinterpret_u8_s16(vget_high_s16(out1)));
|
||||||
|
INIT_VECTOR4(shuffles,
|
||||||
|
vtbl4_u8(all_out, vld1_u8(kShuffles[0])),
|
||||||
|
vtbl4_u8(all_out, vld1_u8(kShuffles[1])),
|
||||||
|
vtbl4_u8(all_out, vld1_u8(kShuffles[2])),
|
||||||
|
vtbl4_u8(all_out, vld1_u8(kShuffles[3])));
|
||||||
|
#endif
|
||||||
// Zigzag reordering
|
// Zigzag reordering
|
||||||
vst1_u8((uint8_t*)(out + 0), vtbl4_u8(all_out, vld1_u8(kShuffles[0])));
|
vst1_u8((uint8_t*)(out + 0), shuffles.val[0]);
|
||||||
vst1_u8((uint8_t*)(out + 4), vtbl4_u8(all_out, vld1_u8(kShuffles[1])));
|
vst1_u8((uint8_t*)(out + 4), shuffles.val[1]);
|
||||||
vst1_u8((uint8_t*)(out + 8), vtbl4_u8(all_out, vld1_u8(kShuffles[2])));
|
vst1_u8((uint8_t*)(out + 8), shuffles.val[2]);
|
||||||
vst1_u8((uint8_t*)(out + 12), vtbl4_u8(all_out, vld1_u8(kShuffles[3])));
|
vst1_u8((uint8_t*)(out + 12), shuffles.val[3]);
|
||||||
// test zeros
|
// test zeros
|
||||||
if (*(uint64_t*)(out + 0) != 0) return 1;
|
if (*(uint64_t*)(out + 0) != 0) return 1;
|
||||||
if (*(uint64_t*)(out + 4) != 0) return 1;
|
if (*(uint64_t*)(out + 4) != 0) return 1;
|
||||||
@ -1031,7 +1047,7 @@ static int QuantizeBlock(int16_t in[16], int16_t out[16],
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // !WORK_AROUND_GCC && !__aarch64__
|
#endif // !WORK_AROUND_GCC
|
||||||
|
|
||||||
#endif // WEBP_USE_NEON
|
#endif // WEBP_USE_NEON
|
||||||
|
|
||||||
@ -1054,7 +1070,7 @@ void VP8EncDspInitNEON(void) {
|
|||||||
VP8SSE16x8 = SSE16x8;
|
VP8SSE16x8 = SSE16x8;
|
||||||
VP8SSE8x8 = SSE8x8;
|
VP8SSE8x8 = SSE8x8;
|
||||||
VP8SSE4x4 = SSE4x4;
|
VP8SSE4x4 = SSE4x4;
|
||||||
#if !(defined(WORK_AROUND_GCC) || defined(__aarch64__))
|
#if !defined(WORK_AROUND_GCC)
|
||||||
VP8EncQuantizeBlock = QuantizeBlock;
|
VP8EncQuantizeBlock = QuantizeBlock;
|
||||||
#endif
|
#endif
|
||||||
#endif // WEBP_USE_NEON
|
#endif // WEBP_USE_NEON
|
||||||
|
@ -450,12 +450,21 @@ static WEBP_INLINE uint32_t ClampedAddSubtractHalf(uint32_t c0, uint32_t c1,
|
|||||||
return ((uint32_t)a << 24) | (r << 16) | (g << 8) | b;
|
return ((uint32_t)a << 24) | (r << 16) | (g << 8) | b;
|
||||||
}
|
}
|
||||||
|
|
||||||
static WEBP_INLINE int Sub3(int a, int b, int c) {
|
// gcc-4.9 on ARM generates incorrect code in Select() when Sub3() is inlined.
|
||||||
|
#if defined(__arm__) && LOCAL_GCC_VERSION == 0x409
|
||||||
|
# define LOCAL_INLINE __attribute__ ((noinline))
|
||||||
|
#else
|
||||||
|
# define LOCAL_INLINE WEBP_INLINE
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static LOCAL_INLINE int Sub3(int a, int b, int c) {
|
||||||
const int pb = b - c;
|
const int pb = b - c;
|
||||||
const int pa = a - c;
|
const int pa = a - c;
|
||||||
return abs(pb) - abs(pa);
|
return abs(pb) - abs(pa);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#undef LOCAL_INLINE
|
||||||
|
|
||||||
static WEBP_INLINE uint32_t Select(uint32_t a, uint32_t b, uint32_t c) {
|
static WEBP_INLINE uint32_t Select(uint32_t a, uint32_t b, uint32_t c) {
|
||||||
const int pa_minus_pb =
|
const int pa_minus_pb =
|
||||||
Sub3((a >> 24) , (b >> 24) , (c >> 24) ) +
|
Sub3((a >> 24) , (b >> 24) , (c >> 24) ) +
|
||||||
@ -1169,7 +1178,7 @@ static void ColorSpaceInverseTransform(const VP8LTransform* const transform,
|
|||||||
data += remaining_width;
|
data += remaining_width;
|
||||||
}
|
}
|
||||||
++y;
|
++y;
|
||||||
if ((y & mask) == 0) pred_row += tiles_per_row;;
|
if ((y & mask) == 0) pred_row += tiles_per_row;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -56,24 +56,20 @@ extern VP8LConvertFunc VP8LConvertBGRAToRGB565;
|
|||||||
extern VP8LConvertFunc VP8LConvertBGRAToBGR;
|
extern VP8LConvertFunc VP8LConvertBGRAToBGR;
|
||||||
|
|
||||||
// Expose some C-only fallback functions
|
// Expose some C-only fallback functions
|
||||||
extern void VP8LTransformColor_C(const VP8LMultipliers* const m,
|
void VP8LTransformColor_C(const VP8LMultipliers* const m,
|
||||||
|
uint32_t* data, int num_pixels);
|
||||||
|
void VP8LTransformColorInverse_C(const VP8LMultipliers* const m,
|
||||||
uint32_t* data, int num_pixels);
|
uint32_t* data, int num_pixels);
|
||||||
extern void VP8LTransformColorInverse_C(const VP8LMultipliers* const m,
|
|
||||||
uint32_t* data, int num_pixels);
|
|
||||||
|
|
||||||
extern void VP8LConvertBGRAToRGB_C(const uint32_t* src,
|
void VP8LConvertBGRAToRGB_C(const uint32_t* src, int num_pixels, uint8_t* dst);
|
||||||
int num_pixels, uint8_t* dst);
|
void VP8LConvertBGRAToRGBA_C(const uint32_t* src, int num_pixels, uint8_t* dst);
|
||||||
extern void VP8LConvertBGRAToRGBA_C(const uint32_t* src,
|
void VP8LConvertBGRAToRGBA4444_C(const uint32_t* src,
|
||||||
int num_pixels, uint8_t* dst);
|
int num_pixels, uint8_t* dst);
|
||||||
extern void VP8LConvertBGRAToRGBA4444_C(const uint32_t* src,
|
void VP8LConvertBGRAToRGB565_C(const uint32_t* src,
|
||||||
int num_pixels, uint8_t* dst);
|
int num_pixels, uint8_t* dst);
|
||||||
extern void VP8LConvertBGRAToRGB565_C(const uint32_t* src,
|
void VP8LConvertBGRAToBGR_C(const uint32_t* src, int num_pixels, uint8_t* dst);
|
||||||
int num_pixels, uint8_t* dst);
|
void VP8LSubtractGreenFromBlueAndRed_C(uint32_t* argb_data, int num_pixels);
|
||||||
extern void VP8LConvertBGRAToBGR_C(const uint32_t* src,
|
void VP8LAddGreenToBlueAndRed_C(uint32_t* data, int num_pixels);
|
||||||
int num_pixels, uint8_t* dst);
|
|
||||||
extern void VP8LSubtractGreenFromBlueAndRed_C(uint32_t* argb_data,
|
|
||||||
int num_pixels);
|
|
||||||
extern void VP8LAddGreenToBlueAndRed_C(uint32_t* data, int num_pixels);
|
|
||||||
|
|
||||||
// Must be called before calling any of the above methods.
|
// Must be called before calling any of the above methods.
|
||||||
void VP8LDspInit(void);
|
void VP8LDspInit(void);
|
||||||
|
@ -47,12 +47,11 @@
|
|||||||
|
|
||||||
static int EncodeLossless(const uint8_t* const data, int width, int height,
|
static int EncodeLossless(const uint8_t* const data, int width, int height,
|
||||||
int effort_level, // in [0..6] range
|
int effort_level, // in [0..6] range
|
||||||
VP8BitWriter* const bw,
|
VP8LBitWriter* const bw,
|
||||||
WebPAuxStats* const stats) {
|
WebPAuxStats* const stats) {
|
||||||
int ok = 0;
|
int ok = 0;
|
||||||
WebPConfig config;
|
WebPConfig config;
|
||||||
WebPPicture picture;
|
WebPPicture picture;
|
||||||
VP8LBitWriter tmp_bw;
|
|
||||||
|
|
||||||
WebPPictureInit(&picture);
|
WebPPictureInit(&picture);
|
||||||
picture.width = width;
|
picture.width = width;
|
||||||
@ -84,16 +83,15 @@ static int EncodeLossless(const uint8_t* const data, int width, int height,
|
|||||||
config.quality = 8.f * effort_level;
|
config.quality = 8.f * effort_level;
|
||||||
assert(config.quality >= 0 && config.quality <= 100.f);
|
assert(config.quality >= 0 && config.quality <= 100.f);
|
||||||
|
|
||||||
ok = VP8LBitWriterInit(&tmp_bw, (width * height) >> 3);
|
ok = (VP8LEncodeStream(&config, &picture, bw) == VP8_ENC_OK);
|
||||||
ok = ok && (VP8LEncodeStream(&config, &picture, &tmp_bw) == VP8_ENC_OK);
|
|
||||||
WebPPictureFree(&picture);
|
WebPPictureFree(&picture);
|
||||||
if (ok) {
|
ok = ok && !bw->error_;
|
||||||
const uint8_t* const buffer = VP8LBitWriterFinish(&tmp_bw);
|
if (!ok) {
|
||||||
const size_t buffer_size = VP8LBitWriterNumBytes(&tmp_bw);
|
VP8LBitWriterDestroy(bw);
|
||||||
VP8BitWriterAppend(bw, buffer, buffer_size);
|
return 0;
|
||||||
}
|
}
|
||||||
VP8LBitWriterDestroy(&tmp_bw);
|
return 1;
|
||||||
return ok && !bw->error_;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
@ -115,8 +113,10 @@ static int EncodeAlphaInternal(const uint8_t* const data, int width, int height,
|
|||||||
const uint8_t* alpha_src;
|
const uint8_t* alpha_src;
|
||||||
WebPFilterFunc filter_func;
|
WebPFilterFunc filter_func;
|
||||||
uint8_t header;
|
uint8_t header;
|
||||||
size_t expected_size;
|
|
||||||
const size_t data_size = width * height;
|
const size_t data_size = width * height;
|
||||||
|
const uint8_t* output = NULL;
|
||||||
|
size_t output_size = 0;
|
||||||
|
VP8LBitWriter tmp_bw;
|
||||||
|
|
||||||
assert((uint64_t)data_size == (uint64_t)width * height); // as per spec
|
assert((uint64_t)data_size == (uint64_t)width * height); // as per spec
|
||||||
assert(filter >= 0 && filter < WEBP_FILTER_LAST);
|
assert(filter >= 0 && filter < WEBP_FILTER_LAST);
|
||||||
@ -125,15 +125,6 @@ static int EncodeAlphaInternal(const uint8_t* const data, int width, int height,
|
|||||||
assert(sizeof(header) == ALPHA_HEADER_LEN);
|
assert(sizeof(header) == ALPHA_HEADER_LEN);
|
||||||
// TODO(skal): have a common function and #define's to validate alpha params.
|
// TODO(skal): have a common function and #define's to validate alpha params.
|
||||||
|
|
||||||
expected_size =
|
|
||||||
(method == ALPHA_NO_COMPRESSION) ? (ALPHA_HEADER_LEN + data_size)
|
|
||||||
: (data_size >> 5);
|
|
||||||
header = method | (filter << 2);
|
|
||||||
if (reduce_levels) header |= ALPHA_PREPROCESSED_LEVELS << 4;
|
|
||||||
|
|
||||||
VP8BitWriterInit(&result->bw, expected_size);
|
|
||||||
VP8BitWriterAppend(&result->bw, &header, ALPHA_HEADER_LEN);
|
|
||||||
|
|
||||||
filter_func = WebPFilters[filter];
|
filter_func = WebPFilters[filter];
|
||||||
if (filter_func != NULL) {
|
if (filter_func != NULL) {
|
||||||
filter_func(data, width, height, width, tmp_alpha);
|
filter_func(data, width, height, width, tmp_alpha);
|
||||||
@ -142,14 +133,42 @@ static int EncodeAlphaInternal(const uint8_t* const data, int width, int height,
|
|||||||
alpha_src = data;
|
alpha_src = data;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (method == ALPHA_NO_COMPRESSION) {
|
if (method != ALPHA_NO_COMPRESSION) {
|
||||||
ok = VP8BitWriterAppend(&result->bw, alpha_src, width * height);
|
ok = VP8LBitWriterInit(&tmp_bw, data_size >> 3);
|
||||||
ok = ok && !result->bw.error_;
|
ok = ok && EncodeLossless(alpha_src, width, height, effort_level,
|
||||||
} else {
|
&tmp_bw, &result->stats);
|
||||||
ok = EncodeLossless(alpha_src, width, height, effort_level,
|
if (ok) {
|
||||||
&result->bw, &result->stats);
|
output = VP8LBitWriterFinish(&tmp_bw);
|
||||||
VP8BitWriterFinish(&result->bw);
|
output_size = VP8LBitWriterNumBytes(&tmp_bw);
|
||||||
|
if (output_size > data_size) {
|
||||||
|
// compressed size is larger than source! Revert to uncompressed mode.
|
||||||
|
method = ALPHA_NO_COMPRESSION;
|
||||||
|
VP8LBitWriterDestroy(&tmp_bw);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
VP8LBitWriterDestroy(&tmp_bw);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (method == ALPHA_NO_COMPRESSION) {
|
||||||
|
output = alpha_src;
|
||||||
|
output_size = data_size;
|
||||||
|
ok = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Emit final result.
|
||||||
|
header = method | (filter << 2);
|
||||||
|
if (reduce_levels) header |= ALPHA_PREPROCESSED_LEVELS << 4;
|
||||||
|
|
||||||
|
VP8BitWriterInit(&result->bw, ALPHA_HEADER_LEN + output_size);
|
||||||
|
ok = ok && VP8BitWriterAppend(&result->bw, &header, ALPHA_HEADER_LEN);
|
||||||
|
ok = ok && VP8BitWriterAppend(&result->bw, output, output_size);
|
||||||
|
|
||||||
|
if (method != ALPHA_NO_COMPRESSION) {
|
||||||
|
VP8LBitWriterDestroy(&tmp_bw);
|
||||||
|
}
|
||||||
|
ok = ok && !result->bw.error_;
|
||||||
result->score = VP8BitWriterSize(&result->bw);
|
result->score = VP8BitWriterSize(&result->bw);
|
||||||
return ok;
|
return ok;
|
||||||
}
|
}
|
||||||
|
@ -141,7 +141,11 @@ static void MergeHistograms(const VP8Histogram* const in,
|
|||||||
|
|
||||||
static void AssignSegments(VP8Encoder* const enc,
|
static void AssignSegments(VP8Encoder* const enc,
|
||||||
const int alphas[MAX_ALPHA + 1]) {
|
const int alphas[MAX_ALPHA + 1]) {
|
||||||
const int nb = enc->segment_hdr_.num_segments_;
|
// 'num_segments_' is previously validated and <= NUM_MB_SEGMENTS, but an
|
||||||
|
// explicit check is needed to avoid spurious warning about 'n + 1' exceeding
|
||||||
|
// array bounds of 'centers' with some compilers (noticed with gcc-4.9).
|
||||||
|
const int nb = (enc->segment_hdr_.num_segments_ < NUM_MB_SEGMENTS) ?
|
||||||
|
enc->segment_hdr_.num_segments_ : NUM_MB_SEGMENTS;
|
||||||
int centers[NUM_MB_SEGMENTS];
|
int centers[NUM_MB_SEGMENTS];
|
||||||
int weighted_average = 0;
|
int weighted_average = 0;
|
||||||
int map[MAX_ALPHA + 1];
|
int map[MAX_ALPHA + 1];
|
||||||
|
@ -111,7 +111,11 @@ int WebPValidateConfig(const WebPConfig* config) {
|
|||||||
return 0;
|
return 0;
|
||||||
if (config->show_compressed < 0 || config->show_compressed > 1)
|
if (config->show_compressed < 0 || config->show_compressed > 1)
|
||||||
return 0;
|
return 0;
|
||||||
|
#if WEBP_ENCODER_ABI_VERSION > 0x0204
|
||||||
|
if (config->preprocessing < 0 || config->preprocessing > 7)
|
||||||
|
#else
|
||||||
if (config->preprocessing < 0 || config->preprocessing > 3)
|
if (config->preprocessing < 0 || config->preprocessing > 3)
|
||||||
|
#endif
|
||||||
return 0;
|
return 0;
|
||||||
if (config->partitions < 0 || config->partitions > 3)
|
if (config->partitions < 0 || config->partitions > 3)
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -42,7 +42,7 @@ typedef void (*VP8SetResidualCoeffsFunc)(const int16_t* const coeffs,
|
|||||||
VP8Residual* const res);
|
VP8Residual* const res);
|
||||||
extern VP8SetResidualCoeffsFunc VP8SetResidualCoeffs;
|
extern VP8SetResidualCoeffsFunc VP8SetResidualCoeffs;
|
||||||
|
|
||||||
extern void VP8SetResidualCoeffsInit(void); // must be called first
|
void VP8SetResidualCoeffsInit(void); // must be called first
|
||||||
|
|
||||||
int VP8RecordCoeffs(int ctx, const VP8Residual* const res);
|
int VP8RecordCoeffs(int ctx, const VP8Residual* const res);
|
||||||
|
|
||||||
@ -59,7 +59,7 @@ static WEBP_INLINE int VP8BitCost(int bit, uint8_t proba) {
|
|||||||
typedef int (*VP8GetResidualCostFunc)(int ctx0, const VP8Residual* const res);
|
typedef int (*VP8GetResidualCostFunc)(int ctx0, const VP8Residual* const res);
|
||||||
extern VP8GetResidualCostFunc VP8GetResidualCost;
|
extern VP8GetResidualCostFunc VP8GetResidualCost;
|
||||||
|
|
||||||
extern void VP8GetResidualCostInit(void); // must be called first
|
void VP8GetResidualCostInit(void); // must be called first
|
||||||
|
|
||||||
// Level cost calculations
|
// Level cost calculations
|
||||||
extern const uint16_t VP8LevelCodes[MAX_VARIABLE_LEVEL][2];
|
extern const uint16_t VP8LevelCodes[MAX_VARIABLE_LEVEL][2];
|
||||||
|
@ -508,7 +508,7 @@ static void StoreSideInfo(const VP8EncIterator* const it) {
|
|||||||
}
|
}
|
||||||
case 7: *info = mb->alpha_; break;
|
case 7: *info = mb->alpha_; break;
|
||||||
default: *info = 0; break;
|
default: *info = 0; break;
|
||||||
};
|
}
|
||||||
}
|
}
|
||||||
#if SEGMENT_VISU // visualize segments and prediction modes
|
#if SEGMENT_VISU // visualize segments and prediction modes
|
||||||
SetBlock(it->yuv_out_ + Y_OFF, mb->segment_ * 64, 16);
|
SetBlock(it->yuv_out_ + Y_OFF, mb->segment_ * 64, 16);
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -30,7 +30,7 @@ extern "C" {
|
|||||||
// version numbers
|
// version numbers
|
||||||
#define ENC_MAJ_VERSION 0
|
#define ENC_MAJ_VERSION 0
|
||||||
#define ENC_MIN_VERSION 4
|
#define ENC_MIN_VERSION 4
|
||||||
#define ENC_REV_VERSION 1
|
#define ENC_REV_VERSION 2
|
||||||
|
|
||||||
// intra prediction modes
|
// intra prediction modes
|
||||||
enum { B_DC_PRED = 0, // 4x4 modes
|
enum { B_DC_PRED = 0, // 4x4 modes
|
||||||
@ -457,10 +457,10 @@ struct VP8Encoder {
|
|||||||
VP8MBInfo* mb_info_; // contextual macroblock infos (mb_w_ + 1)
|
VP8MBInfo* mb_info_; // contextual macroblock infos (mb_w_ + 1)
|
||||||
uint8_t* preds_; // predictions modes: (4*mb_w+1) * (4*mb_h+1)
|
uint8_t* preds_; // predictions modes: (4*mb_w+1) * (4*mb_h+1)
|
||||||
uint32_t* nz_; // non-zero bit context: mb_w+1
|
uint32_t* nz_; // non-zero bit context: mb_w+1
|
||||||
uint8_t *y_top_; // top luma samples.
|
uint8_t* y_top_; // top luma samples.
|
||||||
uint8_t *uv_top_; // top u/v samples.
|
uint8_t* uv_top_; // top u/v samples.
|
||||||
// U and V are packed into 16 bytes (8 U + 8 V)
|
// U and V are packed into 16 bytes (8 U + 8 V)
|
||||||
LFStats *lf_stats_; // autofilter stats (if NULL, autofilter is off)
|
LFStats* lf_stats_; // autofilter stats (if NULL, autofilter is off)
|
||||||
};
|
};
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
@ -571,7 +571,7 @@ int WebPPictureAllocYUVA(WebPPicture* const picture, int width, int height);
|
|||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
#if WEBP_ENCODER_ABI_VERSION <= 0x0202
|
#if WEBP_ENCODER_ABI_VERSION <= 0x0203
|
||||||
void WebPMemoryWriterClear(WebPMemoryWriter* writer);
|
void WebPMemoryWriterClear(WebPMemoryWriter* writer);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -328,16 +328,24 @@ int WebPEncode(const WebPConfig* config, WebPPicture* pic) {
|
|||||||
VP8Encoder* enc = NULL;
|
VP8Encoder* enc = NULL;
|
||||||
if (pic->y == NULL || pic->u == NULL || pic->v == NULL) {
|
if (pic->y == NULL || pic->u == NULL || pic->v == NULL) {
|
||||||
// Make sure we have YUVA samples.
|
// Make sure we have YUVA samples.
|
||||||
float dithering = 0.f;
|
if (config->preprocessing & 4) {
|
||||||
if (config->preprocessing & 2) {
|
#if WEBP_ENCODER_ABI_VERSION > 0x0204
|
||||||
const float x = config->quality / 100.f;
|
if (!WebPPictureSmartARGBToYUVA(pic)) {
|
||||||
const float x2 = x * x;
|
return 0;
|
||||||
// slowly decreasing from max dithering at low quality (q->0)
|
}
|
||||||
// to 0.5 dithering amplitude at high quality (q->100)
|
#endif
|
||||||
dithering = 1.0f + (0.5f - 1.0f) * x2 * x2;
|
} else {
|
||||||
}
|
float dithering = 0.f;
|
||||||
if (!WebPPictureARGBToYUVADithered(pic, WEBP_YUV420, dithering)) {
|
if (config->preprocessing & 2) {
|
||||||
return 0;
|
const float x = config->quality / 100.f;
|
||||||
|
const float x2 = x * x;
|
||||||
|
// slowly decreasing from max dithering at low quality (q->0)
|
||||||
|
// to 0.5 dithering amplitude at high quality (q->100)
|
||||||
|
dithering = 1.0f + (0.5f - 1.0f) * x2 * x2;
|
||||||
|
}
|
||||||
|
if (!WebPPictureARGBToYUVADithered(pic, WEBP_YUV420, dithering)) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -12,6 +12,6 @@ libwebpmuxinclude_HEADERS += ../webp/mux_types.h
|
|||||||
libwebpmuxinclude_HEADERS += ../webp/types.h
|
libwebpmuxinclude_HEADERS += ../webp/types.h
|
||||||
|
|
||||||
libwebpmux_la_LIBADD = ../libwebp.la
|
libwebpmux_la_LIBADD = ../libwebp.la
|
||||||
libwebpmux_la_LDFLAGS = -no-undefined -version-info 1:1:0
|
libwebpmux_la_LDFLAGS = -no-undefined -version-info 1:2:0
|
||||||
libwebpmuxincludedir = $(includedir)/webp
|
libwebpmuxincludedir = $(includedir)/webp
|
||||||
pkgconfig_DATA = libwebpmux.pc
|
pkgconfig_DATA = libwebpmux.pc
|
||||||
|
@ -28,7 +28,7 @@ extern "C" {
|
|||||||
|
|
||||||
#define MUX_MAJ_VERSION 0
|
#define MUX_MAJ_VERSION 0
|
||||||
#define MUX_MIN_VERSION 2
|
#define MUX_MIN_VERSION 2
|
||||||
#define MUX_REV_VERSION 1
|
#define MUX_REV_VERSION 2
|
||||||
|
|
||||||
// Chunk object.
|
// Chunk object.
|
||||||
typedef struct WebPChunk WebPChunk;
|
typedef struct WebPChunk WebPChunk;
|
||||||
|
@ -105,9 +105,7 @@ int32_t VP8GetSignedValue(VP8BitReader* const br, int bits) {
|
|||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
// VP8LBitReader
|
// VP8LBitReader
|
||||||
|
|
||||||
#define LBITS 64 // Number of bits prefetched.
|
#define VP8L_LOG8_WBITS 4 // Number of bytes needed to store VP8L_WBITS bits.
|
||||||
#define WBITS 32 // Minimum number of bytes needed after VP8LFillBitWindow.
|
|
||||||
#define LOG8_WBITS 4 // Number of bytes needed to store WBITS bits.
|
|
||||||
|
|
||||||
#if !defined(WEBP_FORCE_ALIGNED) && \
|
#if !defined(WEBP_FORCE_ALIGNED) && \
|
||||||
(defined(__arm__) || defined(_M_ARM) || defined(__aarch64__) || \
|
(defined(__arm__) || defined(_M_ARM) || defined(__aarch64__) || \
|
||||||
@ -151,16 +149,6 @@ void VP8LInitBitReader(VP8LBitReader* const br, const uint8_t* const start,
|
|||||||
br->buf_ = start;
|
br->buf_ = start;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Special version that assumes br->pos_ <= br_len_.
|
|
||||||
static int IsEndOfStreamSpecial(const VP8LBitReader* const br) {
|
|
||||||
assert(br->pos_ <= br->len_);
|
|
||||||
return br->pos_ == br->len_ && br->bit_pos_ >= LBITS;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int IsEndOfStream(const VP8LBitReader* const br) {
|
|
||||||
return (br->pos_ > br->len_) || IsEndOfStreamSpecial(br);
|
|
||||||
}
|
|
||||||
|
|
||||||
void VP8LBitReaderSetBuffer(VP8LBitReader* const br,
|
void VP8LBitReaderSetBuffer(VP8LBitReader* const br,
|
||||||
const uint8_t* const buf, size_t len) {
|
const uint8_t* const buf, size_t len) {
|
||||||
assert(br != NULL);
|
assert(br != NULL);
|
||||||
@ -168,38 +156,39 @@ void VP8LBitReaderSetBuffer(VP8LBitReader* const br,
|
|||||||
assert(len < 0xfffffff8u); // can't happen with a RIFF chunk.
|
assert(len < 0xfffffff8u); // can't happen with a RIFF chunk.
|
||||||
br->buf_ = buf;
|
br->buf_ = buf;
|
||||||
br->len_ = len;
|
br->len_ = len;
|
||||||
br->eos_ = IsEndOfStream(br);
|
// pos_ > len_ should be considered a param error.
|
||||||
|
br->error_ = (br->pos_ > br->len_);
|
||||||
|
br->eos_ = br->error_ || VP8LIsEndOfStream(br);
|
||||||
}
|
}
|
||||||
|
|
||||||
// If not at EOS, reload up to LBITS byte-by-byte
|
// If not at EOS, reload up to VP8L_LBITS byte-by-byte
|
||||||
static void ShiftBytes(VP8LBitReader* const br) {
|
static void ShiftBytes(VP8LBitReader* const br) {
|
||||||
while (br->bit_pos_ >= 8 && br->pos_ < br->len_) {
|
while (br->bit_pos_ >= 8 && br->pos_ < br->len_) {
|
||||||
br->val_ >>= 8;
|
br->val_ >>= 8;
|
||||||
br->val_ |= ((vp8l_val_t)br->buf_[br->pos_]) << (LBITS - 8);
|
br->val_ |= ((vp8l_val_t)br->buf_[br->pos_]) << (VP8L_LBITS - 8);
|
||||||
++br->pos_;
|
++br->pos_;
|
||||||
br->bit_pos_ -= 8;
|
br->bit_pos_ -= 8;
|
||||||
}
|
}
|
||||||
|
br->eos_ = VP8LIsEndOfStream(br);
|
||||||
}
|
}
|
||||||
|
|
||||||
void VP8LFillBitWindow(VP8LBitReader* const br) {
|
void VP8LDoFillBitWindow(VP8LBitReader* const br) {
|
||||||
if (br->bit_pos_ >= WBITS) {
|
assert(br->bit_pos_ >= VP8L_WBITS);
|
||||||
// TODO(jzern): given the fixed read size it may be possible to force
|
// TODO(jzern): given the fixed read size it may be possible to force
|
||||||
// alignment in this block.
|
// alignment in this block.
|
||||||
#if defined(VP8L_USE_UNALIGNED_LOAD)
|
#if defined(VP8L_USE_UNALIGNED_LOAD)
|
||||||
if (br->pos_ + sizeof(br->val_) < br->len_) {
|
if (br->pos_ + sizeof(br->val_) < br->len_) {
|
||||||
br->val_ >>= WBITS;
|
br->val_ >>= VP8L_WBITS;
|
||||||
br->bit_pos_ -= WBITS;
|
br->bit_pos_ -= VP8L_WBITS;
|
||||||
// The expression below needs a little-endian arch to work correctly.
|
// The expression below needs a little-endian arch to work correctly.
|
||||||
// This gives a large speedup for decoding speed.
|
// This gives a large speedup for decoding speed.
|
||||||
br->val_ |= (vp8l_val_t)*(const uint32_t*)(br->buf_ + br->pos_) <<
|
br->val_ |= (vp8l_val_t)*(const uint32_t*)(br->buf_ + br->pos_) <<
|
||||||
(LBITS - WBITS);
|
(VP8L_LBITS - VP8L_WBITS);
|
||||||
br->pos_ += LOG8_WBITS;
|
br->pos_ += VP8L_LOG8_WBITS;
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
#endif
|
|
||||||
ShiftBytes(br); // Slow path.
|
|
||||||
br->eos_ = IsEndOfStreamSpecial(br);
|
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
ShiftBytes(br); // Slow path.
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t VP8LReadBits(VP8LBitReader* const br, int n_bits) {
|
uint32_t VP8LReadBits(VP8LBitReader* const br, int n_bits) {
|
||||||
@ -210,8 +199,6 @@ uint32_t VP8LReadBits(VP8LBitReader* const br, int n_bits) {
|
|||||||
(uint32_t)(br->val_ >> br->bit_pos_) & kBitMask[n_bits];
|
(uint32_t)(br->val_ >> br->bit_pos_) & kBitMask[n_bits];
|
||||||
const int new_bits = br->bit_pos_ + n_bits;
|
const int new_bits = br->bit_pos_ + n_bits;
|
||||||
br->bit_pos_ = new_bits;
|
br->bit_pos_ = new_bits;
|
||||||
// If this read is going to cross the read buffer, set the eos flag.
|
|
||||||
br->eos_ = IsEndOfStreamSpecial(br);
|
|
||||||
ShiftBytes(br);
|
ShiftBytes(br);
|
||||||
return val;
|
return val;
|
||||||
} else {
|
} else {
|
||||||
|
@ -107,6 +107,9 @@ int32_t VP8GetSignedValue(VP8BitReader* const br, int num_bits);
|
|||||||
// maximum number of bits (inclusive) the bit-reader can handle:
|
// maximum number of bits (inclusive) the bit-reader can handle:
|
||||||
#define VP8L_MAX_NUM_BIT_READ 24
|
#define VP8L_MAX_NUM_BIT_READ 24
|
||||||
|
|
||||||
|
#define VP8L_LBITS 64 // Number of bits prefetched.
|
||||||
|
#define VP8L_WBITS 32 // Minimum number of bytes ready after VP8LFillBitWindow.
|
||||||
|
|
||||||
typedef uint64_t vp8l_val_t; // right now, this bit-reader can only use 64bit.
|
typedef uint64_t vp8l_val_t; // right now, this bit-reader can only use 64bit.
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
@ -138,14 +141,26 @@ static WEBP_INLINE uint32_t VP8LPrefetchBits(VP8LBitReader* const br) {
|
|||||||
return (uint32_t)(br->val_ >> br->bit_pos_);
|
return (uint32_t)(br->val_ >> br->bit_pos_);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Returns true if there was an attempt at reading bit past the end of
|
||||||
|
// the buffer. Doesn't set br->eos_ flag.
|
||||||
|
static WEBP_INLINE int VP8LIsEndOfStream(const VP8LBitReader* const br) {
|
||||||
|
assert(br->pos_ <= br->len_);
|
||||||
|
return (br->pos_ == br->len_) && (br->bit_pos_ > VP8L_LBITS);
|
||||||
|
}
|
||||||
|
|
||||||
// For jumping over a number of bits in the bit stream when accessed with
|
// For jumping over a number of bits in the bit stream when accessed with
|
||||||
// VP8LPrefetchBits and VP8LFillBitWindow.
|
// VP8LPrefetchBits and VP8LFillBitWindow.
|
||||||
static WEBP_INLINE void VP8LSetBitPos(VP8LBitReader* const br, int val) {
|
static WEBP_INLINE void VP8LSetBitPos(VP8LBitReader* const br, int val) {
|
||||||
br->bit_pos_ = val;
|
br->bit_pos_ = val;
|
||||||
|
br->eos_ = VP8LIsEndOfStream(br);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Advances the read buffer by 4 bytes to make room for reading next 32 bits.
|
// Advances the read buffer by 4 bytes to make room for reading next 32 bits.
|
||||||
void VP8LFillBitWindow(VP8LBitReader* const br);
|
// Speed critical, but infrequent part of the code can be non-inlined.
|
||||||
|
extern void VP8LDoFillBitWindow(VP8LBitReader* const br);
|
||||||
|
static WEBP_INLINE void VP8LFillBitWindow(VP8LBitReader* const br) {
|
||||||
|
if (br->bit_pos_ >= VP8L_WBITS) VP8LDoFillBitWindow(br);
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
} // extern "C"
|
} // extern "C"
|
||||||
|
@ -24,6 +24,7 @@
|
|||||||
#include <string.h> // memcpy
|
#include <string.h> // memcpy
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include "../dsp/dsp.h"
|
||||||
#include "./bit_reader.h"
|
#include "./bit_reader.h"
|
||||||
#include "./endian_inl.h"
|
#include "./endian_inl.h"
|
||||||
|
|
||||||
@ -63,7 +64,7 @@ static WEBP_INLINE void VP8LoadNewBytes(VP8BitReader* const br) {
|
|||||||
#if defined(WEBP_FORCE_ALIGNED)
|
#if defined(WEBP_FORCE_ALIGNED)
|
||||||
lbit_t in_bits;
|
lbit_t in_bits;
|
||||||
memcpy(&in_bits, br->buf_, sizeof(in_bits));
|
memcpy(&in_bits, br->buf_, sizeof(in_bits));
|
||||||
#elif defined(__mips__) // MIPS
|
#elif defined(WEBP_USE_MIPS32)
|
||||||
// This is needed because of un-aligned read.
|
// This is needed because of un-aligned read.
|
||||||
lbit_t in_bits;
|
lbit_t in_bits;
|
||||||
lbit_t* p_buf_ = (lbit_t*)br->buf_;
|
lbit_t* p_buf_ = (lbit_t*)br->buf_;
|
||||||
|
@ -52,7 +52,7 @@ static int BitWriterResize(VP8BitWriter* const bw, size_t extra_size) {
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void kFlush(VP8BitWriter* const bw) {
|
static void Flush(VP8BitWriter* const bw) {
|
||||||
const int s = 8 + bw->nb_bits_;
|
const int s = 8 + bw->nb_bits_;
|
||||||
const int32_t bits = bw->value_ >> s;
|
const int32_t bits = bw->value_ >> s;
|
||||||
assert(bw->nb_bits_ >= 0);
|
assert(bw->nb_bits_ >= 0);
|
||||||
@ -118,7 +118,7 @@ int VP8PutBit(VP8BitWriter* const bw, int bit, int prob) {
|
|||||||
bw->range_ = kNewRange[bw->range_];
|
bw->range_ = kNewRange[bw->range_];
|
||||||
bw->value_ <<= shift;
|
bw->value_ <<= shift;
|
||||||
bw->nb_bits_ += shift;
|
bw->nb_bits_ += shift;
|
||||||
if (bw->nb_bits_ > 0) kFlush(bw);
|
if (bw->nb_bits_ > 0) Flush(bw);
|
||||||
}
|
}
|
||||||
return bit;
|
return bit;
|
||||||
}
|
}
|
||||||
@ -135,7 +135,7 @@ int VP8PutBitUniform(VP8BitWriter* const bw, int bit) {
|
|||||||
bw->range_ = kNewRange[bw->range_];
|
bw->range_ = kNewRange[bw->range_];
|
||||||
bw->value_ <<= 1;
|
bw->value_ <<= 1;
|
||||||
bw->nb_bits_ += 1;
|
bw->nb_bits_ += 1;
|
||||||
if (bw->nb_bits_ > 0) kFlush(bw);
|
if (bw->nb_bits_ > 0) Flush(bw);
|
||||||
}
|
}
|
||||||
return bit;
|
return bit;
|
||||||
}
|
}
|
||||||
@ -173,14 +173,14 @@ int VP8BitWriterInit(VP8BitWriter* const bw, size_t expected_size) {
|
|||||||
uint8_t* VP8BitWriterFinish(VP8BitWriter* const bw) {
|
uint8_t* VP8BitWriterFinish(VP8BitWriter* const bw) {
|
||||||
VP8PutValue(bw, 0, 9 - bw->nb_bits_);
|
VP8PutValue(bw, 0, 9 - bw->nb_bits_);
|
||||||
bw->nb_bits_ = 0; // pad with zeroes
|
bw->nb_bits_ = 0; // pad with zeroes
|
||||||
kFlush(bw);
|
Flush(bw);
|
||||||
return bw->buf_;
|
return bw->buf_;
|
||||||
}
|
}
|
||||||
|
|
||||||
int VP8BitWriterAppend(VP8BitWriter* const bw,
|
int VP8BitWriterAppend(VP8BitWriter* const bw,
|
||||||
const uint8_t* data, size_t size) {
|
const uint8_t* data, size_t size) {
|
||||||
assert(data != NULL);
|
assert(data != NULL);
|
||||||
if (bw->nb_bits_ != -8) return 0; // kFlush() must have been called
|
if (bw->nb_bits_ != -8) return 0; // Flush() must have been called
|
||||||
if (!BitWriterResize(bw, size)) return 0;
|
if (!BitWriterResize(bw, size)) return 0;
|
||||||
memcpy(bw->buf_ + bw->pos_, data, size);
|
memcpy(bw->buf_ + bw->pos_, data, size);
|
||||||
bw->pos_ += size;
|
bw->pos_ += size;
|
||||||
|
@ -16,6 +16,7 @@
|
|||||||
#include "../webp/config.h"
|
#include "../webp/config.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include "../dsp/dsp.h"
|
||||||
#include "../webp/types.h"
|
#include "../webp/types.h"
|
||||||
|
|
||||||
// some endian fix (e.g.: mips-gcc doesn't define __BIG_ENDIAN__)
|
// some endian fix (e.g.: mips-gcc doesn't define __BIG_ENDIAN__)
|
||||||
@ -34,25 +35,13 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if !defined(HAVE_CONFIG_H)
|
#if !defined(HAVE_CONFIG_H)
|
||||||
#ifdef __GNUC__
|
|
||||||
# define LOCAL_GCC_VERSION ((__GNUC__ << 8) | __GNUC_MINOR__)
|
|
||||||
#else
|
|
||||||
# define LOCAL_GCC_VERSION 0
|
|
||||||
#endif // __GNUC__
|
|
||||||
|
|
||||||
#ifdef __clang__
|
|
||||||
# define LOCAL_CLANG_VERSION ((__clang_major__ << 8) | __clang_minor__)
|
|
||||||
#else
|
|
||||||
# define LOCAL_CLANG_VERSION 0
|
|
||||||
#endif // __clang__
|
|
||||||
|
|
||||||
// clang-3.3 and gcc-4.3 have builtin functions for swap32/swap64
|
// clang-3.3 and gcc-4.3 have builtin functions for swap32/swap64
|
||||||
#if LOCAL_GCC_VERSION >= 0x403 || LOCAL_CLANG_VERSION >= 0x303
|
#if LOCAL_GCC_PREREQ(4,3) || LOCAL_CLANG_PREREQ(3,3)
|
||||||
#define HAVE_BUILTIN_BSWAP32
|
#define HAVE_BUILTIN_BSWAP32
|
||||||
#define HAVE_BUILTIN_BSWAP64
|
#define HAVE_BUILTIN_BSWAP64
|
||||||
#endif
|
#endif
|
||||||
// clang-3.3 and gcc-4.8 have a builtin function for swap16
|
// clang-3.3 and gcc-4.8 have a builtin function for swap16
|
||||||
#if LOCAL_GCC_VERSION >= 0x408 || LOCAL_CLANG_VERSION >= 0x303
|
#if LOCAL_GCC_PREREQ(4,8) || LOCAL_CLANG_PREREQ(3,3)
|
||||||
#define HAVE_BUILTIN_BSWAP16
|
#define HAVE_BUILTIN_BSWAP16
|
||||||
#endif
|
#endif
|
||||||
#endif // !HAVE_CONFIG_H
|
#endif // !HAVE_CONFIG_H
|
||||||
@ -69,7 +58,16 @@ static WEBP_INLINE uint16_t BSwap16(uint16_t x) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static WEBP_INLINE uint32_t BSwap32(uint32_t x) {
|
static WEBP_INLINE uint32_t BSwap32(uint32_t x) {
|
||||||
#if defined(HAVE_BUILTIN_BSWAP32)
|
#if defined(WEBP_USE_MIPS32_R2)
|
||||||
|
uint32_t ret;
|
||||||
|
__asm__ volatile (
|
||||||
|
"wsbh %[ret], %[x] \n\t"
|
||||||
|
"rotr %[ret], %[ret], 16 \n\t"
|
||||||
|
: [ret]"=r"(ret)
|
||||||
|
: [x]"r"(x)
|
||||||
|
);
|
||||||
|
return ret;
|
||||||
|
#elif defined(HAVE_BUILTIN_BSWAP32)
|
||||||
return __builtin_bswap32(x);
|
return __builtin_bswap32(x);
|
||||||
#elif defined(__i386__) || defined(__x86_64__)
|
#elif defined(__i386__) || defined(__x86_64__)
|
||||||
uint32_t swapped_bytes;
|
uint32_t swapped_bytes;
|
||||||
|
@ -32,10 +32,10 @@
|
|||||||
#define DSIZE 4 // dithering size (must be a power of two)
|
#define DSIZE 4 // dithering size (must be a power of two)
|
||||||
// cf. http://en.wikipedia.org/wiki/Ordered_dithering
|
// cf. http://en.wikipedia.org/wiki/Ordered_dithering
|
||||||
static const uint8_t kOrderedDither[DSIZE][DSIZE] = {
|
static const uint8_t kOrderedDither[DSIZE][DSIZE] = {
|
||||||
{ 0, 8, 2, 10 }, // coefficients are in DFIX fixed-point precision
|
{ 0, 8, 2, 10 }, // coefficients are in DFIX fixed-point precision
|
||||||
{ 12, 4, 14, 6 },
|
{ 12, 4, 14, 6 },
|
||||||
{ 3, 11, 1, 9 },
|
{ 3, 11, 1, 9 },
|
||||||
{ 15, 7, 13, 5 }
|
{ 15, 7, 13, 5 }
|
||||||
};
|
};
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
@ -155,9 +155,9 @@ static void SubMem(void* ptr) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#else
|
#else
|
||||||
#define Increment(v) do {} while(0)
|
#define Increment(v) do {} while (0)
|
||||||
#define AddMem(p, s) do {} while(0)
|
#define AddMem(p, s) do {} while (0)
|
||||||
#define SubMem(p) do {} while(0)
|
#define SubMem(p) do {} while (0)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Returns 0 in case of overflow of nmemb * size.
|
// Returns 0 in case of overflow of nmemb * size.
|
||||||
|
@ -444,16 +444,20 @@ struct WebPDecoderOptions {
|
|||||||
int dithering_strength; // dithering strength (0=Off, 100=full)
|
int dithering_strength; // dithering strength (0=Off, 100=full)
|
||||||
#if WEBP_DECODER_ABI_VERSION > 0x0203
|
#if WEBP_DECODER_ABI_VERSION > 0x0203
|
||||||
int flip; // flip output vertically
|
int flip; // flip output vertically
|
||||||
|
#endif
|
||||||
|
#if WEBP_DECODER_ABI_VERSION > 0x0204
|
||||||
int alpha_dithering_strength; // alpha dithering strength in [0..100]
|
int alpha_dithering_strength; // alpha dithering strength in [0..100]
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Unused for now:
|
// Unused for now:
|
||||||
int force_rotation; // forced rotation (to be applied _last_)
|
int force_rotation; // forced rotation (to be applied _last_)
|
||||||
int no_enhancement; // if true, discard enhancement layer
|
int no_enhancement; // if true, discard enhancement layer
|
||||||
#if WEBP_DECODER_ABI_VERSION > 0x0203
|
#if WEBP_DECODER_ABI_VERSION < 0x0203
|
||||||
uint32_t pad[3]; // padding for later use
|
|
||||||
#else
|
|
||||||
uint32_t pad[5]; // padding for later use
|
uint32_t pad[5]; // padding for later use
|
||||||
|
#elif WEBP_DECODER_ABI_VERSION < 0x0204
|
||||||
|
uint32_t pad[4]; // padding for later use
|
||||||
|
#else
|
||||||
|
uint32_t pad[3]; // padding for later use
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -231,14 +231,14 @@ struct WebPMemoryWriter {
|
|||||||
// The following must be called first before any use.
|
// The following must be called first before any use.
|
||||||
WEBP_EXTERN(void) WebPMemoryWriterInit(WebPMemoryWriter* writer);
|
WEBP_EXTERN(void) WebPMemoryWriterInit(WebPMemoryWriter* writer);
|
||||||
|
|
||||||
#if WEBP_ENCODER_ABI_VERSION > 0x0202
|
#if WEBP_ENCODER_ABI_VERSION > 0x0203
|
||||||
// The following must be called to deallocate writer->mem memory. The 'writer'
|
// The following must be called to deallocate writer->mem memory. The 'writer'
|
||||||
// object itself is not deallocated.
|
// object itself is not deallocated.
|
||||||
WEBP_EXTERN(void) WebPMemoryWriterClear(WebPMemoryWriter* writer);
|
WEBP_EXTERN(void) WebPMemoryWriterClear(WebPMemoryWriter* writer);
|
||||||
#endif
|
#endif
|
||||||
// The custom writer to be used with WebPMemoryWriter as custom_ptr. Upon
|
// The custom writer to be used with WebPMemoryWriter as custom_ptr. Upon
|
||||||
// completion, writer.mem and writer.size will hold the coded data.
|
// completion, writer.mem and writer.size will hold the coded data.
|
||||||
#if WEBP_ENCODER_ABI_VERSION > 0x0202
|
#if WEBP_ENCODER_ABI_VERSION > 0x0203
|
||||||
// writer.mem must be freed by calling WebPMemoryWriterClear.
|
// writer.mem must be freed by calling WebPMemoryWriterClear.
|
||||||
#else
|
#else
|
||||||
// writer.mem must be freed by calling 'free(writer.mem)'.
|
// writer.mem must be freed by calling 'free(writer.mem)'.
|
||||||
@ -446,13 +446,14 @@ WEBP_EXTERN(int) WebPPictureImportBGRA(
|
|||||||
WEBP_EXTERN(int) WebPPictureImportBGRX(
|
WEBP_EXTERN(int) WebPPictureImportBGRX(
|
||||||
WebPPicture* picture, const uint8_t* bgrx, int bgrx_stride);
|
WebPPicture* picture, const uint8_t* bgrx, int bgrx_stride);
|
||||||
|
|
||||||
// Converts picture->argb data to the YUVA format specified by 'colorspace'.
|
// Converts picture->argb data to the YUV420A format. The 'colorspace'
|
||||||
|
// parameter is deprecated and should be equal to WEBP_YUV420.
|
||||||
// Upon return, picture->use_argb is set to false. The presence of real
|
// Upon return, picture->use_argb is set to false. The presence of real
|
||||||
// non-opaque transparent values is detected, and 'colorspace' will be
|
// non-opaque transparent values is detected, and 'colorspace' will be
|
||||||
// adjusted accordingly. Note that this method is lossy.
|
// adjusted accordingly. Note that this method is lossy.
|
||||||
// Returns false in case of error.
|
// Returns false in case of error.
|
||||||
WEBP_EXTERN(int) WebPPictureARGBToYUVA(WebPPicture* picture,
|
WEBP_EXTERN(int) WebPPictureARGBToYUVA(WebPPicture* picture,
|
||||||
WebPEncCSP colorspace);
|
WebPEncCSP /*colorspace = WEBP_YUV420*/);
|
||||||
|
|
||||||
// Same as WebPPictureARGBToYUVA(), but the conversion is done using
|
// Same as WebPPictureARGBToYUVA(), but the conversion is done using
|
||||||
// pseudo-random dithering with a strength 'dithering' between
|
// pseudo-random dithering with a strength 'dithering' between
|
||||||
@ -461,6 +462,15 @@ WEBP_EXTERN(int) WebPPictureARGBToYUVA(WebPPicture* picture,
|
|||||||
WEBP_EXTERN(int) WebPPictureARGBToYUVADithered(
|
WEBP_EXTERN(int) WebPPictureARGBToYUVADithered(
|
||||||
WebPPicture* picture, WebPEncCSP colorspace, float dithering);
|
WebPPicture* picture, WebPEncCSP colorspace, float dithering);
|
||||||
|
|
||||||
|
#if WEBP_ENCODER_ABI_VERSION > 0x0204
|
||||||
|
// Performs 'smart' RGBA->YUVA420 downsampling and colorspace conversion.
|
||||||
|
// Downsampling is handled with extra care in case of color clipping. This
|
||||||
|
// method is roughly 2x slower than WebPPictureARGBToYUVA() but produces better
|
||||||
|
// YUV representation.
|
||||||
|
// Returns false in case of error.
|
||||||
|
WEBP_EXTERN(int) WebPPictureSmartARGBToYUVA(WebPPicture* picture);
|
||||||
|
#endif
|
||||||
|
|
||||||
// Converts picture->yuv to picture->argb and sets picture->use_argb to true.
|
// Converts picture->yuv to picture->argb and sets picture->use_argb to true.
|
||||||
// The input format must be YUV_420 or YUV_420A.
|
// The input format must be YUV_420 or YUV_420A.
|
||||||
// Note that the use of this method is discouraged if one has access to the
|
// Note that the use of this method is discouraged if one has access to the
|
||||||
|
Loading…
x
Reference in New Issue
Block a user