Compare commits

...

57 Commits
main ... v0.4.2

Author SHA1 Message Date
James Zern
6a2209aa36 update ChangeLog
Change-Id: I32a22786f99d0c239761a362485a4a91c783851b
2014-10-17 16:15:30 +02:00
James Zern
36cad6abe8 bit_reader.h: cosmetics: fix a typo
Change-Id: I1ba09124700b3120f18eb3705eb5ba805feb2ca0
(cherry picked from commit 79b5bdbfde6773e95744155853ecb880889b931a)
2014-10-17 16:02:03 +02:00
James Zern
e2ecae62f0 enc_mips32: workaround gcc-4.9 bug
avoids an ICE with NDK r10b + NDK_TOOLCHAIN_VERSION=4.9

In function 'SSE16x16':
enc_mips32.c (684) internal compiler error: Segmentation fault

Change-Id: I1a3d33c0a9534c97633ab93bcdf9bf59d3a7e473
(cherry picked from commit 0ce27e715ec8d0bc6f3a9bf66b2b0d761ab433f9)
2014-10-15 19:58:03 +02:00
James Zern
243e68df60 update ChangeLog
Change-Id: Ib9504997d00c9f72cff30aa699fe1998b6be940d
2014-10-14 20:43:43 +02:00
James Zern
eec5f5f121 enc/vp8enci.h: update version number
0.4.1 -> 0.4.2
missed in: 857578a bump version to 0.4.2

Change-Id: Iaa62ce5af5935243748e51105008f252443e7d27
2014-10-14 20:40:02 +02:00
James Zern
0c1b98d28c update NEWS
Change-Id: Ib9b48e3611b77214bc875524249366ff62451c1b
2014-10-14 12:02:17 +02:00
James Zern
69b0fc9492 update AUTHORS
Change-Id: I750dc65205705b94f6a3fd467e6746c482c983cb
2014-10-14 12:02:17 +02:00
James Zern
857578a811 bump version to 0.4.2
libwebp{,decoder} - 0.4.2
libwebp libtool - 5.2.0
libwebpdecoder libtool - 1.2.0

mux/demux - 0.2.2
libtool - 1.2.0

Change-Id: If593a198f802fd68c7dbbdbe0fc2612dbc44e2df
2014-10-14 12:02:17 +02:00
James Zern
9129deb5b1 restore encode API compatibility
protect WebPPictureSmartARGBToYUVA with an ABI check

Change-Id: Iaec4a9f8f590f27c4c72129b90068690efc84eb7
2014-10-14 12:02:17 +02:00
James Zern
f17b95e992 AssignSegments: quiet -Warray-bounds warning
the number of segments are previously validated, but an explicit check
is needed to avoid a warning under gcc-4.9

(cherry picked from commit c8a87bb62d64b03087499e9277937fe76f1f1726)

Change-Id: Ifa7c0dd7f3f075b3860fa8ec176d2c98ff54fcea
2014-10-14 12:02:16 +02:00
James Zern
9c56c8a12e enc_neon: initialize vectors w/vdup_n_u32
replaces {} initialization gnu-ism

(cherry picked from commit 7534d716407712329fe73776e5644183515332fa)

Change-Id: I5a7b2d4246f0205e4bfb7f4b77d720c47d8674ec
2014-10-14 12:02:16 +02:00
James Zern
a008902320 iosbuild: cleanup
- s/declare -r/readonly/
- remove unnecessary build variables
- echo configure line

(cherry picked from commit 041956f6a3c9a9299523712d01c9e6d97f606aec)

Change-Id: I4489d8413934dcec57d60abf136a72d08fa0fd99
2014-10-14 12:02:16 +02:00
James Zern
cc6de53b3b iosbuild: output autoconf req. on failure
(cherry picked from commit 767eb40238f6c4476508f88e27bd8886e7bed29e)

Change-Id: I2a6d80cf22f5b58e80345a411c48f047fecdbb47
2014-10-14 12:02:16 +02:00
James Zern
740d765aea iosbuild: make iOS 6 the minimum requirement
iOS 5 support isn't available in the Xcode 6 install; iOS 6 covers
phones starting at the 3GS, so should be a reasonable base line

(cherry picked from commit 9f7d9e6ddaea051bf5f231356591bddde4d9a7ac)

Change-Id: Ie5603c9e30cb52114b372509e183febbf679a69a
2014-10-14 12:02:16 +02:00
James Zern
403023f500 iobuild.sh: only install .h files in Headers
cp * -> cp *.h; avoids picking up autoconf files

(cherry picked from commit 38128cb9df35f19d8654a052c389b021666134e3)

Change-Id: I57c04562d554431ddf4605af65077f32d90ac58e
2014-10-14 12:02:16 +02:00
skal
b65727b55d Premultiply with alpha during U/V downsampling
This prevents the 'alpha-leak' reported in issue #220

Speed-diff is kept minimal.

(cherry picked from commit c792d4129ab3500a59e271cadb5885d9f079de0b)

Change-Id: I1976de5e6de7cfcec89a54df9233c1a6586a5846
2014-10-14 12:02:16 +02:00
Urvang Joshi
8de0debcec gif2webp: Background color correction
For some GIF images, the first frame is missing the corresponding
graphic control extension. For such cases, we were never calling
GetBackgroundColor(), and default background color value (white) was being used
incorrectly.
So, we call GetBackgroundColor() when we encounter the first image
descriptor instead, to make sure that it is always called.

(cherry picked from commit 0cc811d7d6f8200cde698b5273e632620deb4c6b)

Change-Id: I00fc8e943d8a0c1578dcd718f3e74dec7de4ed61
2014-10-14 12:02:16 +02:00
Pascal Massimino
f8b7d94daa Amend the lossless spec according to issue #205, #206 and #224
http://code.google.com/p/webp/issues/detail?id=205 <- Select()
http://code.google.com/p/webp/issues/detail?id=206 <- out-of-bound colormap index
http://code.google.com/p/webp/issues/detail?id=224 <- version number MUST be 0

(cherry picked from commit d7167ff7ce71f73205e9c8af07ce8bd8134cf779)

Change-Id: I56a575529862dfc8ad189ddcfc47ef59a58f273d
2014-10-14 12:02:16 +02:00
Pascal Massimino
9102a7b63d Add a WebPExtractAlpha function to dsp
This is the opposite of WebPDispatchAlpha

+ Implement the SSE2 version

(cherry picked from commit cddd33405055d70e5aab7b2aabaf1970522dd2e4)

Conflicts:
	src/dsp/alpha_processing_sse2.c

Change-Id: I0c297309255f508c5261da8aad01f7e57f924d6c
2014-10-14 12:02:16 +02:00
James Zern
e407b5d516 webpmux: simplify InitializeConfig()
put WebPMuxConfig on the stack in main() rather than allocating it in
InitializeConfig(); removes a level of indirection there.

(cherry picked from commit c0a462cac252da745e4b4f21851db3e5188b5681)

Change-Id: I81d386f7472ebbd322dd3fdbfda9d78dbeb62a66
2014-10-14 12:02:16 +02:00
James Zern
3e70e64153 webpmux: fix indent
+ remove unnecessary cast

(cherry picked from commit 6986bb5e125287b6f36550807abdbd3a3c2a84f3)

Change-Id: I2070fbe6aeda49f5790c69390e5b539a2c1a5616
2014-10-14 12:02:16 +02:00
James Zern
be38f1af47 webpmux: fix exit status on numeric value parse error
in most cases 'ok' is set via a goto macro

(cherry picked from commit f89e1690df4b0c96c31f5f2e346e8843b5e3dcba)

Change-Id: I17c832446bf3e716d3bcd323dbcc72bec544029c
2014-10-14 12:02:16 +02:00
James Zern
94dadcb1a1 webpmux: fix loop_count range check
explicitly check [0, 65535], the use of 'long' was removed in a prior
commit

(cherry picked from commit 0e23c487dad7a1bd9b2cff409144910386823c15)

Change-Id: I70d5bf286908459b5d4d619c657853f0e833b6ea
2014-10-14 12:02:16 +02:00
James Zern
40b3a618ec examples: warn on invalid numeric parameters
add ExUtilGet[U]Int / ExUtilGetFloat which print an error message on
parse failure.
fixes issue #219.

(cherry picked from commit 96d43a873a61886e0642ec50f25cadccc21a5086)

Conflicts:
	examples/cwebp.c
	examples/dwebp.c

Change-Id: Ie537f5aebd138925bf1a48289b6b5e261b3af2ca
2014-10-14 12:02:16 +02:00
Urvang Joshi
b7d209a448 gif2webp: Handle frames with missing graphic control extension
According to the GIF spec (http://www.w3.org/Graphics/GIF/spec-gif89a.txt),
this block is optional, and its scope is only the first graphic rendering block
that follows.

The spec doesn't mention what default values of frame dimensions, offsets,
duration and transparent index to use in such a case, though. So, we use the
defaults used by GIF reader in Chromium:
https://code.google.com/p/chromium/codesearch#chromium/src/third_party/WebKit/Source/platform/image-decoders/gif/GIFImageReader.h&l=186

(cherry picked from commit d51f3e40698284ffc4831e7d8de7ae59d453f41d)

Change-Id: Iecc6967847192483770e85ac15fe2835cd01ce7b
2014-10-14 12:02:16 +02:00
James Zern
bf0eb74829 configure: simplify libpng-config invocation
use --ldflags over --prefix + --libs combination

based on comment in issue #180.

(cherry picked from commit be70b86c5764b296f7ad75cf91f2e0b4c3d7cfe8)

Change-Id: If2ca06053d5237b6722ddf4117917e5f3c06ab59
2014-10-14 12:02:15 +02:00
Vikas Arora
3740f7d4c6 Rectify bug in lossless incremental decoding.
Handle the corner case when VP8LDecodeImage() method is called with an invalid
header data. The lossless decoding doesn't support incremental mode yet.
Return the error status as BITSTREAM error in case not all pixels are decoded
with the provided bit-stream. Also added asserts in the VP8LDecodeImage() method
to validate the decoder header with appropriate/valid data for huffman trees
(htree_groups_ etc).

(cherry picked from commit e0a99321611c5b5a43e33b4d377877d999e730f9)

Change-Id: Ibac9fcfc4bd0a2c5f624bb9d4a2b9f6459aa19ea
2014-10-14 12:02:06 +02:00
Pascal Massimino
3ab0a377d2 make VP8LSetBitPos() set br->eos_ flag
ReadSymbol() finishes with a VP8LSetBitPos() call only and could miss an eos_ during the decode loop.

Things are faster because of inlining too.

(cherry picked from commit d3242aee16e022f296ff985b5a17d653b8af0529)

Change-Id: I2d2a275f38834ba005bc767d45c5de72d032103e
2014-10-14 10:03:15 +02:00
Pascal Massimino
2e4312b14f Lossless decoding: fix eos_ flag condition
eos_ needs to be set only when superfluous bits have actually
been requested.
Earlier, we were assuming pre-mature end-of-stream to be an error.
Now, more precisely, we mark error when we have encountered end-of-stream *and*
we attempt to read more bits after that.

This handles cases where image data requires no bits to be read

(cherry picked from commit a9decb5584dccf74e2fefd37cefc59d786834771)

Change-Id: I628e2c39c64f10c443fb51f86b1f5919cc9fd299
2014-10-14 10:03:14 +02:00
Pascal Massimino
e6609ac6b9 fix erroneous dec->status_ setting
We only need to set BITSTREAM_ERROR if !ok.

(cherry picked from commit 3fea6a28dafe8b326b0e407bd36b22a72e32f8b0)

Conflicts:
    src/dec/vp8l.c

Change-Id: I5bd13e64797e8bc509477edb29158abb39cb0ee1
2014-10-14 10:02:30 +02:00
skal
5692eae1f3 add a fallback to ALPHA_NO_COMPRESSION
if ALPHA_LOSSLESS_COMPRESSION produces a too big file (very rare!),
we fall-back to no-compression automatically.

(cherry picked from commit 187d379db68839f76d1390be291c471f2f66644c)

Change-Id: I5f3f509c635ce43a5e7c23f5d0f0c8329a5f24b7
2014-10-14 09:57:41 +02:00
James Zern
6ecd5bf682 ExUtilReadFromStdin: (windows) open stdin in bin mode
fixes input/decode from stdin in the examples

(cherry picked from commit a6140194ff28bafbc4a2b5804c923c7e5aa52163)

Change-Id: Ie8052da758a9ef64477501b709408236d258da82
2014-10-14 09:57:41 +02:00
James Zern
4206ac6bbf webpmux: (windows) open stdout in binary mode
prevents corrupt output. related to issue #217

(cherry picked from commit e80eab1fbc63fa267f7e97a89c6d5d07b9981d45)

Change-Id: I6f0dac8131127717ba72b0709fb35d421ab41acb
2014-10-14 09:57:41 +02:00
James Zern
d40e885931 cwebp: (windows) open stdout in binary mode
prevents corrupt output. fixes issue #217

(cherry picked from commit e9bfb1166db75689ca8ce278d1a18ef8b6042667)

Change-Id: If90afb441636144300da66d64f0e7f78505b4060
2014-10-14 09:57:41 +02:00
James Zern
4aaf463449 example_util: add ExUtilSetBinaryMode
use it in dwebp when dealing with 'stdout'

(cherry picked from commit 5927e15bc78cc13134672ebfb83e3b6143204cae)

Change-Id: I8b8a0b0de9e73731e913ac3c83b5e2b33c693175
2014-10-14 09:57:41 +02:00
Urvang Joshi
4c82ff76c1 webpmux man page: Clarify some title, descriptions and examples
Based on the feedback here:
https://groups.google.com/a/webmproject.org/d/msg/webp-discuss/qY6rWJLqRTY/pF8oSj8DOGYJ

(cherry picked from commit 30f3b75b33ca2c959a4cfedff0843b09216ed12e)

Change-Id: I9119ea8e211ffb269026010e3c590385bc6a9f17
2014-10-14 09:57:41 +02:00
James Zern
23d4fb3362 dsp/lossless: workaround gcc-4.9 bug on arm
force Sub3() to not be inlined, otherwise the code in Select() will be
incorrect.
https://android-review.googlesource.com/#/c/102511

(cherry picked from commit 637b3888090dea7d79aa51731186938f8f0edf4d)

Change-Id: I90ae58bf3e6cc92ca9897f69974733d562e29aaf
2014-10-13 19:03:49 +02:00
James Zern
5af7719047 dsp.h: collect gcc/clang version test macros
endian_inl.h already relies on dsp.h, grab the definitions from there.

(cherry picked from commit 8323a9038d3dcd722516f874a3310e16be5b10b2)

Change-Id: I445f7d0631723043c55da1070498f89965bec7b1
2014-10-13 19:03:49 +02:00
James Zern
90d112466b enc_neon: enable QuantizeBlock for aarch64
vtbl4_u8 is available everywhere except iOS arm64: use vtbl2q_u8 there
with a corresponding change in the load.

(cherry picked from commit 953acd56a413da79c5b7235e7839dc57d2e68430)

Change-Id: Ib84212dda3c7875348282726c29e3b79b78b0eac
2014-10-13 19:03:48 +02:00
skal
ee78e7801d SmartRGBYUV: fix odd-width problem with pixel replication
rightmost pixel was missing a copy, which could lead to invalid read.

Also added a lower dimension of 4, below which we use the regular conversion.
This is to prevent corner cases, in addition to not being overkill.

(cherry picked from commit 2523aa73cb0aa337aaa5cd480a47a65476cdeb2c)

Change-Id: Iac12e7a3d74590f12fe8eeb1830b9891e61439f6
2014-10-13 19:03:48 +02:00
Pascal Massimino
c9ac2041e9 fix some MSVC64 warning about float conversion
(cherry picked from commit ee52dc4e549b0f13c86d2a34cfd9d6f96209f35c)

Change-Id: I27ab27fc15033d27d0505729f6275fb542c8d473
2014-10-13 19:03:48 +02:00
James Zern
f4497a1ef5 cpu: check for _MSC_VER before using msvc inline asm
_M_IX86 will be defined in mingw builds after including windows.h. as
the gcc inline asm is first, this missing check would only have caused
an error if the code was reorganized.

(cherry picked from commit 3fca851a202e5b1018a2cc491b9e005913394afe)

Change-Id: I395679bcfc43e94d308d1ceb0c0fbf932b2c378c
2014-10-13 19:03:48 +02:00
skal
e2159fdff7 faster RGB->YUV conversion function (~7% speedup)
with a special case for dithering==0., it gets somewhat faster on x86
thanks to inlining.

Also, less macros.

(cherry picked from commit e2a83d71091abc3e5177ee0ffc4ceb18c7714fab)

Change-Id: Ic2f2bf6718310743bb40cef2104fa759a073e6d5
2014-10-13 19:03:48 +02:00
skal
21abaa05e3 Add smart RGB->YUV conversion option -pre 4
New function: WebPPictureSmartARGBToYUVA()
This implement smart RGB->YUV conversion.

This is rather undocumented for now, and is triggered using '-pre 4'
preprocessing option.

This is slow-ish and use quite some memory, but should be improvable.
This is somehow a usable beta version.

(cherry picked from commit 3fc4c539aa00c325eba9ef8faec30ec241d71e9c)

Change-Id: Ia50a8c30134e4cab8a7d3eb70aef13ce1f6187a1
2014-10-13 19:03:48 +02:00
James Zern
1a161e20a4 configure: add work around for gcc-4.9 aarch64 bug
add -frename-registers to avoid:
src/dsp/dec_neon.c🔢1: internal
compiler error: in simplify_const_unary_operation, at
simplify-rtx.c:1539

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=62040
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=61622
https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=757738

(cherry picked from commit e2b8cec05b2d18892c8375b575a727dbeb95c864)

Change-Id: I52fb3a29ac30b82b27da05378bdb495ddebb97d7
2014-10-13 19:03:48 +02:00
Djordje Pesut
55b10de73f MIPS: mips32r2: added optimization for BSwap32
gcc < 4.8.3 doesn't translate bswap optimally.
use optimized version always

(cherry picked from commit 98c54107df065ff224bd925e670effc7dc8253e6)

Change-Id: I979ea26ad6dc0166d3d2f39c4148eb8adfb7ddec
2014-10-13 19:03:48 +02:00
Lou Quillio
76d2192206 Update PATENTS to reflect s/VP8/WebM/g
Sync with http://www.webmproject.org/license/additional/

modified:   PATENTS

(cherry picked from commit dab702b357a011cf0bdbf01acb0e4e28bfb3a1bb)

Change-Id: I9f7af36fdcf57a82311363a043707b181832fc18
2014-10-13 18:19:08 +02:00
Djordje Pesut
29a9db1f7c MIPS: detect mips32r6 and disable mips32r1 code
(cherry picked from commit b7e5a5c451dfead56672703299a44e1e9907becd)

Change-Id: Id1325c789a990c9a8704e84e99a22d580303eb8a
2014-10-13 18:19:04 +02:00
Timothy Gu
245c4a6737 Correctly use the AC_CANONICAL_* macros
http://www.gnu.org/software/autoconf/manual/autoconf.html#Using-System-Type

Signed-off-by: Timothy Gu <timothygu99@gmail.com>
(cherry picked from commit 63c2fc02ce3d0674a0a6d1e10e9ee04a76aa9d5d)

Change-Id: I40a13e84f5266ed20bc4db098502b1610ab71206
2014-10-13 18:18:58 +02:00
James Zern
40aa8b69b0 cosmetics
fix some indent/whitespace, remove a few duplicate includes, extra
semi-colons

(cherry picked from commit e300c9d8191db55e113f0aa8effc7a57c6219a41)

Change-Id: If937182b40a21e0f2028496e7b4b06c6e8a41352
2014-10-13 18:18:50 +02:00
James Zern
2ddcca5efe cosmetics: remove some extraneous 'extern's
(cherry picked from commit f7b4c48bbacf637efa4368c5573fc1cdffae22eb)

Change-Id: Ib3f0cff37120c51633387dd1c46592c53ab0ba6d
2014-10-13 18:18:44 +02:00
James Zern
f40dd7c6de vp8enci.h: cosmetics: fix '*' placement
associate with the type

(cherry picked from commit b47fb00ac0bbb3554b36bbe736f7933e5894bd69)

Change-Id: Icf94f11bf79f6ccee3150e27b228755f8f3f0f37
2014-10-13 18:18:35 +02:00
James Zern
4610c9c55a bit_writer: cosmetics: rename kFlush() -> Flush()
(cherry picked from commit 4c6dde37b959cc71b6c7309d2e1e5701d74ce434)

Change-Id: I8907927974188bee85ffade1d75d2e50817aa115
2014-10-13 18:18:31 +02:00
James Zern
fc3c1750dc dsp: detect mips64 & disable mips32 code
(cherry picked from commit 0524d9e5e83babd417539e042dec5ed1affc7ef2)

Change-Id: Icf68dafd5cf0614ca25b36a0252caa1784ac8059
2014-10-13 18:18:25 +02:00
James Zern
c1a7955d59 cwebp.1: restore quality description
based on:
d3485d9 cwebp.1: fix quality description placement

Change-Id: I8bd16db7f39cc9ff816cc02c04a455493e550c26
2014-10-13 18:18:24 +02:00
James Zern
57a7e73d27 correct alpha_dithering_strength ABI check
the ABI wasn't bumped with this addition, but it's more correct to say
it was added with 0x0205 rather than 0x0204

Change-Id: I2ba12a33b612fac16bdfeb8272e76b0ea84f3938
2014-10-13 18:18:22 +02:00
James Zern
6c83157524 correct WebPMemoryWriterClear ABI check
this function was introduced in 0x0204; fix checks related to this to be
> 0x0203 instead of 0x0202, pointed out on ffmpeg-devel.

Change-Id: I52cd2b98304baf1eb9a83094e2374f2120a1546b
2014-10-13 18:18:19 +02:00
58 changed files with 1599 additions and 452 deletions

View File

@ -20,5 +20,6 @@ Contributors:
- Scott Talbot (s at chikachow dot org)
- Slobodan Prijic (slobodan dot prijic at imgtec 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)
- Vikas Arora (vikasa at google dot com)

View File

@ -33,6 +33,7 @@ LOCAL_SRC_FILES := \
src/dec/vp8l.c \
src/dec/webp.c \
src/dsp/alpha_processing.c \
src/dsp/alpha_processing_sse2.c \
src/dsp/cpu.c \
src/dsp/dec.c \
src/dsp/dec_clip_tables.c \

View File

@ -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
8d34ea3 update ChangeLog (tag: v0.4.1-rc1)
dbc3da6 makefile.unix: add vwebp.1 to the dist target
@ -17,7 +74,7 @@ c2fc52e restore encode API compatibility
793368e restore decode API compatibility
b8984f3 gif2webp: fix compile with giflib 5.1.0
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"
157de01 Merge "Actuate memory stats for PRINT_MEMORY_INFO"
fbda2f4 JPEG decoder: delay conversion to YUV to WebPEncode() call

View File

@ -172,6 +172,7 @@ DEMUX_OBJS = \
DSP_DEC_OBJS = \
$(DIROBJ)\dsp\alpha_processing.obj \
$(DIROBJ)\dsp\alpha_processing_sse2.obj \
$(DIROBJ)\dsp\cpu.obj \
$(DIROBJ)\dsp\dec.obj \
$(DIROBJ)\dsp\dec_clip_tables.obj \

8
NEWS
View File

@ -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
This is a binary compatible release.
* AArch64 (arm64) & MIPS support/optimizations

39
PATENTS
View File

@ -1,22 +1,23 @@
Additional IP Rights Grant (Patents)
------------------------------------
"This implementation" means the copyrightable works distributed by
Google as part of the WebM Project.
"These implementations" means the copyrightable works that implement the WebM
codecs distributed by Google as part of the WebM Project.
Google hereby grants to you a perpetual, worldwide, non-exclusive,
no-charge, royalty-free, irrevocable (except as stated in this section)
patent license to make, have made, use, offer to sell, sell, import,
transfer, and otherwise run, modify and propagate the contents of this
implementation of VP8, where such license applies only to those patent
claims, both currently owned by Google and acquired in the future,
licensable by Google that are necessarily infringed by this
implementation of VP8. This grant does not include claims that would be
infringed only as a consequence of further modification of this
implementation. If you or your agent or exclusive licensee institute or
order or agree to the institution of patent litigation against any
entity (including a cross-claim or counterclaim in a lawsuit) alleging
that this implementation of VP8 or any code incorporated within this
implementation of VP8 constitutes direct or contributory patent
infringement, or inducement of patent infringement, then any patent
rights granted to you under this License for this implementation of VP8
shall terminate as of the date such litigation is filed.
Google hereby grants to you a perpetual, worldwide, non-exclusive, no-charge,
royalty-free, irrevocable (except as stated in this section) patent license to
make, have made, use, offer to sell, sell, import, transfer, and otherwise
run, modify and propagate the contents of these implementations of WebM, where
such license applies only to those patent claims, both currently owned by
Google and acquired in the future, licensable by Google that are necessarily
infringed by these implementations of WebM. This grant does not include claims
that would be infringed only as a consequence of further modification of these
implementations. If you or your agent or exclusive licensee institute or order
or agree to the institution of patent litigation or any other patent
enforcement activity against any entity (including a cross-claim or
counterclaim in a lawsuit) alleging that any of these implementations of WebM
or any code incorporated within any of these implementations of WebM
constitutes direct or contributory patent infringement, or inducement of
patent infringement, then any patent rights granted to you under this License
for these implementations of WebM shall terminate as of the date such
litigation is filed.

2
README
View File

@ -4,7 +4,7 @@
\__\__/\____/\_____/__/ ____ ___
/ _/ / \ \ / _ \/ _/
/ \_/ / / \ \ __/ \__
\____/____/\_____/_____/____/v0.4.1
\____/____/\_____/_____/____/v0.4.2
Description:
============

View File

@ -1,7 +1,7 @@
 __ __ ____ ____ ____ __ __ _ __ __
/ \\/ \/ _ \/ _ \/ _ \/ \ \/ \___/_ / _\
\ / __/ _ \ __/ / / (_/ /__
\__\__/\_____/_____/__/ \__//_/\_____/__/___/v0.2.1
\__\__/\_____/_____/__/ \__//_/\_____/__/___/v0.2.2
Description:

View File

@ -1,7 +1,7 @@
AC_INIT([libwebp], [0.4.1],
AC_INIT([libwebp], [0.4.2],
[http://code.google.com/p/webp/issues],,
[http://developers.google.com/speed/webp])
AC_CANONICAL_TARGET
AC_CANONICAL_HOST
AC_PREREQ([2.60])
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])
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])
dnl === Check for machine specific flags
@ -283,15 +296,12 @@ AC_ARG_ENABLE([png], AS_HELP_STRING([--disable-png],
@<:@default=auto@:>@]))
AS_IF([test "x$enable_png" != "xno"], [
CLEAR_LIBVARS([PNG])
AC_PATH_PROGS(LIBPNG_CONFIG,
[libpng-config libpng15-config libpng14-config libpng12-config])
AC_PATH_PROGS([LIBPNG_CONFIG],
[libpng-config libpng16-config libpng15-config libpng14-config \
libpng12-config])
if test -n "$LIBPNG_CONFIG"; then
PNG_INCLUDES=`$LIBPNG_CONFIG --cflags`
PNG_PREFIX=`$LIBPNG_CONFIG --prefix`
if test "${PNG_PREFIX}/lib" != "/usr/lib" ; then
PNG_LIBS="-L${PNG_PREFIX}/lib"
fi
PNG_LIBS="$PNG_LIBS `$LIBPNG_CONFIG --libs`"
PNG_LIBS="`$LIBPNG_CONFIG --ldflags`"
fi
WITHLIB_OPTION([png], [PNG])
@ -409,8 +419,9 @@ AC_ARG_ENABLE([wic],
@<:@default=auto@:>@]),,
[enable_wic=yes])
if test \( "$target_os" = "mingw32" -o "$target_os" = "mingw64" \) \
-a "$enable_wic" = "yes"; then
case $host_os in
mingw*)
if test "$enable_wic" = "yes"; then
AC_CHECK_HEADERS([wincodec.h shlwapi.h windows.h])
if test "$ac_cv_header_wincodec_h" = "yes"; then
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})
fi
fi
esac
dnl === If --enable-aligned is defined, define WEBP_FORCE_ALIGNED

View File

@ -14,6 +14,7 @@ Specification for WebP Lossless Bitstream
_Jyrki Alakuijala, Ph.D., Google, Inc., 2012-06-19_
Paragraphs marked as \[AMENDED\] were amended on 2014-09-16.
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);
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The version_number is a 3 bit code that must be discarded by the decoder
at this time. Complying encoders write a 3-bit value 0.
The version_number is a 3 bit code that must be set to 0. Any other value
should be treated as an error. \[AMENDED\]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
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));
// Return either left or top, the one closer to the prediction.
if (pL <= pT) {
if (pL < pT) { // \[AMENDED\]
return L;
} else {
return T;
@ -542,6 +543,9 @@ color.
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
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

View File

@ -22,6 +22,7 @@
#include "webp/encode.h"
#include "./example_util.h"
#include "./metadata.h"
#include "./stopwatch.h"
@ -709,6 +710,7 @@ int main(int argc, const char *argv[]) {
}
for (c = 1; c < argc; ++c) {
int parse_error = 0;
if (!strcmp(argv[c], "-h") || !strcmp(argv[c], "-help")) {
HelpShort();
return 0;
@ -732,30 +734,31 @@ int main(int argc, const char *argv[]) {
} else if (!strcmp(argv[c], "-short")) {
++short_output;
} else if (!strcmp(argv[c], "-s") && c < argc - 2) {
picture.width = strtol(argv[++c], NULL, 0);
picture.height = strtol(argv[++c], NULL, 0);
picture.width = ExUtilGetInt(argv[++c], 0, &parse_error);
picture.height = ExUtilGetInt(argv[++c], 0, &parse_error);
} 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
use_lossless_preset = 0; // disable -z option
#endif
} 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
use_lossless_preset = 0; // disable -z option
} 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;
#endif
} 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) {
config.alpha_compression = strtol(argv[++c], NULL, 0);
config.alpha_compression = ExUtilGetInt(argv[++c], 0, &parse_error);
} else if (!strcmp(argv[c], "-alpha_cleanup")) {
keep_alpha = keep_alpha ? 2 : 0;
} else if (!strcmp(argv[c], "-blend_alpha") && c < argc - 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;
} else if (!strcmp(argv[c], "-alpha_filter") && c < argc - 1) {
++c;
@ -786,13 +789,13 @@ int main(int argc, const char *argv[]) {
goto Error;
}
} 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) {
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) {
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) {
config.filter_strength = strtol(argv[++c], NULL, 0);
config.filter_strength = ExUtilGetInt(argv[++c], 0, &parse_error);
} else if (!strcmp(argv[c], "-af")) {
config.autofilter = 1;
} else if (!strcmp(argv[c], "-jpeg_like")) {
@ -806,26 +809,26 @@ int main(int argc, const char *argv[]) {
} else if (!strcmp(argv[c], "-nostrong")) {
config.filter_type = 0;
} 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) {
config.pass = strtol(argv[++c], NULL, 0);
config.pass = ExUtilGetInt(argv[++c], 0, &parse_error);
} 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) {
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) {
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) {
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) {
crop = 1;
crop_x = strtol(argv[++c], NULL, 0);
crop_y = strtol(argv[++c], NULL, 0);
crop_w = strtol(argv[++c], NULL, 0);
crop_h = strtol(argv[++c], NULL, 0);
crop_x = ExUtilGetInt(argv[++c], 0, &parse_error);
crop_y = ExUtilGetInt(argv[++c], 0, &parse_error);
crop_w = ExUtilGetInt(argv[++c], 0, &parse_error);
crop_h = ExUtilGetInt(argv[++c], 0, &parse_error);
} else if (!strcmp(argv[c], "-resize") && c < argc - 2) {
resize_w = strtol(argv[++c], NULL, 0);
resize_h = strtol(argv[++c], NULL, 0);
resize_w = ExUtilGetInt(argv[++c], 0, &parse_error);
resize_h = ExUtilGetInt(argv[++c], 0, &parse_error);
#ifndef WEBP_DLL
} else if (!strcmp(argv[c], "-noasm")) {
VP8GetCPUInfo = NULL;
@ -920,6 +923,11 @@ int main(int argc, const char *argv[]) {
} else {
in_file = argv[c];
}
if (parse_error) {
HelpLong();
return -1;
}
}
if (in_file == NULL) {
fprintf(stderr, "No input file specified!\n");
@ -981,7 +989,7 @@ int main(int argc, const char *argv[]) {
// Open the output
if (out_file != NULL) {
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) {
fprintf(stderr, "Error! Cannot open output file '%s'\n", out_file);
goto Error;
@ -1126,7 +1134,7 @@ int main(int argc, const char *argv[]) {
return_value = 0;
Error:
#if WEBP_ENCODER_ABI_VERSION > 0x0202
#if WEBP_ENCODER_ABI_VERSION > 0x0203
WebPMemoryWriterClear(&memory_writer);
#else
free(memory_writer.mem);

View File

@ -38,11 +38,6 @@
#include <wincodec.h>
#endif
#if defined(_WIN32)
#include <fcntl.h> // for _O_BINARY
#include <io.h> // for _setmode()
#endif
#include "webp/decode.h"
#include "./example_util.h"
#include "./stopwatch.h"
@ -482,15 +477,8 @@ static int SaveOutput(const WebPDecBuffer* const buffer,
needs_open_file = (format != PNG);
#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) {
fout = use_stdout ? stdout : fopen(out_file, "wb");
fout = use_stdout ? ExUtilSetBinaryMode(stdout) : fopen(out_file, "wb");
if (fout == NULL) {
fprintf(stderr, "Error opening output file %s\n", out_file);
return 0;
@ -557,7 +545,7 @@ static void Help(void) {
" -nofilter .... disable in-loop filtering\n"
" -nodither .... disable dithering\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"
#endif
" -mt .......... use multi-threading\n"
@ -598,6 +586,7 @@ int main(int argc, const char *argv[]) {
}
for (c = 1; c < argc; ++c) {
int parse_error = 0;
if (!strcmp(argv[c], "-h") || !strcmp(argv[c], "-help")) {
Help();
return 0;
@ -628,24 +617,25 @@ int main(int argc, const char *argv[]) {
format = YUV;
} else if (!strcmp(argv[c], "-mt")) {
config.options.use_threads = 1;
#if WEBP_DECODER_ABI_VERSION > 0x0203
#if WEBP_DECODER_ABI_VERSION > 0x0204
} else if (!strcmp(argv[c], "-alpha_dither")) {
config.options.alpha_dithering_strength = 100;
#endif
} else if (!strcmp(argv[c], "-nodither")) {
config.options.dithering_strength = 0;
} 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) {
config.options.use_cropping = 1;
config.options.crop_left = strtol(argv[++c], NULL, 0);
config.options.crop_top = strtol(argv[++c], NULL, 0);
config.options.crop_width = strtol(argv[++c], NULL, 0);
config.options.crop_height = strtol(argv[++c], NULL, 0);
config.options.crop_left = ExUtilGetInt(argv[++c], 0, &parse_error);
config.options.crop_top = ExUtilGetInt(argv[++c], 0, &parse_error);
config.options.crop_width = ExUtilGetInt(argv[++c], 0, &parse_error);
config.options.crop_height = ExUtilGetInt(argv[++c], 0, &parse_error);
} else if (!strcmp(argv[c], "-scale") && c < argc - 2) {
config.options.use_scaling = 1;
config.options.scaled_width = strtol(argv[++c], NULL, 0);
config.options.scaled_height = strtol(argv[++c], NULL, 0);
config.options.scaled_width = ExUtilGetInt(argv[++c], 0, &parse_error);
config.options.scaled_height = ExUtilGetInt(argv[++c], 0, &parse_error);
#if WEBP_DECODER_ABI_VERSION > 0x0203
} else if (!strcmp(argv[c], "-flip")) {
config.options.flip = 1;
@ -668,6 +658,11 @@ int main(int argc, const char *argv[]) {
} else {
in_file = argv[c];
}
if (parse_error) {
Help();
return -1;
}
}
if (in_file == NULL) {

View File

@ -11,6 +11,11 @@
//
#include "./example_util.h"
#if defined(_WIN32)
#include <fcntl.h> // for _O_BINARY
#include <io.h> // for _setmode()
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@ -18,12 +23,50 @@
#include "webp/decode.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
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) {
static const size_t kBlockSize = 16384; // default initial size
size_t max_size = 0;
size_t size = 0;
uint8_t* input = NULL;
@ -32,6 +75,8 @@ int ExUtilReadFromStdin(const uint8_t** data, size_t* data_size) {
*data = NULL;
*data_size = 0;
if (!ExUtilSetBinaryMode(stdin)) return 0;
while (!feof(stdin)) {
// We double the buffer size each time and read as much as possible.
const size_t extra_size = (max_size == 0) ? kBlockSize : max_size;

View File

@ -13,12 +13,30 @@
#ifndef WEBP_EXAMPLES_EXAMPLE_UTIL_H_
#define WEBP_EXAMPLES_EXAMPLE_UTIL_H_
#include <stdio.h>
#include "webp/decode.h"
#ifdef __cplusplus
extern "C" {
#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
// in 'data' and 'data_size'. Returns 1 on success, 0 otherwise. '*data' should
// be deleted using free().

View File

@ -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,
size_t* const kmax_ptr) {
@ -163,21 +174,22 @@ static int ReadFrame(GifFileType* const gif, WebPFrameRect* const gif_rect,
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) {
if (transparent_index != -1 && bgcolor_idx == transparent_index) {
*bgcolor = WEBP_UTIL_TRANSPARENT_COLOR; // Special case.
return 1;
} else if (color_map == NULL || color_map->Colors == NULL
|| 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 {
const GifColorType color = color_map->Colors[bgcolor_idx];
*bgcolor = (0xff << 24)
| (color.Red << 16)
| (color.Green << 8)
| (color.Blue << 0);
return 1;
}
}
@ -278,10 +290,7 @@ int main(int argc, const char *argv[]) {
size_t kmax = 0;
int allow_mixed = 0; // If true, each frame can be lossy or lossless.
memset(&info, 0, sizeof(info));
info.id = WEBP_CHUNK_ANMF;
info.dispose_method = WEBP_MUX_DISPOSE_BACKGROUND;
info.blend_method = WEBP_MUX_BLEND;
ResetFrameInfo(&info);
if (!WebPConfigInit(&config) || !WebPPictureInit(&frame)) {
fprintf(stderr, "Error! Version mismatch!\n");
@ -296,6 +305,7 @@ int main(int argc, const char *argv[]) {
}
for (c = 1; c < argc; ++c) {
int parse_error = 0;
if (!strcmp(argv[c], "-h") || !strcmp(argv[c], "-help")) {
Help();
return 0;
@ -307,17 +317,17 @@ int main(int argc, const char *argv[]) {
allow_mixed = 1;
config.lossless = 0;
} 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) {
config.method = strtol(argv[++c], NULL, 0);
config.method = ExUtilGetInt(argv[++c], 0, &parse_error);
} 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;
} 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;
} 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) {
static const struct {
const char* option;
@ -381,6 +391,11 @@ int main(int argc, const char *argv[]) {
} else {
in_file = argv[c];
}
if (parse_error) {
Help();
return -1;
}
}
// 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,
kmin, kmax, allow_mixed);
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.
if (image_desc->Width == 0 || image_desc->Height == 0) {
@ -492,6 +511,11 @@ int main(int argc, const char *argv[]) {
goto End;
}
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;
}
case EXTENSION_RECORD_TYPE: {
@ -525,13 +549,6 @@ int main(int argc, const char *argv[]) {
: WEBP_MUX_DISPOSE_NONE;
}
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;
}
case PLAINTEXT_EXT_FUNC_CODE: {

View File

@ -475,7 +475,7 @@ static WebPEncodingError SetFrame(const WebPConfig* const config,
// TODO(later): Perhaps a rough SSIM/PSNR produced by the encoder should
// also be a criteria, in addition to sizes.
if (mem1.size <= mem2.size) {
#if WEBP_ENCODER_ABI_VERSION > 0x0202
#if WEBP_ENCODER_ABI_VERSION > 0x0203
WebPMemoryWriterClear(&mem2);
#else
free(mem2.mem);
@ -483,7 +483,7 @@ static WebPEncodingError SetFrame(const WebPConfig* const config,
#endif
GetEncodedData(&mem1, encoded_data);
} else {
#if WEBP_ENCODER_ABI_VERSION > 0x0202
#if WEBP_ENCODER_ABI_VERSION > 0x0203
WebPMemoryWriterClear(&mem1);
#else
free(mem1.mem);
@ -497,7 +497,7 @@ static WebPEncodingError SetFrame(const WebPConfig* const config,
return error_code;
Err:
#if WEBP_ENCODER_ABI_VERSION > 0x0202
#if WEBP_ENCODER_ABI_VERSION > 0x0203
WebPMemoryWriterClear(&mem1);
WebPMemoryWriterClear(&mem2);
#else

View File

@ -377,7 +377,7 @@ static void Help(void) {
" -nofancy ..... don't use the fancy YUV420 upscaler\n"
" -nofilter .... disable in-loop filtering\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"
#endif
" -mt .......... use multi-threading\n"
@ -402,12 +402,13 @@ int main(int argc, char *argv[]) {
return -1;
}
config->options.dithering_strength = 50;
#if WEBP_DECODER_ABI_VERSION > 0x0203
#if WEBP_DECODER_ABI_VERSION > 0x0204
config->options.alpha_dithering_strength = 100;
#endif
kParams.use_color_profile = 1;
for (c = 1; c < argc; ++c) {
int parse_error = 0;
if (!strcmp(argv[c], "-h") || !strcmp(argv[c], "-help")) {
Help();
return 0;
@ -417,12 +418,13 @@ int main(int argc, char *argv[]) {
config->options.no_fancy_upsampling = 1;
} else if (!strcmp(argv[c], "-nofilter")) {
config->options.bypass_filtering = 1;
#if WEBP_DECODER_ABI_VERSION > 0x0203
#if WEBP_DECODER_ABI_VERSION > 0x0204
} else if (!strcmp(argv[c], "-noalphadither")) {
config->options.alpha_dithering_strength = 0;
#endif
} 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")) {
kParams.print_info = 1;
} else if (!strcmp(argv[c], "-version")) {
@ -445,6 +447,11 @@ int main(int argc, char *argv[]) {
} else {
kParams.file_name = argv[c];
}
if (parse_error) {
Help();
return -1;
}
}
if (kParams.file_name == NULL) {

View File

@ -402,8 +402,9 @@ static int CreateMux(const char* const filename, WebPMux** mux) {
static int WriteData(const char* filename, const WebPData* const webpdata) {
int ok = 0;
FILE* fout = strcmp(filename, "-") ? fopen(filename, "wb") : stdout;
if (!fout) {
FILE* fout = strcmp(filename, "-") ? fopen(filename, "wb")
: ExUtilSetBinaryMode(stdout);
if (fout == NULL) {
fprintf(stderr, "Error opening output WebP file %s!\n", filename);
return 0;
}
@ -487,7 +488,7 @@ static int ParseBgcolorArgs(const char* args, uint32_t* const bgcolor) {
static void DeleteConfig(WebPMuxConfig* config) {
if (config != NULL) {
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.
static int InitializeConfig(int argc, const char* argv[],
WebPMuxConfig** config) {
WebPMuxConfig* config) {
int num_feature_args = 0;
int ok = 1;
assert(config != NULL);
*config = NULL;
memset(config, 0, sizeof(*config));
// Validate command-line arguments.
if (!ValidateCommandLine(argc, argv, &num_feature_args)) {
ERROR_GOTO1("Exiting due to command-line parsing error.\n", Err1);
}
// Allocate memory.
*config = (WebPMuxConfig*)calloc(1, sizeof(**config));
if (*config == NULL) {
ERROR_GOTO1("ERROR: Memory allocation error.\n", Err1);
}
(*config)->feature_.arg_count_ = num_feature_args;
(*config)->feature_.args_ =
(FeatureArg*)calloc(num_feature_args, sizeof(FeatureArg));
if ((*config)->feature_.args_ == NULL) {
config->feature_.arg_count_ = num_feature_args;
config->feature_.args_ =
(FeatureArg*)calloc(num_feature_args, sizeof(*config->feature_.args_));
if (config->feature_.args_ == NULL) {
ERROR_GOTO1("ERROR: Memory allocation error.\n", Err1);
}
// Parse command-line.
if (!ParseCommandLine(argc, argv, *config) ||
!ValidateConfig(*config)) {
if (!ParseCommandLine(argc, argv, config) || !ValidateConfig(config)) {
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;
long num = 0;
int ok = 1;
int parse_error = 0;
const WebPChunkId id = is_frame ? WEBP_CHUNK_ANMF : WEBP_CHUNK_FRGM;
WebPMuxFrameInfo info;
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) {
ERROR_GOTO1("ERROR: Frame/Fragment index must be non-negative.\n", ErrGet);
}
if (parse_error) goto ErrGet;
err = WebPMuxGetFrame(mux, num, &info);
if (err == WEBP_MUX_OK && info.id != id) err = WEBP_MUX_NOT_FOUND;
@ -871,7 +868,7 @@ static int GetFrameFragment(const WebPMux* mux,
ErrGet:
WebPDataClear(&info.bitstream);
WebPMuxDelete(mux_single);
return ok;
return ok && !parse_error;
}
// Read and process config.
@ -933,16 +930,19 @@ static int Process(const WebPMuxConfig* config) {
break;
}
case SUBTYPE_LOOP: {
const long loop_count =
strtol(feature->args_[i].params_, NULL, 10);
if (loop_count != (int)loop_count) {
int parse_error = 0;
const 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
// to be valid. The 'sufficient' conditioned in checked in
// WebPMuxSetAnimationParams() method called later.
ERROR_GOTO1("ERROR: Loop count must be in the range 0 to "
"65535.\n", Err2);
}
params.loop_count = (int)loop_count;
ok = !parse_error;
if (!ok) goto Err2;
params.loop_count = loop_count;
break;
}
case SUBTYPE_ANMF: {
@ -1069,14 +1069,14 @@ static int Process(const WebPMuxConfig* config) {
// Main.
int main(int argc, const char* argv[]) {
WebPMuxConfig* config;
WebPMuxConfig config;
int ok = InitializeConfig(argc - 1, argv + 1, &config);
if (ok) {
ok = Process(config);
ok = Process(&config);
} else {
PrintHelp();
}
DeleteConfig(config);
DeleteConfig(&config);
return !ok;
}

View File

@ -12,31 +12,35 @@
set -e
# 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)}'
)
# 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.
# Note that iPhoneOS-V6 support is not available with the iOS6 SDK.
declare -r PLATFORMS="iPhoneSimulator iPhoneOS-V7 iPhoneOS-V7s iPhoneOS-V7-arm64"
declare -r SRCDIR=$(dirname $0)
declare -r TOPDIR=$(pwd)
declare -r BUILDDIR="${TOPDIR}/iosbuild"
declare -r TARGETDIR="${TOPDIR}/WebP.framework"
declare -r DEVELOPER=$(xcode-select --print-path)
declare -r PLATFORMSROOT="${DEVELOPER}/Platforms"
declare -r LIPO=$(xcrun -sdk iphoneos${SDK} -find lipo)
readonly PLATFORMS="iPhoneSimulator iPhoneOS-V7 iPhoneOS-V7s iPhoneOS-V7-arm64"
readonly SRCDIR=$(dirname $0)
readonly TOPDIR=$(pwd)
readonly BUILDDIR="${TOPDIR}/iosbuild"
readonly TARGETDIR="${TOPDIR}/WebP.framework"
readonly DEVELOPER=$(xcode-select --print-path)
readonly PLATFORMSROOT="${DEVELOPER}/Platforms"
readonly LIPO=$(xcrun -sdk iphoneos${SDK} -find lipo)
LIBLIST=''
if [[ -z "${SDK}" ]]; then
echo "iOS SDK not available"
exit 1
elif [[ ${SDK} < 4.0 ]]; then
echo "You need iOS SDK version 4.0 or above"
elif [[ ${SDK} < 6.0 ]]; then
echo "You need iOS SDK version 6.0 or above"
exit 1
else
echo "iOS SDK Version ${SDK}"
@ -47,7 +51,17 @@ rm -rf ${TARGETDIR}
mkdir -p ${BUILDDIR}
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
ARCH2=""
@ -71,30 +85,20 @@ for PLATFORM in ${PLATFORMS}; do
ROOTDIR="${BUILDDIR}/${PLATFORM}-${SDK}-${ARCH}"
mkdir -p "${ROOTDIR}"
SDKROOT="${PLATFORMSROOT}/${PLATFORM}.platform/Developer/SDKs/${PLATFORM}${SDK}.sdk/"
CFLAGS="-arch ${ARCH2:-${ARCH}} -pipe -isysroot ${SDKROOT} -O3 -DNDEBUG"
LDFLAGS="-arch ${ARCH2:-${ARCH}} -pipe -isysroot ${SDKROOT}"
if [[ -z "${XCODE}" ]]; then
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
SDKROOT="${PLATFORMSROOT}/"
SDKROOT+="${PLATFORM}.platform/Developer/SDKs/${PLATFORM}${SDK}.sdk/"
CFLAGS="-arch ${ARCH2:-${ARCH}} -pipe -isysroot ${SDKROOT} -O3 -DNDEBUG"
CFLAGS+=" -miphoneos-version-min=6.0"
export CFLAGS
export LDFLAGS
export CXXFLAGS=${CFLAGS}
set -x
export PATH="${DEVROOT}/usr/bin:${OLDPATH}"
${SRCDIR}/configure --host=${ARCH}-apple-darwin --prefix=${ROOTDIR} \
--build=$(${SRCDIR}/config.guess) \
--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
cd src/
@ -109,5 +113,5 @@ for PLATFORM in ${PLATFORMS}; do
export PATH=${OLDPATH}
done
cp -a ${SRCDIR}/src/webp/* ${TARGETDIR}/Headers/
cp -a ${SRCDIR}/src/webp/*.h ${TARGETDIR}/Headers/
${LIPO} -create ${LIBLIST} -output ${TARGETDIR}/WebP

View File

@ -108,6 +108,7 @@ DEMUX_OBJS = \
DSP_DEC_OBJS = \
src/dsp/alpha_processing.o \
src/dsp/alpha_processing_sse2.o \
src/dsp/cpu.o \
src/dsp/dec.o \
src/dsp/dec_clip_tables.o \

View File

@ -1,5 +1,5 @@
.\" Hey, EMACS: -*- nroff -*-
.TH CWEBP 1 "July 22, 2014"
.TH CWEBP 1 "Oct 13, 2014"
.SH NAME
cwebp \- compress an image file to a WebP file
.SH SYNOPSIS
@ -38,6 +38,13 @@ Print the version number (as major.minor.revision) and exit.
.BI \-q " float
Specify the compression factor for RGB channels between 0 and 100. The default
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
.\" .TP
.\" .BI \-z " int
@ -47,13 +54,6 @@ is 75.
.\" 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
.\" 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
.BI \-alpha_q " int
Specify the compression factor for alpha compression between 0 and 100.

View File

@ -1,7 +1,8 @@
.\" Hey, EMACS: -*- nroff -*-
.TH WEBPMUX 1 "December 17, 2013"
.TH WEBPMUX 1 "August 28, 2014"
.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
.B webpmux \-get
.I GET_OPTIONS
@ -45,8 +46,8 @@ This manual page documents the
.B webpmux
command.
.PP
\fBwebpmux\fP can be used to create a WebP container file
and extract/strip relevant data from the container file.
\fBwebpmux\fP can be used to create/extract from animated WebP files, as well as
to add/extract/strip XMP/EXIF metadata and ICC profile.
.SH OPTIONS
.SS GET_OPTIONS (\-get):
.TP
@ -60,7 +61,7 @@ Get EXIF metadata.
Get XMP metadata.
.TP
.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)
.TP
@ -91,12 +92,13 @@ Strip EXIF metadata.
Strip XMP metadata.
.SS FRAME_OPTIONS (\-frame)
Create an animated WebP file from multiple (non\-animated) WebP images.
.TP
.I file_i +di[+xi+yi[+mi[bi]]]
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
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).
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
@ -130,37 +132,61 @@ Please report all bugs to our issue tracker:
http://code.google.com/p/webp/issues
.br
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
.P
Add ICC profile:
.br
webpmux \-set icc image_profile.icc in.webp \-o icc_container.webp
.P
Extract ICC profile:
.br
webpmux \-get icc icc_container.webp \-o image_profile.icc
.P
Strip ICC profile:
.br
webpmux \-strip icc icc_container.webp \-o without_icc.webp
.P
Add XMP metadata:
.br
webpmux \-set xmp image_metadata.xmp in.webp \-o xmp_container.webp
.P
Extract XMP metadata:
.br
webpmux \-get xmp xmp_container.webp \-o image_metadata.xmp
.P
Strip XMP metadata:
.br
webpmux \-strip xmp xmp_container.webp \-o without_xmp.webp
.P
Add EXIF metadata:
.br
webpmux \-set exif image_metadata.exif in.webp \-o exif_container.webp
.P
Extract EXIF metadata:
.br
webpmux \-get exif exif_container.webp \-o image_metadata.exif
.P
Strip EXIF metadata:
.br
webpmux \-strip exif exif_container.webp \-o without_exif.webp
.P
Create an animated WebP file from 3 (non\-animated) WebP images:
.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
.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
.RS 8
\-o anim_container.webp
.RE
.P
Get the 2nd frame from an animated WebP file:
.br
webpmux \-get frame 2 anim_container.webp \-o frame_2.webp
.P
Using \-get/\-set/\-strip with input file name starting with '\-':
.br
webpmux \-set icc image_profile.icc \-o icc_container.webp \-\- \-\-\-in.webp
.br

View File

@ -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
# not have unresolved symbols. Some platforms (Windows among them) require all
# 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
pkgconfig_DATA = libwebp.pc
@ -47,7 +47,7 @@ if BUILD_LIBWEBPDECODER
libwebpdecoder_la_LIBADD += dsp/libwebpdspdecode.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
endif

View File

@ -177,7 +177,7 @@ void VP8InitDithering(const WebPDecoderOptions* const options,
dec->dither_ = 1;
}
}
#if WEBP_DECODER_ABI_VERSION > 0x0203
#if WEBP_DECODER_ABI_VERSION > 0x0204
// potentially allow alpha dithering
dec->alpha_dithering_ = options->alpha_dithering_strength;
if (dec->alpha_dithering_ > 100) {

View File

@ -529,6 +529,12 @@ static VP8StatusCode DecodeVP8LData(WebPIDecoder* const idec) {
}
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_);
}

View File

@ -11,7 +11,7 @@
//
// Author: Skal (pascal.massimino@gmail.com)
#include "vp8i.h"
#include "./vp8i.h"
#include "../utils/bit_reader_inl.h"
#define USE_GENERIC_TREE

View File

@ -31,7 +31,7 @@ extern "C" {
// version numbers
#define DEC_MAJ_VERSION 0
#define DEC_MIN_VERSION 4
#define DEC_REV_VERSION 1
#define DEC_REV_VERSION 2
// intra prediction modes
enum { B_DC_PRED = 0, // 4x4 modes

View File

@ -234,6 +234,7 @@ static int ReadHuffmanCodeLengths(
End:
VP8LHuffmanTreeFree(&tree);
if (!ok) dec->status_ = VP8_STATUS_BITSTREAM_ERROR;
return ok;
}
@ -801,6 +802,7 @@ static int DecodeAlphaData(VP8LDecoder* const dec, uint8_t* const data,
ok = 0;
goto End;
}
assert(br->eos_ == VP8LIsEndOfStream(br));
ok = !br->error_;
if (!ok) goto End;
}
@ -918,6 +920,7 @@ static int DecodeImageData(VP8LDecoder* const dec, uint32_t* const data,
ok = 0;
goto End;
}
assert(br->eos_ == VP8LIsEndOfStream(br));
ok = !br->error_;
if (!ok) goto End;
}
@ -1354,6 +1357,10 @@ int VP8LDecodeImage(VP8LDecoder* const dec) {
// Sanity checks.
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_;
assert(io != NULL);
params = (WebPDecParams*)io->opaque;

View File

@ -9,6 +9,6 @@ libwebpdemuxinclude_HEADERS += ../webp/mux_types.h
libwebpdemuxinclude_HEADERS += ../webp/types.h
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
pkgconfig_DATA = libwebpdemux.pc

View File

@ -25,7 +25,7 @@
#define DMUX_MAJ_VERSION 0
#define DMUX_MIN_VERSION 2
#define DMUX_REV_VERSION 1
#define DMUX_REV_VERSION 2
typedef struct {
size_t start_; // start location of the data

View File

@ -38,6 +38,7 @@ libwebpdsp_avx2_la_CPPFLAGS = $(libwebpdsp_la_CPPFLAGS)
libwebpdsp_avx2_la_CFLAGS = $(AM_CFLAGS) $(AVX2_FLAGS)
libwebpdspdecode_sse2_la_SOURCES =
libwebpdspdecode_sse2_la_SOURCES += alpha_processing_sse2.c
libwebpdspdecode_sse2_la_SOURCES += dec_sse2.c
libwebpdspdecode_sse2_la_SOURCES += lossless_sse2.c
libwebpdspdecode_sse2_la_SOURCES += upsampling_sse2.c

View File

@ -284,15 +284,46 @@ static void ApplyAlphaMultiply_16b(uint8_t* rgba4444,
#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 (*WebPApplyAlphaMultiply4444)(uint8_t*, int, int, int);
int (*WebPExtractAlpha)(const uint8_t*, int, int, int, uint8_t*, int);
//------------------------------------------------------------------------------
// Init function
extern void WebPInitAlphaProcessingSSE2(void);
void WebPInitAlphaProcessing(void) {
WebPMultARGBRow = MultARGBRow;
WebPMultRow = MultRow;
WebPApplyAlphaMultiply = ApplyAlphaMultiply;
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
}
}

View 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
}

View File

@ -57,7 +57,7 @@ static WEBP_INLINE uint64_t xgetbv(void) {
}
#elif defined(_MSC_FULL_VER) && _MSC_FULL_VER >= 160040219 // >= VS2010 SP1
#define xgetbv() _xgetbv(0)
#elif defined(_M_IX86)
#elif defined(_MSC_VER) && defined(_M_IX86)
static WEBP_INLINE uint64_t xgetbv(void) {
uint32_t eax_, edx_;
__asm {
@ -118,7 +118,7 @@ static int armCPUInfo(CPUFeature feature) {
return 1;
}
VP8CPUInfo VP8GetCPUInfo = armCPUInfo;
#elif defined(__mips__)
#elif defined(WEBP_USE_MIPS32)
static int mipsCPUInfo(CPUFeature feature) {
(void)feature;
return 1;

View File

@ -32,9 +32,19 @@ extern "C" {
# define LOCAL_GCC_PREREQ(maj, min) \
(LOCAL_GCC_VERSION >= (((maj) << 8) | (min)))
#else
# define LOCAL_GCC_VERSION 0
# define LOCAL_GCC_PREREQ(maj, min) 0
#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 && \
(defined(_M_X64) || defined(_M_IX86))
#define WEBP_MSC_SSE2 // Visual C++ SSE2 targets
@ -60,8 +70,11 @@ extern "C" {
#define WEBP_USE_NEON
#endif
#if defined(__mips__)
#if defined(__mips__) && !defined(__mips64) && (__mips_isa_rev < 6)
#define WEBP_USE_MIPS32
#if (__mips_isa_rev >= 2)
#define WEBP_USE_MIPS32_R2
#endif
#endif
typedef enum {
@ -244,6 +257,13 @@ extern void (*WebPApplyAlphaMultiply)(
extern void (*WebPApplyAlphaMultiply4444)(
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).
// Un-Multiply operation transforms x into x * 255 / A.

View File

@ -20,6 +20,10 @@
#include "../enc/vp8enci.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 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(D, D + 1, D + 2, D + 3)
#if !defined(WORK_AROUND_GCC)
static int SSE16x16(const uint8_t* a, const uint8_t* b) {
int count;
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;
}
#endif // WORK_AROUND_GCC
#undef GET_SSE_MIPS32
#undef GET_SSE_MIPS32_INNER
@ -759,9 +766,11 @@ void VP8EncDspInitMIPS32(void) {
VP8TDisto4x4 = Disto4x4;
VP8TDisto16x16 = Disto16x16;
VP8FTransform = FTransform;
#if !defined(WORK_AROUND_GCC)
VP8SSE16x16 = SSE16x16;
VP8SSE8x8 = SSE8x8;
VP8SSE16x8 = SSE16x8;
VP8SSE4x4 = SSE4x4;
#endif
#endif // WEBP_USE_MIPS32
}

View File

@ -253,7 +253,7 @@ static void ITransform(const uint8_t* ref,
// Load all 4x4 pixels into a single uint8x16_t variable.
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 + 1 * BPS), out, 1);
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) {
uint32x4_t sum = { 0, 0, 0, 0 };
uint32x4_t sum = vdupq_n_u32(0);
int y;
for (y = 0; y < 16; ++y) {
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) {
uint32x4_t sum = { 0, 0, 0, 0 };
uint32x4_t sum = vdupq_n_u32(0);
int y;
for (y = 0; y < 8; ++y) {
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) {
uint32x4_t sum = { 0, 0, 0, 0 };
uint32x4_t sum = vdupq_n_u32(0);
int y;
for (y = 0; y < 8; ++y) {
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
// in iOS/arm64 builds. Disable this function in those cases.
#if !(defined(WORK_AROUND_GCC) || defined(__aarch64__))
// Compilation with gcc-4.6.x is problematic for now.
#if !defined(WORK_AROUND_GCC)
static int16x8_t Quantize(int16_t* const in,
const VP8Matrix* const mtx, int offset) {
@ -1012,17 +1011,34 @@ static int QuantizeBlock(int16_t in[16], int16_t out[16],
const VP8Matrix* const mtx) {
const int16x8_t out0 = Quantize(in, mtx, 0);
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;
INIT_VECTOR4(all_out,
vreinterpret_u8_s16(vget_low_s16(out0)),
vreinterpret_u8_s16(vget_high_s16(out0)),
vreinterpret_u8_s16(vget_low_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
vst1_u8((uint8_t*)(out + 0), vtbl4_u8(all_out, vld1_u8(kShuffles[0])));
vst1_u8((uint8_t*)(out + 4), vtbl4_u8(all_out, vld1_u8(kShuffles[1])));
vst1_u8((uint8_t*)(out + 8), vtbl4_u8(all_out, vld1_u8(kShuffles[2])));
vst1_u8((uint8_t*)(out + 12), vtbl4_u8(all_out, vld1_u8(kShuffles[3])));
vst1_u8((uint8_t*)(out + 0), shuffles.val[0]);
vst1_u8((uint8_t*)(out + 4), shuffles.val[1]);
vst1_u8((uint8_t*)(out + 8), shuffles.val[2]);
vst1_u8((uint8_t*)(out + 12), shuffles.val[3]);
// test zeros
if (*(uint64_t*)(out + 0) != 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;
}
#endif // !WORK_AROUND_GCC && !__aarch64__
#endif // !WORK_AROUND_GCC
#endif // WEBP_USE_NEON
@ -1054,7 +1070,7 @@ void VP8EncDspInitNEON(void) {
VP8SSE16x8 = SSE16x8;
VP8SSE8x8 = SSE8x8;
VP8SSE4x4 = SSE4x4;
#if !(defined(WORK_AROUND_GCC) || defined(__aarch64__))
#if !defined(WORK_AROUND_GCC)
VP8EncQuantizeBlock = QuantizeBlock;
#endif
#endif // WEBP_USE_NEON

View File

@ -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;
}
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 pa = a - c;
return abs(pb) - abs(pa);
}
#undef LOCAL_INLINE
static WEBP_INLINE uint32_t Select(uint32_t a, uint32_t b, uint32_t c) {
const int pa_minus_pb =
Sub3((a >> 24) , (b >> 24) , (c >> 24) ) +
@ -1169,7 +1178,7 @@ static void ColorSpaceInverseTransform(const VP8LTransform* const transform,
data += remaining_width;
}
++y;
if ((y & mask) == 0) pred_row += tiles_per_row;;
if ((y & mask) == 0) pred_row += tiles_per_row;
}
}

View File

@ -56,24 +56,20 @@ extern VP8LConvertFunc VP8LConvertBGRAToRGB565;
extern VP8LConvertFunc VP8LConvertBGRAToBGR;
// 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);
extern void VP8LTransformColorInverse_C(const VP8LMultipliers* const m,
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);
void VP8LConvertBGRAToRGBA_C(const uint32_t* src, int num_pixels, uint8_t* dst);
void VP8LConvertBGRAToRGBA4444_C(const uint32_t* src,
int num_pixels, uint8_t* dst);
extern void VP8LConvertBGRAToRGBA_C(const uint32_t* src,
void VP8LConvertBGRAToRGB565_C(const uint32_t* src,
int num_pixels, uint8_t* dst);
extern void VP8LConvertBGRAToRGBA4444_C(const uint32_t* src,
int num_pixels, uint8_t* dst);
extern void VP8LConvertBGRAToRGB565_C(const uint32_t* src,
int num_pixels, uint8_t* dst);
extern void VP8LConvertBGRAToBGR_C(const uint32_t* src,
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);
void VP8LConvertBGRAToBGR_C(const uint32_t* src, int num_pixels, uint8_t* dst);
void VP8LSubtractGreenFromBlueAndRed_C(uint32_t* argb_data, int num_pixels);
void VP8LAddGreenToBlueAndRed_C(uint32_t* data, int num_pixels);
// Must be called before calling any of the above methods.
void VP8LDspInit(void);

View File

@ -47,12 +47,11 @@
static int EncodeLossless(const uint8_t* const data, int width, int height,
int effort_level, // in [0..6] range
VP8BitWriter* const bw,
VP8LBitWriter* const bw,
WebPAuxStats* const stats) {
int ok = 0;
WebPConfig config;
WebPPicture picture;
VP8LBitWriter tmp_bw;
WebPPictureInit(&picture);
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;
assert(config.quality >= 0 && config.quality <= 100.f);
ok = VP8LBitWriterInit(&tmp_bw, (width * height) >> 3);
ok = ok && (VP8LEncodeStream(&config, &picture, &tmp_bw) == VP8_ENC_OK);
ok = (VP8LEncodeStream(&config, &picture, bw) == VP8_ENC_OK);
WebPPictureFree(&picture);
if (ok) {
const uint8_t* const buffer = VP8LBitWriterFinish(&tmp_bw);
const size_t buffer_size = VP8LBitWriterNumBytes(&tmp_bw);
VP8BitWriterAppend(bw, buffer, buffer_size);
ok = ok && !bw->error_;
if (!ok) {
VP8LBitWriterDestroy(bw);
return 0;
}
VP8LBitWriterDestroy(&tmp_bw);
return ok && !bw->error_;
return 1;
}
// -----------------------------------------------------------------------------
@ -115,8 +113,10 @@ static int EncodeAlphaInternal(const uint8_t* const data, int width, int height,
const uint8_t* alpha_src;
WebPFilterFunc filter_func;
uint8_t header;
size_t expected_size;
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(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);
// 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];
if (filter_func != NULL) {
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;
}
if (method == ALPHA_NO_COMPRESSION) {
ok = VP8BitWriterAppend(&result->bw, alpha_src, width * height);
ok = ok && !result->bw.error_;
} else {
ok = EncodeLossless(alpha_src, width, height, effort_level,
&result->bw, &result->stats);
VP8BitWriterFinish(&result->bw);
if (method != ALPHA_NO_COMPRESSION) {
ok = VP8LBitWriterInit(&tmp_bw, data_size >> 3);
ok = ok && EncodeLossless(alpha_src, width, height, effort_level,
&tmp_bw, &result->stats);
if (ok) {
output = VP8LBitWriterFinish(&tmp_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);
return ok;
}

View File

@ -141,7 +141,11 @@ static void MergeHistograms(const VP8Histogram* const in,
static void AssignSegments(VP8Encoder* const enc,
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 weighted_average = 0;
int map[MAX_ALPHA + 1];

View File

@ -111,7 +111,11 @@ int WebPValidateConfig(const WebPConfig* config) {
return 0;
if (config->show_compressed < 0 || config->show_compressed > 1)
return 0;
#if WEBP_ENCODER_ABI_VERSION > 0x0204
if (config->preprocessing < 0 || config->preprocessing > 7)
#else
if (config->preprocessing < 0 || config->preprocessing > 3)
#endif
return 0;
if (config->partitions < 0 || config->partitions > 3)
return 0;

View File

@ -42,7 +42,7 @@ typedef void (*VP8SetResidualCoeffsFunc)(const int16_t* const coeffs,
VP8Residual* const res);
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);
@ -59,7 +59,7 @@ static WEBP_INLINE int VP8BitCost(int bit, uint8_t proba) {
typedef int (*VP8GetResidualCostFunc)(int ctx0, const VP8Residual* const res);
extern VP8GetResidualCostFunc VP8GetResidualCost;
extern void VP8GetResidualCostInit(void); // must be called first
void VP8GetResidualCostInit(void); // must be called first
// Level cost calculations
extern const uint16_t VP8LevelCodes[MAX_VARIABLE_LEVEL][2];

View File

@ -508,7 +508,7 @@ static void StoreSideInfo(const VP8EncIterator* const it) {
}
case 7: *info = mb->alpha_; break;
default: *info = 0; break;
};
}
}
#if SEGMENT_VISU // visualize segments and prediction modes
SetBlock(it->yuv_out_ + Y_OFF, mb->segment_ * 64, 16);

File diff suppressed because it is too large Load Diff

View File

@ -30,7 +30,7 @@ extern "C" {
// version numbers
#define ENC_MAJ_VERSION 0
#define ENC_MIN_VERSION 4
#define ENC_REV_VERSION 1
#define ENC_REV_VERSION 2
// intra prediction modes
enum { B_DC_PRED = 0, // 4x4 modes
@ -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);
#endif

View File

@ -328,6 +328,13 @@ int WebPEncode(const WebPConfig* config, WebPPicture* pic) {
VP8Encoder* enc = NULL;
if (pic->y == NULL || pic->u == NULL || pic->v == NULL) {
// Make sure we have YUVA samples.
if (config->preprocessing & 4) {
#if WEBP_ENCODER_ABI_VERSION > 0x0204
if (!WebPPictureSmartARGBToYUVA(pic)) {
return 0;
}
#endif
} else {
float dithering = 0.f;
if (config->preprocessing & 2) {
const float x = config->quality / 100.f;
@ -340,6 +347,7 @@ int WebPEncode(const WebPConfig* config, WebPPicture* pic) {
return 0;
}
}
}
enc = InitVP8Encoder(config, pic);
if (enc == NULL) return 0; // pic->error is already set.

View File

@ -12,6 +12,6 @@ libwebpmuxinclude_HEADERS += ../webp/mux_types.h
libwebpmuxinclude_HEADERS += ../webp/types.h
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
pkgconfig_DATA = libwebpmux.pc

View File

@ -28,7 +28,7 @@ extern "C" {
#define MUX_MAJ_VERSION 0
#define MUX_MIN_VERSION 2
#define MUX_REV_VERSION 1
#define MUX_REV_VERSION 2
// Chunk object.
typedef struct WebPChunk WebPChunk;

View File

@ -105,9 +105,7 @@ int32_t VP8GetSignedValue(VP8BitReader* const br, int bits) {
//------------------------------------------------------------------------------
// VP8LBitReader
#define LBITS 64 // Number of bits prefetched.
#define WBITS 32 // Minimum number of bytes needed after VP8LFillBitWindow.
#define LOG8_WBITS 4 // Number of bytes needed to store WBITS bits.
#define VP8L_LOG8_WBITS 4 // Number of bytes needed to store VP8L_WBITS bits.
#if !defined(WEBP_FORCE_ALIGNED) && \
(defined(__arm__) || defined(_M_ARM) || defined(__aarch64__) || \
@ -151,16 +149,6 @@ void VP8LInitBitReader(VP8LBitReader* const br, const uint8_t* const 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,
const uint8_t* const buf, size_t len) {
assert(br != NULL);
@ -168,38 +156,39 @@ void VP8LBitReaderSetBuffer(VP8LBitReader* const br,
assert(len < 0xfffffff8u); // can't happen with a RIFF chunk.
br->buf_ = buf;
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) {
while (br->bit_pos_ >= 8 && br->pos_ < br->len_) {
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->bit_pos_ -= 8;
}
br->eos_ = VP8LIsEndOfStream(br);
}
void VP8LFillBitWindow(VP8LBitReader* const br) {
if (br->bit_pos_ >= WBITS) {
void VP8LDoFillBitWindow(VP8LBitReader* const br) {
assert(br->bit_pos_ >= VP8L_WBITS);
// TODO(jzern): given the fixed read size it may be possible to force
// alignment in this block.
#if defined(VP8L_USE_UNALIGNED_LOAD)
if (br->pos_ + sizeof(br->val_) < br->len_) {
br->val_ >>= WBITS;
br->bit_pos_ -= WBITS;
br->val_ >>= VP8L_WBITS;
br->bit_pos_ -= VP8L_WBITS;
// The expression below needs a little-endian arch to work correctly.
// This gives a large speedup for decoding speed.
br->val_ |= (vp8l_val_t)*(const uint32_t*)(br->buf_ + br->pos_) <<
(LBITS - WBITS);
br->pos_ += LOG8_WBITS;
(VP8L_LBITS - VP8L_WBITS);
br->pos_ += VP8L_LOG8_WBITS;
return;
}
#endif
ShiftBytes(br); // Slow path.
br->eos_ = IsEndOfStreamSpecial(br);
}
}
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];
const int new_bits = br->bit_pos_ + n_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);
return val;
} else {

View File

@ -107,6 +107,9 @@ int32_t VP8GetSignedValue(VP8BitReader* const br, int num_bits);
// maximum number of bits (inclusive) the bit-reader can handle:
#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 struct {
@ -138,14 +141,26 @@ static WEBP_INLINE uint32_t VP8LPrefetchBits(VP8LBitReader* const br) {
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
// VP8LPrefetchBits and VP8LFillBitWindow.
static WEBP_INLINE void VP8LSetBitPos(VP8LBitReader* const br, int val) {
br->bit_pos_ = val;
br->eos_ = VP8LIsEndOfStream(br);
}
// 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
} // extern "C"

View File

@ -24,6 +24,7 @@
#include <string.h> // memcpy
#endif
#include "../dsp/dsp.h"
#include "./bit_reader.h"
#include "./endian_inl.h"
@ -63,7 +64,7 @@ static WEBP_INLINE void VP8LoadNewBytes(VP8BitReader* const br) {
#if defined(WEBP_FORCE_ALIGNED)
lbit_t 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.
lbit_t in_bits;
lbit_t* p_buf_ = (lbit_t*)br->buf_;

View File

@ -52,7 +52,7 @@ static int BitWriterResize(VP8BitWriter* const bw, size_t extra_size) {
return 1;
}
static void kFlush(VP8BitWriter* const bw) {
static void Flush(VP8BitWriter* const bw) {
const int s = 8 + bw->nb_bits_;
const int32_t bits = bw->value_ >> s;
assert(bw->nb_bits_ >= 0);
@ -118,7 +118,7 @@ int VP8PutBit(VP8BitWriter* const bw, int bit, int prob) {
bw->range_ = kNewRange[bw->range_];
bw->value_ <<= shift;
bw->nb_bits_ += shift;
if (bw->nb_bits_ > 0) kFlush(bw);
if (bw->nb_bits_ > 0) Flush(bw);
}
return bit;
}
@ -135,7 +135,7 @@ int VP8PutBitUniform(VP8BitWriter* const bw, int bit) {
bw->range_ = kNewRange[bw->range_];
bw->value_ <<= 1;
bw->nb_bits_ += 1;
if (bw->nb_bits_ > 0) kFlush(bw);
if (bw->nb_bits_ > 0) Flush(bw);
}
return bit;
}
@ -173,14 +173,14 @@ int VP8BitWriterInit(VP8BitWriter* const bw, size_t expected_size) {
uint8_t* VP8BitWriterFinish(VP8BitWriter* const bw) {
VP8PutValue(bw, 0, 9 - bw->nb_bits_);
bw->nb_bits_ = 0; // pad with zeroes
kFlush(bw);
Flush(bw);
return bw->buf_;
}
int VP8BitWriterAppend(VP8BitWriter* const bw,
const uint8_t* data, size_t size) {
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;
memcpy(bw->buf_ + bw->pos_, data, size);
bw->pos_ += size;

View File

@ -16,6 +16,7 @@
#include "../webp/config.h"
#endif
#include "../dsp/dsp.h"
#include "../webp/types.h"
// some endian fix (e.g.: mips-gcc doesn't define __BIG_ENDIAN__)
@ -34,25 +35,13 @@
#endif
#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
#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_BSWAP64
#endif
// 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
#endif
#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) {
#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);
#elif defined(__i386__) || defined(__x86_64__)
uint32_t swapped_bytes;

View File

@ -444,16 +444,20 @@ struct WebPDecoderOptions {
int dithering_strength; // dithering strength (0=Off, 100=full)
#if WEBP_DECODER_ABI_VERSION > 0x0203
int flip; // flip output vertically
#endif
#if WEBP_DECODER_ABI_VERSION > 0x0204
int alpha_dithering_strength; // alpha dithering strength in [0..100]
#endif
// Unused for now:
int force_rotation; // forced rotation (to be applied _last_)
int no_enhancement; // if true, discard enhancement layer
#if WEBP_DECODER_ABI_VERSION > 0x0203
uint32_t pad[3]; // padding for later use
#else
#if WEBP_DECODER_ABI_VERSION < 0x0203
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
};

View File

@ -231,14 +231,14 @@ struct WebPMemoryWriter {
// The following must be called first before any use.
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'
// object itself is not deallocated.
WEBP_EXTERN(void) WebPMemoryWriterClear(WebPMemoryWriter* writer);
#endif
// The custom writer to be used with WebPMemoryWriter as custom_ptr. Upon
// 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.
#else
// writer.mem must be freed by calling 'free(writer.mem)'.
@ -446,13 +446,14 @@ WEBP_EXTERN(int) WebPPictureImportBGRA(
WEBP_EXTERN(int) WebPPictureImportBGRX(
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
// non-opaque transparent values is detected, and 'colorspace' will be
// adjusted accordingly. Note that this method is lossy.
// Returns false in case of error.
WEBP_EXTERN(int) WebPPictureARGBToYUVA(WebPPicture* picture,
WebPEncCSP colorspace);
WebPEncCSP /*colorspace = WEBP_YUV420*/);
// Same as WebPPictureARGBToYUVA(), but the conversion is done using
// pseudo-random dithering with a strength 'dithering' between
@ -461,6 +462,15 @@ WEBP_EXTERN(int) WebPPictureARGBToYUVA(WebPPicture* picture,
WEBP_EXTERN(int) WebPPictureARGBToYUVADithered(
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.
// 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