Compare commits

...

2104 Commits

Author SHA1 Message Date
243e68df60 update ChangeLog
Change-Id: Ib9504997d00c9f72cff30aa699fe1998b6be940d
2014-10-14 20:43:43 +02:00
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
0c1b98d28c update NEWS
Change-Id: Ib9b48e3611b77214bc875524249366ff62451c1b
2014-10-14 12:02:17 +02:00
69b0fc9492 update AUTHORS
Change-Id: I750dc65205705b94f6a3fd467e6746c482c983cb
2014-10-14 12:02:17 +02:00
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
9129deb5b1 restore encode API compatibility
protect WebPPictureSmartARGBToYUVA with an ABI check

Change-Id: Iaec4a9f8f590f27c4c72129b90068690efc84eb7
2014-10-14 12:02:17 +02:00
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 c8a87bb62d)

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

(cherry picked from commit 7534d71640)

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

(cherry picked from commit 041956f6a3)

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

Change-Id: I2a6d80cf22f5b58e80345a411c48f047fecdbb47
2014-10-14 12:02:16 +02:00
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 9f7d9e6dda)

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

(cherry picked from commit 38128cb9df)

Change-Id: I57c04562d554431ddf4605af65077f32d90ac58e
2014-10-14 12:02:16 +02:00
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 c792d4129a)

Change-Id: I1976de5e6de7cfcec89a54df9233c1a6586a5846
2014-10-14 12:02:16 +02:00
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 0cc811d7d6)

Change-Id: I00fc8e943d8a0c1578dcd718f3e74dec7de4ed61
2014-10-14 12:02:16 +02:00
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 d7167ff7ce)

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

+ Implement the SSE2 version

(cherry picked from commit cddd334050)

Conflicts:
	src/dsp/alpha_processing_sse2.c

Change-Id: I0c297309255f508c5261da8aad01f7e57f924d6c
2014-10-14 12:02:16 +02:00
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 c0a462cac2)

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

(cherry picked from commit 6986bb5e12)

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

(cherry picked from commit f89e1690df)

Change-Id: I17c832446bf3e716d3bcd323dbcc72bec544029c
2014-10-14 12:02:16 +02:00
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 0e23c487da)

Change-Id: I70d5bf286908459b5d4d619c657853f0e833b6ea
2014-10-14 12:02:16 +02:00
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 96d43a873a)

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

Change-Id: Ie537f5aebd138925bf1a48289b6b5e261b3af2ca
2014-10-14 12:02:16 +02:00
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 d51f3e4069)

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

based on comment in issue #180.

(cherry picked from commit be70b86c57)

Change-Id: If2ca06053d5237b6722ddf4117917e5f3c06ab59
2014-10-14 12:02:15 +02:00
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 e0a9932161)

Change-Id: Ibac9fcfc4bd0a2c5f624bb9d4a2b9f6459aa19ea
2014-10-14 12:02:06 +02:00
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 d3242aee16)

Change-Id: I2d2a275f38834ba005bc767d45c5de72d032103e
2014-10-14 10:03:15 +02:00
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 a9decb5584)

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

(cherry picked from commit 3fea6a28da)

Conflicts:
    src/dec/vp8l.c

Change-Id: I5bd13e64797e8bc509477edb29158abb39cb0ee1
2014-10-14 10:02:30 +02:00
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 187d379db6)

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

(cherry picked from commit a6140194ff)

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

(cherry picked from commit e80eab1fbc)

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

(cherry picked from commit e9bfb1166d)

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

(cherry picked from commit 5927e15bc7)

Change-Id: I8b8a0b0de9e73731e913ac3c83b5e2b33c693175
2014-10-14 09:57:41 +02:00
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 30f3b75b33)

Change-Id: I9119ea8e211ffb269026010e3c590385bc6a9f17
2014-10-14 09:57:41 +02:00
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 637b388809)

Change-Id: I90ae58bf3e6cc92ca9897f69974733d562e29aaf
2014-10-13 19:03:49 +02:00
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 8323a9038d)

Change-Id: I445f7d0631723043c55da1070498f89965bec7b1
2014-10-13 19:03:49 +02:00
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 953acd56a4)

Change-Id: Ib84212dda3c7875348282726c29e3b79b78b0eac
2014-10-13 19:03:48 +02:00
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 2523aa73cb)

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

Change-Id: I27ab27fc15033d27d0505729f6275fb542c8d473
2014-10-13 19:03:48 +02:00
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 3fca851a20)

Change-Id: I395679bcfc43e94d308d1ceb0c0fbf932b2c378c
2014-10-13 19:03:48 +02:00
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 e2a83d7109)

Change-Id: Ic2f2bf6718310743bb40cef2104fa759a073e6d5
2014-10-13 19:03:48 +02:00
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 3fc4c539aa)

Change-Id: Ia50a8c30134e4cab8a7d3eb70aef13ce1f6187a1
2014-10-13 19:03:48 +02:00
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 e2b8cec05b)

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

(cherry picked from commit 98c54107df)

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

modified:   PATENTS

(cherry picked from commit dab702b357)

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

Change-Id: Id1325c789a990c9a8704e84e99a22d580303eb8a
2014-10-13 18:19:04 +02:00
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 63c2fc02ce)

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

(cherry picked from commit e300c9d819)

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

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

(cherry picked from commit b47fb00ac0)

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

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

Change-Id: Icf68dafd5cf0614ca25b36a0252caa1784ac8059
2014-10-13 18:18:25 +02:00
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
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
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
8af2771813 update ChangeLog
Change-Id: I3b930aa6cb72d17f41e52d645de1d9b2f3a0238b
2014-07-28 17:22:32 -07:00
f59c0b4bde iosbuild.sh: specify optimization flags
explicitly set '-O3 -DNDEBUG'. setting CFLAGS on the command line
overrides the default, resulting in -O0.

Change-Id: I213979f646b1444b1d8e0eb0bb58e9b2c3cc4dd3
2014-07-26 20:40:51 -07:00
8d34ea3e36 update ChangeLog
Change-Id: I5346984d2adff27b64304c154d720456549a9f24
2014-07-24 11:54:02 -07:00
dbc3da66d3 makefile.unix: add vwebp.1 to the dist target
Change-Id: Icf8b3853a9b175688c3b92d6f498ed44c58ca462
2014-07-23 23:41:47 -07:00
89a7c83cd4 update ChangeLog
Change-Id: Ie9c2c7fe53321aefa17905c4322ad3373869ebad
2014-07-23 23:05:49 -07:00
ffe67ee92e Merge "update NEWS for the next release" into 0.4.1 2014-07-23 23:02:19 -07:00
2def1fe635 gif2webp: dust up the help message
* try to avoid trailing '.'
* rationalize capitalization

missed in:
0a8b886 dust up the help message

Change-Id: I6f80736cc8a2ff4f185f63d463a57d5bbf88a0db
2014-07-23 20:03:49 -07:00
fb668d78b3 remove -noalphadither option from README/vwebp.1
+ vwebp's -help output

this is a future option; missed in:
793368e restore decode API compatibility

Change-Id: If920df2cf8de57ebad93a6b98830562149396d8d
2014-07-23 19:54:34 -07:00
e49f693b1f update NEWS for the next release
Change-Id: If708c6b442816f43522b7e5b292f3cba266d614a
2014-07-23 19:25:36 -07:00
cd01358057 Merge "update AUTHORS" into 0.4.1 2014-07-23 17:33:15 -07:00
268d01eb24 update AUTHORS
Change-Id: I1eae9342df7bf4e8e98d5328b2e3eab7cba9fee8
2014-07-23 17:21:04 -07:00
85213b9bbe bump version to 0.4.1
libwebp{,decoder} - 0.4.1
libwebp libtool - 5.1.0
libwebpdecoder libtool - 1.1.0

mux/demux - 0.2.1
libtool - 1.1.0

Change-Id: If593a198f802fd68c7dbbdbe0fc2612dbc44e2df
2014-07-23 17:17:25 -07:00
695f80ae25 Merge "restore mux API compatibility" into 0.4.1 2014-07-23 17:11:33 -07:00
862d296cf9 restore mux API compatibility
protect WebPMuxSetCanvasSize w/a WEBP_MUX_ABI_VERSION check

Change-Id: I6b01af55ebb4cc4c860d3cbf43be722077896748
2014-07-23 16:13:56 -07:00
8f6f8c5dde remove the !WEBP_REFERENCE_IMPLEMENTATION tweak in Put8x8uv
There's no speed diff, so better remove it altogether

Reported in https://code.google.com/p/webp/issues/detail?id=215

Change-Id: I991330de18bec340029d6df5fed0dfb4337e4662
2014-07-23 14:15:40 -07:00
d713a69644 Merge changes If4debc15,I437a5d5f into 0.4.1
* changes:
  restore encode API compatibility
  restore decode API compatibility
2014-07-23 13:56:27 -07:00
c2fc52e4ec restore encode API compatibility
protect WebPConfigLosslessPreset/WebPMemoryWriterClear w/a
WEBP_ENCODER_ABI_VERSION check

Change-Id: If4debc15fee172a3f18079bc2bd29eb8447bc14b
2014-07-22 22:19:55 -07:00
793368e8c6 restore decode API compatibility
protect flip/alpha_dither w/a WEBP_DECODER_ABI_VERSION check

Change-Id: I437a5d5f78800f71b7e7e323faa321f946bf9515
2014-07-22 20:03:52 -07:00
b8984f3151 gif2webp: fix compile with giflib 5.1.0
DGifCloseFile() added an error code output parameter
http://giflib.sourceforge.net/gif_lib.html#compatibility

fixes issue #209

original patch by grizzly dot nyo at gmail

Change-Id: I5554de2bd70dbfd95fd356424ad5fb800ac94592
2014-07-22 17:50:30 -07:00
222f9b1a9d gif2webp: simplify giflib version checking
introduce LOCAL_GIF_PREREQ/VERSION similar to the GCC variants in dsp.

Change-Id: I00ba5d523047b3b1c14ade992172e75e69043eb3
2014-07-22 17:41:55 -07:00
d2cc61b7dd Extend MakeARGB32() to accept Alpha channel.
Change-Id: I31b8e2d085000e2e3687a373401e4f655f11fc42
2014-07-21 14:49:38 -07:00
4595b62b7c Merge "use explicit size of kErrorMessages[] arrays" 2014-07-21 13:37:49 -07:00
157de01507 Merge "Actuate memory stats for PRINT_MEMORY_INFO" 2014-07-21 13:31:15 -07:00
fbda2f499c JPEG decoder: delay conversion to YUV to WebPEncode() call
We store the raw RGB samples decoded from JPEG, and avoid precision loss.

Note that this may increase the encoding time reported by
cwebp -v, since RGB->YUV now occur during WebPEncode call
(in case of lossy), instead of ReadJPEG().
This also increases the memory use, since we're carying the
source ARGB samples around.

Change-Id: Ic2180206cfc9f5574f391e91c3b89b9d81695d01
2014-07-21 22:26:22 +02:00
0b747b1b39 use explicit size of kErrorMessages[] arrays
Change-Id: If02864e3a07ae37814bf379bf347862cd2871bf4
2014-07-21 13:21:56 -07:00
3398d81ac3 Actuate memory stats for PRINT_MEMORY_INFO
Change-Id: If7eac591b5205990ca452ca02b084a908482850a
2014-07-21 13:16:18 -07:00
6f3202be98 Merge "move WebPPictureInit to picture.c" 2014-07-21 11:47:17 -07:00
6c347bbb0c move WebPPictureInit to picture.c
Change-Id: I4b8c352cfd47256d0c3827334a6942c1caf742f6
2014-07-21 14:16:19 +02:00
fb3acf19d7 fix configure message for multi-thread
it's not just decoding, but general multi-threading

Change-Id: I9d1b7e14f05b93a0eb92955526b7019c2b0df20c
2014-07-21 00:21:50 -07:00
40b086f78a configure: check for _beginthreadex
fixes thread support detection in e.g., cross-compiles/mingw installs
without libpthread, the behavior is unchanged in mingw installs with
libpthread. in the latter case although libpthread is detected the
windows api (_beginthreadex) path is being used.

Change-Id: Ie5f39f15f380731a1006a2497496d627f08fa103
2014-07-20 14:56:37 -07:00
1549d62067 reorder the YUVA->ARGB and ARGB->YUVA functions correctly
+ rework few loops
+ consolidate few error-checks / error-reporting
+ don't modify picture->colorspace in Import() for ARGB output

Change-Id: Iae6da9b50acc738c59b85c3ee64efbaf6af8bffc
2014-07-18 07:15:54 -07:00
c6461bfda2 Merge "extract colorspace code from picture.c into picture_csp.c" 2014-07-16 17:01:28 -07:00
736f2a175e extract colorspace code from picture.c into picture_csp.c
had to refactor few functions here and there.

Change-Id: I86fde6fec7c2fc7eb48f0ecf327dbbd2bd40b9d4
2014-07-16 16:37:26 -07:00
645daa033b Merge "configure: check for -Wformat-security" 2014-07-16 03:23:29 -07:00
abafed861c configure: check for -Wformat-security
from debian hardening:
https://wiki.debian.org/Hardening#DEB_BUILD_HARDENING_FORMAT_.28gcc.2Fg.2B-.2B-_-Wformat_-Wformat-security_-Werror.3Dformat-security.29

Change-Id: I6729fb92e7286532151c2dde93b876476ed2af96
2014-07-14 22:52:15 -07:00
fbadb48026 split monolithic picture.c into picture_{tools,psnr,rescale}.c
Change-Id: Ia5eb5496e4337e5bac8203872c5b014cad21c4f9
2014-07-12 09:13:33 -07:00
c76f07ecc2 dec_neon/TransformAC3: initialize vector w/vcreate
replaces {} initialization gnu-ism

Change-Id: I5bedcba1a9c21883207301f07456cc6a843199a0
2014-07-11 15:56:53 -07:00
bb4fc051bf gif2webp: Allow single-frame animations
Some single-frame GIF images have a canvas larger than the frame rectangle. For
such images, we retain the ANMF, ANIM and VP8X chunks in the output WebP file.
This ensures that the full canvas width/height and frame offsets are retained.

Change-Id: I3ebae4893f953984de4072fda0938411de787a29
2014-07-10 15:21:05 -07:00
46fd44c104 thread: remove harmless race on status_ in End()
if a thread was still doing work when End() was called there'd be a race
on worker->status_. in these cases, however, the specific value is
meaningless as it would be >= OK and the thread would have been shut
down properly, but we'll check 'impl_' instead to avoid any potential
TSan/DRD reports.

Change-Id: Ib93cbc226a099f07761f7bad765549dffb8054b1
2014-07-08 20:32:29 -07:00
5a1a7264fc Merge "configure: check for __builtin_bswapXX()" 2014-07-05 13:43:44 -07:00
6781423b7d configure: check for __builtin_bswapXX()
defines HAVE_BUILTIN_BSWAP16/32/64
updated endian_inl.h to have a non-configure fallback for gcc and clang
BSwap16() now uses __builtin_bswap16 if available

Change-Id: Ia04ee07b39303c4b247df96d84f298fb8a81f389
2014-07-05 12:35:13 -07:00
6450c48d4c configure: fix iOS builds
possibly other cross-compiles; avoids misusing -mavx2/-msse2 in these
cases by checking the usability of the associated intrinsics header
files.

iosbuild.sh has been broken since at least:
6e61a3a configure: test for -msse2

Change-Id: Ic650d9eec70f6a5de7d89997b3b425a4aa50ccd9
2014-07-04 21:48:36 -07:00
6422e683af VP8LFillBitWindow: enable fast path for 32-bit builds
also reduce the load size from 64 to 32 bits as the top 32 bits are
being shifted away in the operation.

the change is neutral speed-wise on x86_64 as is the change in load size
on x86, but it gives a slight improvement on 32-bit arm.
x86 is improved ~13%, 32-bit arm ~3.7%
aarch64 is untested but will likely benefit as well.

Change-Id: Ibcb02a70f46f2651105d7ab571afe352673bef48
2014-07-04 14:42:47 -07:00
4f7f52b2a1 VP8LFillBitWindow: respect WEBP_FORCE_ALIGNED
Change-Id: I23eddf01590de002efc21d8c7acc545a08fc3e48
2014-07-04 13:53:29 -07:00
e458badcc3 endian_inl.h: implement htoleXX with BSwapXX
+ s/htole(16|32)/HToLE$1/ to avoid any name conflicts

Change-Id: Ic1c84711557e50f73d83ca5aa2b3992ac6738216
2014-07-04 12:16:36 -07:00
f2664d1aab endian_inl.h: add BSwap16
+ use it in VP8LoadNewBytes()

Change-Id: I701d3652dc0cbd553852978702ef68c2657bca1c
2014-07-04 12:16:28 -07:00
6fbf5345e3 Merge "configure: add --enable-aligned" 2014-07-04 00:12:28 -07:00
dc0f479d6a configure: add --enable-aligned
forces aligned memory reads (via memcpy) in the VP8 bit reader, useful
for platforms that don't support unaligned loads.

Change-Id: Ifa44a9a1677fbdc6a929520f9340b7e3fcbd6692
2014-07-03 23:30:09 -07:00
9cc69e2b53 Merge "configure: support WIC + OpenGL under mingw64" 2014-07-03 23:24:16 -07:00
257adfb0be remove experimental YUV444 YUV422 and YUV400 code
(never used)

Change-Id: I12a886703592133939607df05132e9b498f916c1
2014-07-03 22:26:25 -07:00
10f4257c3b configure: support WIC + OpenGL under mingw64
fixes issue #211

original patch by grizzly dot nyo at gmail

Change-Id: Ie7bf63d24c112e7e351979da4bebcb690a831c5d
2014-07-03 18:57:07 -07:00
380cca4f2c configure.ac: add AC_C_BIGENDIAN
this defines WORDS_BIGENDIAN, replacing uses of
__BIG_ENDIAN__/__BYTE_ORDER__ with it

+ fixes lossless BGRA output with big-endian toolchains
  that do not define __BIG_ENDIAN__ (codesourcery mips gcc)

Change-Id: Ieaccd623292d235343b5e34b7a720fc251c432d7
2014-07-03 18:15:50 -07:00
ee70a90187 endian_inl.h: add BSwap64
Change-Id: I66672b770500294b8f4ee8fa4bf1dfff1119dbe6
2014-07-03 13:35:34 -07:00
47779d46c8 endian_inl.h: add BSwap32
Change-Id: I96e3ae49659307024415d64587e6312888a0070f
2014-07-03 13:28:13 -07:00
d5104b1ff6 utils: add endian_inl.h
moves the following to this header:
- htole*() definitions from bit_writer.c
- __BIG_ENDIAN__ fallback define from bit_reader_inl.h

Change-Id: I7fff59543f08a70bf8f9ddac849b72ed290471b1
2014-07-03 13:07:14 -07:00
58ab622437 Merge "make alpha-detection loop in IsKeyFrame() in good x/y order" 2014-07-02 22:38:41 -07:00
9d5629025c make alpha-detection loop in IsKeyFrame() in good x/y order
Change-Id: Ifeeb855e66c7b6b849e8584787dc24e7371b1e67
2014-07-02 21:03:35 -07:00
516971b136 lossless: Remove unaligned read warning
(typecast uint32 pointer to uint64).
The proposed change is little (0.05%) slower but avoids uint32 to uint64
pointer conversion.

Change-Id: I6b8828077ea1324fabd04bfa7e7439e324776250
2014-07-02 20:55:27 -07:00
b8b596f6c3 Merge "configure.ac: add an autoconf version prerequisite" 2014-07-02 19:26:39 -07:00
34b02f8cb0 configure.ac: add an autoconf version prerequisite
ax_pthread.m4 uses AS_CASE() which was added in 2.60

Change-Id: Ifafe2271a8814c734a20d24048e9b24925e13077
2014-07-01 20:02:58 -07:00
e59f53600f neon: normalize vdup_n_* usage
with constants, prefer this over vmov_n_* or vcreate_*

Change-Id: Ia84b2a82faea58e2626211a7e2257e0ba4af358a
2014-07-01 00:55:05 -07:00
6ee7160dd2 Merge changes I0da7b3d3,Idad2f278,I4accc305
* changes:
  neon: add INIT_VECTOR4
  neon: add INIT_VECTOR3
  neon: add INIT_VECTOR2
2014-07-01 00:48:38 -07:00
abc02f2492 Merge "fix (uncompiled) typo" 2014-07-01 00:29:19 -07:00
bc03670f01 neon: add INIT_VECTOR4
used to initialize NxMx4 vector types
replaces initialization via '{{ }}' gnu-ism.

Change-Id: I0da7b3d321f3d48579b7863fb2e4d3f449ae7f5e
2014-07-01 00:18:23 -07:00
6c1c632b03 neon: add INIT_VECTOR3
used to initialize NxMx3 vector types
replaces initialization via '{{ }}' gnu-ism.

Change-Id: Idad2f278ab104cf2cc650517194258ce3cfb37b4
2014-06-30 23:53:23 -07:00
dc7687e51b neon: add INIT_VECTOR2
used to initialize NxMx2 vector types
replaces initialization via '{{ }}' gnu-ism.

Change-Id: I4accc305c7dd4c886b63c22e38890b629bffb139
2014-06-30 23:52:42 -07:00
4536e7c49c add WebPMuxSetCanvasSize() to the mux API
previously, the final canvas size was adjusted tightly from the
animation frames. Now, it can be specified separately (to be larger, in particular).

calling WebPMuxSetCanvasSize(mux, 0, 0) triggers the 'adjust tightly' behaviour.
This can be useful after calling WebPMuxCreate() if further image addition
is expected.

-> Fixed gif2webp accordingly.

also: made WebPMuxAssemble() more robust by systematically zero-ing WebPData.

Change-Id: Ib4f7eac372cf9dbf6e25cd686a77960e386a0b7f
2014-06-30 07:00:49 +02:00
824eab1086 fix (uncompiled) typo
output was not properly descaled when compiled
without USE_GAMMA_COMPRESSION

Change-Id: I5282c9573cfcfbef4be22b6b3cdec7e16cad9c1c
2014-06-27 17:10:25 +02:00
1f3e5f1e60 remove unused 'shift' argument and QFIX2 define
this will remove a warning about the shift amount not being
an immediate (=constant).

Change-Id: Ie9a00fefdb9a07ec8994fb113f24234518bc878a
Also: fix the NULL sharpen argument mismatch.
2014-06-26 00:44:12 -07:00
8e867051fd Merge "VP8LoadNewBytes: use __builtin_bswap32 if available" 2014-06-25 02:15:17 -07:00
1b6a263566 Merge "Fix handling of weird GIF with canvas dimension 0x0" 2014-06-25 02:14:54 -07:00
1da3d46138 VP8LoadNewBytes: use __builtin_bswap32 if available
mostly to balance the use of bswap64, some gcc platforms are already
interpreting the default case the same

Change-Id: Icf860f55b3f16bea349a7d721e6d6abeeb4e5cf3
2014-06-24 23:24:36 -07:00
1582e402fd Fix handling of weird GIF with canvas dimension 0x0
Similarly to Chrome, we then use the first sub-rectangle
to set the canvas size.

Also: add check for too-large GIF dimensions (>MAX_CANVAS_SIZE)

Change-Id: Idce55f1e6f6982a8f0e082aac540e16b530e023e
2014-06-24 17:40:40 +02:00
b8811dac12 Merge "rename interface -> winterface" 2014-06-24 00:44:11 -07:00
db8b8b5fc2 Fix logic in the GIF LOOP-detection parsing
We align with Blink/Chromium code by:
  - checking for ANIMEXTS1.0 signature too
  - using ByteCount >= 3 instead of requiring ByteCount==3

Change-Id: Idc484ca62878517df3dccb1fdb3bb45104a5e066
see: http://odur.let.rug.nl/kleiweg/gif/netscape.html
2014-06-23 23:26:36 +02:00
25aaddc84c rename interface -> winterface
to avoid name clash on win32

Change-Id: Ia4ad3d4528df4652bab803f9a9544e21e6c4b177
2014-06-23 14:21:22 -07:00
5584d9d2fc make WebPSetWorkerInterface() check its arguments
Change-Id: I522c58cfe05e864a50cacb58bdfa14d5369c6d60
2014-06-23 07:39:56 +02:00
a9ef7ef991 Merge "cosmetics: update thread.h comments" 2014-06-19 23:23:06 -07:00
c6af999168 Merge "dust up the help message" 2014-06-19 23:12:02 -07:00
0a8b8863cc dust up the help message
* try to avoid trailing '.'
* rationalize capitalization

Change-Id: I50939baf01b1ab44d3031eee916ba51f2338af8a
2014-06-20 07:13:11 +02:00
a9cf31913c cosmetics: update thread.h comments
WebPWorker*() are now part of WebPWorkerInterface; refer to them with
unadorned names.

Change-Id: Iae1dd59f1e545cba6dd8c18f26ba60eb9a84419b
2014-06-19 19:31:10 -07:00
27bfeee43a QuantizeBlock SSE2 Optimization:
Another store to load forward block was detected coming from the function
FTransform.
FTransform save the output data 4 times 8 bytes each. when this data is
later being loaded by the QuantizeBlock function in one chunk of 16 bytes
that caused a store to load forward block.
The fix was done in the FTransform function where each two consecutive 8 bytes
were merged into one 16 bytes register and saved into the memory.
This fix gives ~21% function level gain and 1.6% user level gain.

Change-Id: Idc27c307d5083f3ebe206d3ca19059e5bd465992
2014-06-18 16:22:00 -07:00
2bc0dc3edc Merge "webpmux: warn when odd frame offsets are used" 2014-06-18 12:18:09 -07:00
3114ebe46c Merge changes Id8edd3c1,Id418eb96,Ide05e3be
* changes:
  examples/Android.mk: add cwebp
  Android.mk: move dwebp to examples/Android.mk
  Android.mk: add ENABLE_SHARED flag
2014-06-18 12:17:15 -07:00
c072663493 webpmux: warn when odd frame offsets are used
offsets are stored as (x/2, y/2)

Change-Id: Ic8f727ab7996a84c1f8c57f4f6dbaf8701bf8eae
2014-06-18 10:47:23 -07:00
c5c6b408b1 Merge "add alpha dithering for lossy" 2014-06-18 07:32:24 -07:00
d51467841e examples/Android.mk: add cwebp
Change-Id: Id8edd3c17d82e4ab0087c315cd3ead1cb285e714
2014-06-17 23:41:12 -07:00
ca0fa7c7a5 Android.mk: move dwebp to examples/Android.mk
this depends on the top-level Android.mk for shared flags

Change-Id: Id418eb9639e839518a921ffcb6a376ce10aafbd2
2014-06-17 23:41:01 -07:00
73d8fca01e Android.mk: add ENABLE_SHARED flag
builds libwebp.so instead of libwebp.a
$ ndk-build ENABLE_SHARED=1

Change-Id: Ide05e3be4f9848852e6d7e9d99abe11344419241
2014-06-17 23:30:20 -07:00
6e93317f5b muxread: fix out of bounds read
ChunkVerifyAndAssign() expects to have at least 8 bytes to work with,
but was only checking for the presence of 4.

Change-Id: I8456b15d872de24a90c1e8fbfba463391ced5c7f
2014-06-17 12:53:28 -07:00
8b0f6a4802 Makefile.vc: fix CFLAGS assignment w/HAVE_AVX2=1
there's no '+=' operator

Change-Id: Icd6fe684bd468827339f0d73643b325c8477d5c5
2014-06-16 20:23:20 -07:00
bbe32df1e3 add alpha dithering for lossy
new options:
 dwebp -alpha_dither
 vwebp -noalphadither

When the source was marked as quantized, we use a threshold-averaging
filter to smooth the decoded alpha plane.
Note: this option forces the decoding of alpha data in one pass, and
might slow the decoding a bit.

The new field in WebPDecoderOptions struct is 'alpha_dithering_strength'
(0 by default, means: off). Max strength value is '100'.

Change-Id: I218e21af96360d4781587fede95f8ea4e2b7287a
2014-06-14 00:06:16 +02:00
790207679d Merge "make error-code reporting consistent upon malloc failure" 2014-06-13 00:25:30 -07:00
77bf4410f7 make error-code reporting consistent upon malloc failure
Sometimes, the error-code was not set correctly.
We now return OUT_OF_MEMORY everytimes it's appropriate
(tested using MALLOC_FAIL_AT mechanism)

Took the opportunity to clean-up the code and dust the error
code returned (some were erroneously set to INVALID_CONFIGURATION)

Change-Id: I56f7331e2447557b3dd038e245daace4fc82214c
2014-06-13 08:45:12 +02:00
7a93c000ee **/Makefile.am: remove unused AM_CPPFLAGS
only 1 of <lib>_CPPFLAGS and AM_CPPFLAGS is used, with the former
getting precedence when it's defined. configure's DEFAULT_INCLUDES is
covering what's necessary given the include paths are all source
relative.

Change-Id: I7d14076acd266b28a88a3d92bcc3d7165284d5f3
2014-06-12 11:59:05 -07:00
24e3080571 Add an interface abstraction to the WebP worker thread implementation
This allows custom implementations of threading mecanism.

Patch by Leonhard Gruenschloss.

Change-Id: Id8ea5917acd2f24fa8bce79748d1747de2751614
2014-06-12 11:35:44 +02:00
d6cd6358ff Merge "fix orig_rect==NULL case" 2014-06-12 00:48:30 -07:00
2bfd1ffaba fix orig_rect==NULL case
Change-Id: I3bb4fbebf59cba2a67681e74530fc0fe51f1958f
2014-06-12 00:26:33 -07:00
059e21c195 Merge "configure: move config.h to src/webp/config.h" 2014-06-11 22:52:07 -07:00
f05fe006c2 properly report back encoding error code in WebPFrameCacheAddFrame()
User-hook can fail but error was not propagated back.

Change-Id: Ic79f9543bf767634a127eccfef90af855ff15c34
Also: some ad-hoc clean-up and API dusting. More to come later...
2014-06-11 23:26:47 +02:00
32b3137936 configure: move config.h to src/webp/config.h
this change has the side-effect of using directory names in the
include, silencing a lint warning.

Change-Id: Ib91cf63a90534e32fadfa5c2372bfdb29f854d02
2014-06-10 23:42:00 -07:00
90090d99b5 Merge changes I7c675e51,I84f7d785
* changes:
  configure: test for -msse2
  rename upsampling_mips32.c to yuv_mips32.c
2014-06-10 16:15:21 -07:00
ae7661b36e makefiles: define WEBP_HAVE_AVX2 when appropriate
more precisely: in makefile.unix and Makefile.vc when HAVE_AVX2=1

Change-Id: Ia93f373eef6595c016d650728f4f64f61764cd48
2014-06-09 16:35:36 -07:00
69fce2ea78 remove the special casing for res->first in VP8SetResidualCoeffs
if res->first = 1, coeffs[0]=0 because of quant.c:749 and line
added at quant.c:744
So, no need for the extra case.
Going forward, TrellisQuantizeBlock() should also be calling
a variant of VP8SetResidualCoeffs() to set the 'last' field.

also: fixes a warning for win64
    + slight speed-up

Change-Id: Ib24b611f7396d24aeb5b56dc74d5c39160f048f0
2014-06-08 06:40:22 +02:00
6e61a3a905 configure: test for -msse2
+ add a WEBP_HAVE_SSE2 to dsp.h

not all 32-bit toolchain configurations will have sse2 enabled by
default

Change-Id: I7c675e511581f93cf55c79f960fa7efa2df4987e
2014-06-07 19:44:08 -07:00
b9d2efc629 rename upsampling_mips32.c to yuv_mips32.c
matches yuv_sse2 added in;
bdfeeba dsp/yuv: move sse2 functions to yuv_sse2.c

Change-Id: I84f7d7858ca6851c956e8366a7c76b45070dcbc3
2014-06-07 12:35:47 -07:00
bdfeebaa01 dsp/yuv: move sse2 functions to yuv_sse2.c
Change-Id: I2f037ff18e7cf07e8801f49b3a89c1e36ef73000
2014-06-05 23:52:54 -07:00
46b32e861a Merge "configure: set WEBP_HAVE_AVX2 when available" 2014-06-05 02:57:42 -07:00
88305db4fc Merge "VP8RandomBits2: prevent signed int overflow" 2014-06-05 01:46:42 -07:00
73fee88c4a VP8RandomBits2: prevent signed int overflow
'diff' at its largest may be INT_MAX; << 1 of anything at or above
1 << 30 will overflow.

Change-Id: Idb2b5a9b55acc2f6d5e32be8baaebee3f89919ad
2014-06-04 23:19:03 -07:00
db4860b355 enc_sse2: prevent signed int overflow
_mm_movemask_epi8 returns a 16-bit mask; << 16 can overflow a signed
int.

Change-Id: Ia0bb0804fe548fb9b0edb3695e82727506066cda
2014-06-04 23:18:22 -07:00
3fdaf4d28c Merge "real fix for longjmp warning" 2014-06-04 03:01:40 -07:00
385e334019 real fix for longjmp warning
the 'volatile' qualifier was at the wrong place

Patch by Paul Pluzhnikov

Change-Id: I26e6f311a0ccd145de640b3505fe92965389c1d9
2014-06-04 11:02:42 +02:00
230a055501 configure: set WEBP_HAVE_AVX2 when available
this is used to set WEBP_USE_AVX2 in files where the build flag won't be
used, i.e., dsp/enc.c, which enables VP8EncDspInitAVX2() to be called

Change-Id: I362f4ba39ca40d3e07a081292d5f743c649d9d7f
2014-06-03 23:29:23 -07:00
a2ac8a420e restore original value_/range_ field order
no speed change, just for coherency

Change-Id: Iaa395bca24f33a14b68ba6920b838ef87d0d0db6
2014-06-03 09:36:56 +02:00
5e2ee56fdd Merge "remove libwebpdspdecode dep on libwebpdsp_avx2" 2014-06-03 00:28:54 -07:00
61362db57c remove libwebpdspdecode dep on libwebpdsp_avx2
it's encode only, libwebpdecoder doesn't need the symbols

Change-Id: I5633dd2017a96e60068ae5384f1ba27898d29f83
2014-06-03 00:05:56 -07:00
42c447aeb0 Merge "lossy bit-reader clean-up:" 2014-06-02 23:53:00 -07:00
479ffd8b5d Merge "remove unused #include's" 2014-06-02 23:07:20 -07:00
9754d39a4e Merge "strong filtering speed-up (~2-3% x86, ~1-2% for NEON)" 2014-06-02 23:06:18 -07:00
158aff9bb9 remove unused #include's
Change-Id: Icd91a4b6a0bde49145f57e3e74a997822c45792c
2014-06-03 08:01:05 +02:00
09545eeadc lossy bit-reader clean-up:
* remove LEFT/RIGHT_JUSTIFY distinction. It's all RIGHT_JUSTIFY now.
* simplify VP8GetSigned(), and add some masking branch-less code. Much
  faster on ARM (~13% speed-up). 8% on x86-64, 5% on MacBook.
* split critical implementation into separate bit_reader_inl.h file that
  is only included where needed (vp8.c / tree.c / bit_reader.c)
* bumped BITS value from 16 to 24 for x86-32b too, since it's a bit faster.

Change-Id: If41ca1da3e5c3dadacf2379d1ba419b151e7fce8
2014-06-03 07:46:55 +02:00
ea8b0a171d strong filtering speed-up (~2-3% x86, ~1-2% for NEON)
Extract loop invariant and avoid storing/loading samples
if they can be re-used. This is particularly interesting when
a transpose is involved (HFilter16i).

Change-Id: I93274620f6da220a35025ff8708ff0c9ee8c4139
2014-06-03 07:14:23 +02:00
6679f8996f Optimize VP8SetResidualCoeffs.
Brings down WebP lossy encoding timings by 5%

Change-Id: Ia4a2fab0a887aaaf7841ce6d9ee16270d3e15489
2014-06-03 06:44:04 +02:00
ac591cf22e fix for gcc-4.9 warnings about longjmp + local variables
Needed to add 'volatile' and some casts.
Relevant excerpt from the 'man longjmp':

===============
The values of automatic variables are unspecified after a call to longjmp() if they meet all the following criteria:
  ·  they are local to the function that made the corresponding setjmp(3) call;
  ·  their values are changed between the calls to setjmp(3) and longjmp(); and
  ·  they are not declared as volatile.
===============

Change-Id: Ic72dc92669513a820369ca52a038afa9ec88091f
2014-05-30 10:19:10 -07:00
4dfa86b29c dsp/cpu: NaCl has no support for xgetbv
or the raw opcode; fixes:
  934ed4: unrecognized instruction

Change-Id: I981870baf0e8b03bf40144ea8ec25eff140d5bc3
2014-05-29 23:02:23 -07:00
4c398699ef Merge "cwebp: fallback to native webp decode in WIC builds" 2014-05-28 15:03:34 -07:00
33aa497e1a Merge "cwebp: add some missing newlines in longhelp output" 2014-05-28 12:52:22 -07:00
c9b340a279 fix missing WebPInitAlphaProcessing call for premultiplied colorspace output
(lossless only)

Change-Id: Ic2d01c8cf9bc1082f07f348733461eb2ee30288a
2014-05-28 10:44:05 +02:00
57897bae09 Merge "lossless_neon: use vcreate_*() where appropriate" 2014-05-28 01:36:13 -07:00
6aa4777b39 Merge "(enc|dec)_neon: use vcreate_*() where appropriate" 2014-05-28 01:34:56 -07:00
0d346e418d Always reinit VP8TransformWHT instead of hard-coding
Change-Id: I2012749ed29bd166d2a96555372f0d9baa784385
2014-05-28 10:21:07 +02:00
7d039fc32d cwebp: fallback to native webp decode in WIC builds
this gives precedence to WIC, but attempts to decode the file as WebP if
it fails

Change-Id: I3d894f39a26aea88897a8ebd345139b82f74f312
2014-05-27 16:28:37 -07:00
d471f424da cwebp: add some missing newlines in longhelp output
+ update README

Change-Id: Ia84d8857d575bc29ab3ce9c0f10264c042067e78
2014-05-27 16:28:02 -07:00
bf0e003067 lossless_neon: use vcreate_*() where appropriate
this is more portable than {} initialization.
more involved cases are left for a follow-up.

Change-Id: If7e111864f287ea0a5de6311454aeda37afbb52a
2014-05-27 16:27:46 -07:00
9251c2f6d2 (enc|dec)_neon: use vcreate_*() where appropriate
this is more portable than {} initialization.
more involved cases are left for a follow-up.

Change-Id: If8783423d17e90694b168a64ba313ed62ce2cc17
2014-05-27 16:26:56 -07:00
399b916d27 lossy decoding: correct alpha-rescaling for YUVA format
The luminance needs to be pre- and post- multiplied by
the alpha value in case of rescaling, for proper averaging.

Also:
- removed util/alpha_processing and moved it to dsp/
- removed WebPInitPremultiply() which was mostly useless
and merged it with the new function WebPInitAlphaProcessing()

Change-Id: If089cefd4ec53f6880a791c476fb1c7f7c5a8e60
2014-05-27 15:27:13 -07:00
78c12ed8e6 Merge "Makefile.vc: add rudimentary avx2 support" 2014-05-27 11:13:40 -07:00
dc5b122f23 try to remove the spurious warning for static analysis
Change-Id: Ib81f16c70a0bfad05021401c1cf6788c974b63bd
2014-05-26 18:31:00 +02:00
ddfefd624c Makefile.vc: add rudimentary avx2 support
similar to makefile.unix:
> nmake /f Makefile.vc CFG=release-static HAVE_AVX2=1

from the msdn:
The /arch:AVX2 option and __AVX2__ macro were introduced in Visual
Studio 2013 Update 2, version 12.0.34567.1
(Update 2, version 12.0.30501.00 seems to work)

Change-Id: I649ee47c9fdc399fc71a8ac8464728608d9b6412
2014-05-23 20:52:02 -07:00
a891164398 Merge "simplify VP8LInitBitReader()" 2014-05-22 22:36:41 -07:00
fdbcd44dd3 simplify VP8LInitBitReader()
gcc was generating very complex code, one for each case of br->len_ values!

also, pretty-fy the mask constants

Change-Id: If62b1e8266f3fe5334517305113038d2ea8a6b42
2014-05-22 21:44:16 -07:00
7c004287af makefile.unix: add rudimentary avx2 support
$ make -f makefile.unix HAVE_AVX2=1

will define -mavx2 for src/dsp/*_dsp.c

Change-Id: Id9651bda54da057cb051dc70f7dcd008a3f803f4
2014-05-22 18:38:40 -07:00
515e35cfb1 Merge "add stub dsp/enc_avx2.c" 2014-05-22 18:28:38 -07:00
a05dc1402c SSE2: yuv->rgb speed-up for point-sampling
- use statically initialized tables (if WEBP_YUV_USE_SSE2_TABLES is defined)
 - use SSE2 row conversion for yuv->ARGB / RGBA / ABGR / RGB / BGR
 - clean-up and harmonize the WebpUpsamplers[] usage.

Change-Id: Ic5f3659a995927bd7363defac99c1fc03a85a47d
2014-05-22 09:56:47 +02:00
178e9a69ae add stub dsp/enc_avx2.c
VP8EncDspInitAVX2 is included in sse2 builds for now, later a configure
flag should be added to avoid the stub when avx2 is unavailable/disabled

Change-Id: I6127b687c273f46f41652aaf8e3b86ae3cfb8108
2014-05-22 00:31:46 -07:00
1b99c09cdc Merge "configure: add a test for -mavx2" 2014-05-22 00:30:10 -07:00
fe72807112 configure: add a test for -mavx2
sets AVX2_FLAGS; currently unused

Change-Id: Ie07ee6c2fa7c1f0748430010a9f207b1723b6def
2014-05-21 23:17:21 -07:00
e46a247c87 cpu: fix check for __cpuidex availability
__cpuidex was added in VS2008 /SP1/

Change-Id: Ie49b00b0246bd6537c0ed583412f17d6fd135baa
2014-05-21 22:59:47 -07:00
176fda2650 fix the bit-writer for lossless in 32bit mode
Sometimes, we can write 18bit or more at time, and it would
overflow the 32bit accumulator.

Also clarified the num-bits limitations (and exposed
VP8L_MAX_NUM_BIT_READ in bit_reader.h)

fixes http://code.google.com/p/webp/issues/detail?id=200

Seems a bit faster (use of local fields for bits_ / used_)

also: added the __QNX__ bswap while at it.

Change-Id: I876db93a931db15b083cf1d838c70105effa7167
2014-05-22 07:19:22 +02:00
541784c710 dsp.h: add a check for AVX2 / define WEBP_USE_AVX2
Change-Id: I90cc870f0bb4426af701779c367587dc2ae79c8b
2014-05-21 20:46:28 -07:00
bdb151ee80 dsp/cpu: add AVX2 detection
currently unused.
https://software.intel.com/en-us/articles/how-to-detect-new-instruction-support-in-the-4th-generation-intel-core-processor-family
http://www.intel.com/content/dam/www/public/us/en/documents/manuals/64-ia-32-architectures-optimization-manual.pdf

Change-Id: I314200f890c58b9a587b902b214f90deb95f0579
2014-05-20 22:48:54 -07:00
ab9f2f8685 Merge "revamp the point-sampling functions by processing a full plane" 2014-05-20 15:21:31 -07:00
a2f8b28905 revamp the point-sampling functions by processing a full plane
-nofancy is slower than fancy upsampler, because the latter has SSE2 optim.

Change-Id: Ibf22e5a8ea1de86a54248d4a4ecc63d514c01b88
2014-05-20 15:13:44 -07:00
ef076026af use decoder's DSP functions for autofilter
-af is now faster (6-7%), since we're using the SSE2 variant
Output is binary the same as before.

Change-Id: If75694594c9501cd486b8f237a810ddcc145cadd
2014-05-20 14:55:05 -07:00
2b5cb32612 Merge "dsp/cpu: add AVX detection" 2014-05-20 01:10:18 -07:00
df08e67e06 dsp/cpu: add AVX detection
currently unused.
https://software.intel.com/en-us/articles/introduction-to-intel-advanced-vector-extensions

similar checks exist in ffmpeg, libyuv. the visual studio inline asm is
based off of libyuv.

Change-Id: I3e233de3492172434e482607a94b99c617f11aad
2014-05-20 00:25:12 -07:00
e2f405c969 Merge "clean-up and slight speed-up in-loop filtering SSE2" 2014-05-20 00:08:40 -07:00
f60957bfd2 clean-up and slight speed-up in-loop filtering SSE2
* remove some sign-bit flipping
* turn some macro into inline functions
* fix some 'const' in signatures
* clarify the int8/uint8 usage

Change-Id: Ib04459ac34cb280c57579c5d79a5efd2f8d5e99d
2014-05-19 23:23:47 -07:00
9fc3ae469f .gitattributes: treat .ppm as binary
Change-Id: I4da7b846f6255078f0ce97fc7e8df9f29271f52a
2014-05-15 23:18:35 -07:00
3da924b5b4 Merge "dsp/WEBP_USE_NEON: test for __aarch64__" 2014-05-14 20:16:18 -07:00
c7164490da Android.mk: always include *_neon.c in the build
the inclusion of the files is harmless when NEON is not enabled and will
allow them to be built with NEON for APP_ABI=arm64-v8a which currently
does not use the '.neon' suffix

Change-Id: I39377876b1b68822c38f4e2396da93c56145fc0f
2014-05-14 00:11:46 -07:00
a577b23a0a dsp/WEBP_USE_NEON: test for __aarch64__
__ARM_NEON__ is unset by current linux gcc/clang + android toolchains
for aarch64/arm64 builds.

Change-Id: Ib2ca172ea6fcf046e4ced19a431088674c99b7f6
2014-05-14 00:07:13 -07:00
54bfffcabc move RemapBitReader() from idec.c to bit_reader code
mostly for coherency and later patch.

Change-Id: Ica8352d67845b6c5b3153435edfb4646c6f24341
2014-05-14 07:07:08 +02:00
34168ecbe4 Merge "remove all unused layer code" 2014-05-08 22:51:13 -07:00
f1e771735a remove all unused layer code
Change-Id: I220590162b24c70f404fe3087f19dd3e6cac3608
2014-05-08 22:37:38 -07:00
b0757db7c6 Code cleanup for VP8LGetHistoImageSymbols.
Fix comments and few nits.
Change-Id: I8fa25ed523f12c6a7bfe125f0e4d638466ba4304
2014-05-08 14:13:47 -07:00
5fe628d35d make the token page size be variable instead of fixed 8192
also changed the token-page layout a little bit to remove
a not-needed field.

This reduces the number of malloc()/free() calls substantially
with minimal increase in memory consumption (~2%).
For the tail of large sources, the number of malloc calls goes
typically from ~10000 to ~100 (e.g.: bryce_big.jpg: 22711 -> 105)

Change-Id: Ib847f41e618ed8c303d26b76da982fbc48de45b9
2014-05-05 14:26:14 -07:00
f948d08c81 memory debug: allow setting pre-defined malloc failure points
MALLOC_FAIL_AT flag can be used to set-up a pre-determined failure
point during malloc calls. The counter value is retrieved using
getenv().
Example usage: export MALLOC_FAIL_AT=37 && cwebp input.png
will make 'cwebp' report a memory allocation error the 37th time
malloc() or calloc() is called.

MALLOC_MEM_LIMIT can be used similarly to prevent allocating more
than a given amount of memory. This is usually less convenient to
use than MALLOC_FAIL_AT since one has to know in advance the typical
memory size allocated.

Both these flags are meant to be used for debugging only!

Also: added a 'total_mem_allocated' to record the overall memory allocated

Change-Id: I9d408095ee7d76acba0f3a31b1276fc36478720a
2014-05-05 14:01:33 -07:00
ca3d746e39 use block-based allocation for backward refs storage, and free-lists
Non-photo source produce far less literal reference and their
buffer is usually much smaller than the picture size if its compresses
well. Hence, use a block-base allocation (and recycling) to avoid
pre-allocating a buffer with maximal size.

This can reduce memory consumption up to 50% for non-photographic
content. Encode speed is also a little better (1-2%)

Change-Id: Icbc229e1e5a08976348e600c8906beaa26954a11
2014-05-05 11:11:55 -07:00
1ba61b09f9 enable NEON intrinsics in aarch64 builds
avoids functions that use vtbl? as in iOS builds these are marked
unavailable

Change-Id: I17aedc3c7dc8f1d5be0941205de0b22c3772ef1b
2014-05-03 12:37:42 -07:00
b9d2bb67d6 dsp/neon.h: coalesce intrinsics-related defines
Change-Id: Ifadd41a5bbf7f99eeb6d75d2b67daa25e0544946
2014-05-03 11:34:07 -07:00
b5c7525897 iosbuild: add support for iOSv7/aarch64
Change-Id: I3a51c77276e245cd871acb18d9d70d109aac000b
2014-05-03 11:14:37 -07:00
9383afd5c7 Reduce number of memory allocations while decoding lossless.
This change reduces the number of calls to WebPSafeMalloc from 200 to
100. The overall memory consumption is down 3% for Lenna image.

Change-Id: I1b351a1f61abf2634c035ef1ccb34050b7876bdd
2014-05-02 01:01:43 -07:00
888e63edc9 Merge "dsp/lossless: prevent signed int overflow in left shift ops" 2014-05-02 00:29:54 -07:00
8137f3edbd Merge "instrument memory allocation routines for debugging" 2014-05-02 00:23:48 -07:00
2aa187360d instrument memory allocation routines for debugging
Some tracing code is activated by PRINT_MEM_INFO flag.
For debugging only! (not thread-safe, and slow).

Change-Id: I282c623c960f97d474a35b600981b761ef89ace9
2014-05-02 00:19:55 -07:00
d3bcf72bf5 Don't allocate VP8LHashChain, but treat like automatic object
the unique instance of VP8LHashChain (1MB size corresponding to hash_to_first_index_)
is now wholy part of VP8LEncoder, instead of maintaining the pointer to VP8LHashChain
in the encoder.

Change-Id: Ib6fe52019fdd211fbbc78dc0ba731a4af0728677
2014-04-30 14:10:48 -07:00
bd6b8619dd dsp/lossless: prevent signed int overflow in left shift ops
force unsigned when shifting by 24.

Change-Id: I453601f33fdf01c516ef66ad23399ae6cbe032b3
2014-04-30 00:10:49 -07:00
b7f19b8311 Merge "dec/vp8l: prevent signed int overflow in left shift ops" 2014-04-29 15:56:54 -07:00
29059d5178 Merge "remove some uint64_t casts and use." 2014-04-29 14:15:40 -07:00
e69a1df4b7 dec/vp8l: prevent signed int overflow in left shift ops
force unsigned when shifting by 24.

Change-Id: I6f9ca5fa2109e59b1d46a909136384fc6dc8ca0b
2014-04-29 14:12:38 -07:00
cf5eb8ad19 remove some uint64_t casts and use.
We use automatic int->uint64_t promotion where applicable.

(uint64_t should be kept only for overflow checking and memory alloc).

Change-Id: I1f41b0f73e2e6380e7d65cc15c1f730696862125
2014-04-29 09:08:25 -07:00
38e2db3e16 MIPS: MIPS32r1: Added optimization for HistogramAdd.
Change-Id: I39622a9c340c4090f64dd10e515c4ef2aa21d10a
2014-04-29 08:36:51 -07:00
e0609ade15 dwebp: fix exit code on webp load failure
on ExUtilLoadWebP() failure no allocated memory will be returned, so
it's safe to exit immediately. additionally, any webp specific problems
will already have been reported as part of the call to
WebPGetFeatures().

broken since:
4a0e739 dwebp: move webp decoding to example_util

Change-Id: Ibc632015a1f52bae7f96d063252624123fa7c2da
2014-04-28 17:22:29 -07:00
bbd358a8e7 Merge "example_util.h: avoid forward declaring enums" 2014-04-28 15:10:12 -07:00
8955da2149 example_util.h: avoid forward declaring enums
doing so is not part of ISO C; removes some pedantic warnings.
use webp/decode.h to pickup VP8StatusCode instead.

Change-Id: I19b35e0f8a36fb7c45944ae9ca86838e08b90548
2014-04-28 14:56:19 -07:00
6d6865f0db Added SSE2 variants for Average2/3/4
The predictors based on Average2 are tad slower.

Following is the performance data for these predictors normalized to
number of instruction cycles (as per valgrind) per operation:
- Predictor6 & Predictor7 now takes 15 instruction cycles compared to 11
  instruction cycles for the C version.
- Predictor8 & Predictor9 now takes 15 instruction cycles compared to 12
  instruction cycles for the C version.

The predictors based on Average4 is faster and Average3 is tad slower:
- Predictor10 (Average4) now takes 23 instruction cycles compared to 25
  instruction cycles for the C version.
- Predictor5 (Average3) now takes 20 instruction cycles compared to 18
  instruction cycles for the C version.

Maybe SSE2 version of Average2 can be improved further. Otherwise, we can
remove the SSE2 version and always fallback to the C version.

Change-Id: I388b2871919985bc28faaad37c1d4beeb20ba029
2014-04-28 14:47:30 -07:00
b3a616b356 make HistogramAdd() a pointer in dsp
* merged the two HistogramAdd/AddEval() into a single call
  (with detection of special case when b==out)
* added a SSE2 variant
* harmonize the histogram type to 'uint32_t' instead
  of just 'int'. This has a lot of ripples on signatures.
* 1-2% faster

Change-Id: I10299ff300f36cdbca5a560df1ae4d4df149d306
2014-04-28 10:09:34 -07:00
c8bbb636ea dec_neon: relocate some inline-asm defines
move simple loop filter defines closer to their use and LOAD* to a
location common with the intrinsics

Change-Id: Iaec506d27bbc9a01be20936e30b68a4b0e690ee3
2014-04-28 00:41:42 -07:00
4e393bb9f1 dec_neon: enable intrinsics-only functions
the complex loop filter has no inline equivalent; the simple loop filter
remains conditional on USE_INTRINSICS: it's left undefined for now.

Change-Id: I4f258e10458df53a7a1819707c8f46b450e9d9d2
2014-04-28 00:39:46 -07:00
ba99a922ab dec_neon: use positive tests for USE_INTRINSICS
makes Simple* layout consistent with the rest of the file

Change-Id: Ib3108b0f2c694c634210e22027c253ea6236a9c6
2014-04-28 00:38:47 -07:00
69058ff813 Merge "example_util: add ExUtilDecodeWebPIncremental" 2014-04-28 00:38:24 -07:00
a7828e8bdb dec_neon: make WORK_AROUND_GCC conditional on version
Change-Id: Ic1b95f8749988de90df7c1ff6c537a21981329db
2014-04-28 00:01:19 -07:00
3f3d717a6c Merge "enc_neon: enable intrinsics-only functions" 2014-04-27 02:05:53 -07:00
de3cb6c820 Merge "move LOCAL_GCC_VERSION def to dsp.h" 2014-04-27 02:04:08 -07:00
1b2fe14de5 example_util: add ExUtilDecodeWebPIncremental
simplifies ExUtilDecodeWebP() call

Change-Id: I33b42ec1c398b9fc0a895ad9deb89ab01a33b3da
2014-04-27 01:58:25 -07:00
ca49e7ad97 Merge "enc_neon: move Transpose4x4 to dsp/neon.h" 2014-04-27 01:11:05 -07:00
ad900abddd Merge "fix warning about size_t -> int conversion" 2014-04-27 01:07:03 -07:00
4825b4360d fix warning about size_t -> int conversion
+ re-order and add some const

Change-Id: I3746520b75699e56e20835d10d1dd9cd9fd6d85d
2014-04-27 00:50:07 -07:00
42b35e086b enc_neon: enable intrinsics-only functions
CollectHistogram / SSE* / QuantizeBlock have no inline equivalents,
enable them where possible and use USE_INTRINSICS to control borderline
cases: it's left undefined for now.

Change-Id: I62235bc4ddb8aa0769d1ce18a90e0d7da1e18155
2014-04-26 19:09:04 -07:00
f937e01261 move LOCAL_GCC_VERSION def to dsp.h
+ add LOCAL_GCC_PREREQ and use it in lossless_neon.c

Change-Id: Ic9fd99540bc3e19c027d1598e4530dfdc9b9de00
2014-04-26 19:09:04 -07:00
5e1a17ef4b enc_neon: move Transpose4x4 to dsp/neon.h
+ reuse it in TransformWHT()

Change-Id: Idfbd0f9b58d6253ac3d65ba55b58989c427ee989
2014-04-26 14:06:04 -07:00
c7b92a5a29 dec_neon: (WORK_AROUND_GCC) delete unused Load4x8
using this in Load4x16 was slightly slower and didn't help mitigate any
of the remaining build issues with 4.6.x.

Change-Id: Idabfe1b528842a514d14a85f4cefeb90abe08e51
2014-04-26 12:36:14 -07:00
8e5f90b086 Merge "make ExUtilLoadWebP() accept NULL bitstream param." 2014-04-26 12:22:53 -07:00
05d4c1b7b3 Merge "cwebp: add webpdec" 2014-04-26 02:25:02 -07:00
ddeb6ac802 cwebp: add webpdec
simple webp decoding, no metadata support

Change-Id: I2752fd1442c87513922878cbf72f001d45b631bc
2014-04-26 02:20:41 -07:00
35d7d095dd Merge "Reduce memory footprint for encoding WebP lossless." 2014-04-26 01:28:43 -07:00
0b896101b4 Reduce memory footprint for encoding WebP lossless.
Reduce calls to Malloc (WebPSafeMalloc/WebPSafeCalloc) for:
- Building HashChain data-structure used in creating the backward references.
- Creating Backward references for LZ77 or RLE coding.
- Creating Huffman tree for encoding the image.
For the above mentioned code-paths, allocate memory once and re-use it
subsequently.

Reduce the foorprint of VP8LHistogram struct by changing the Struct
field 'literal_' from an array of constant size to dynamically allocated
buffer based on the input parameter cache_bits.

Initialize BitWriter buffer corresponding to 16bpp (2*W*H).
There are some hard-files that are compressed at 12 bpp or more. The
realloc is costly and can be avoided for most of the WebP lossless
images by allocating some extra memory at the encoder initializaiton.

Change-Id: I1ea8cf60df727b8eb41547901f376c9a585e6095
2014-04-26 01:14:33 -07:00
f0b65c9a1e make ExUtilLoadWebP() accept NULL bitstream param.
Change-Id: Ifce379873ca39e46d011a1cb829beab89de5f15d
2014-04-26 01:11:44 -07:00
9c0a60ccb3 Merge "dwebp: move webp decoding to example_util" 2014-04-26 01:05:48 -07:00
1d62acf6af MIPS: MIPS32r1: Added optimization for HuffmanCost functions.
HuffmanCost and HuffmanCostCombined optimized and added
'const' to some variables from ExtraCost functions.

Change-Id: I28b2b357a06766bee78bdab294b5fc8c05ac120d
2014-04-24 11:14:57 +02:00
4a0e73904d dwebp: move webp decoding to example_util
this will allow reuse by cwebp

Change-Id: I667252fdacfc5436112d21b040ca299273ec1515
2014-04-22 20:31:41 -07:00
c0220460e9 Merge "Bugfix: Incremental decode of lossy-alpha" 2014-04-22 16:33:12 -07:00
8c7cd722f6 Bugfix: Incremental decode of lossy-alpha
When remapping buffer, br->eos_ was wrongly being set to true for
certain
images.

Also, refactored the end-of-stream detection as a function.

Reported in http://crbug.com/364830

Change-Id: I716ce082ef2b505fe24246b9c14912d8e97b5d84
2014-04-22 16:06:32 -07:00
7955152d58 MIPS: fix error with number of registers.
Some versions of compiler in debug build can't find
a register in class 'GR_REGS' while reloading 'asm'

Number of used registers is decreased in this fix.

Change-Id: I7d7b8172b8f37f1de4db3d8534a346d7a72c5065
2014-04-22 12:06:45 +02:00
b1dabe3767 Merge "Move the HuffmanCost() function to dsp lib" 2014-04-18 12:08:22 -07:00
75b12006e3 Move the HuffmanCost() function to dsp lib
This is to help further optimizations.
(like in https://gerrit.chromium.org/gerrit/#/c/69787/)

There's a small slowdown (~0.5% at -z 9 quality) due to
function pointer usage. Note that, for speed, it's important
to return VP8LStreaks by value, and not pass a pointer.

Change-Id: Id4167366765fb7fc5dff89c1fd75dee456737000
2014-04-18 11:59:48 -07:00
2772b8bd98 MIPS: fix assembler error revealed by clang's debug build
.set at -  Indicates that macro expansions may clobber
           the assembler temporary ($at or $28) register.
           Some macros may not be expanded without this
           and will generate an error message if noat
           is in effect.

"at" also added to the clobber list.

Change-Id: I67feebbd9f2944fc7f26c28496e49e1e2348529d
2014-04-18 18:10:52 +02:00
6653b601ef enc_mips32: fix unused symbol warning in debug
move kC1 / kC2 under __OPTIMIZE__
missed in:
8dec120 enc_mips32: disable ITransform(One) in debug builds

Change-Id: Ic9a12e6d73090c8c06b0e7a4bc56dd9c76b8e596
2014-04-17 23:35:36 -07:00
8dec120975 enc_mips32: disable ITransform(One) in debug builds
avoids:
src/dsp/enc_mips32.c: In function 'ITransformOne':
src/dsp/enc_mips32.c:123:3: can't find a register in class 'GR_REGS' while reloading 'asm'
src/dsp/enc_mips32.c:123:3: 'asm' operand has impossible constraints

Change-Id: Ic469667ee572f25e502c9873c913643cf7bbe89d
2014-04-17 20:10:31 -07:00
98519dd5c1 enc_neon: convert Disto4x4 to intrinsics
Change-Id: I0f00d5af2de2301e8237c2a38a9612d3645abad6
2014-04-17 18:29:31 -07:00
fe9317c9bf cosmetics:
* remove MIPS32 suffix from static function names
* fix a long line in enc_neon.c

Change-Id: Ia1294ae46f471b3eb1e9ba43c6aa1b29a7aeb447
2014-04-16 00:36:19 -07:00
953b074677 enc_neon: cosmetics
fix/remove incorrect comments
+ whitespace

Change-Id: Id1b86beb23e5bf946e73c34ab7066b6ca177f33b
2014-04-15 23:57:03 -07:00
a9fc697cb6 Merge "WIP: extract the float-calculation of HuffmanCost from loop" 2014-04-15 11:33:11 -07:00
3f84b5219d Merge "replace some mult-long (vmull_u8) with mult-long-accumulate (vmlal_u8)" 2014-04-15 07:09:12 -07:00
4ae0533f39 MIPS: MIPS32r1: Added optimizations for ExtraCost functions.
ExtraCost and ExtraCostCombined

Change-Id: I7eceb9ce2807296c6b43b974e4216879ddcd79f2
2014-04-15 15:37:06 +02:00
b30a04cf11 WIP: extract the float-calculation of HuffmanCost from loop
new function: VP8FinalHuffmanCost()

Change-Id: I42102f8e5ef6d7a7af66490af77b7dc2048a9cb9
2014-04-15 14:52:52 +02:00
a8fe8ce231 Merge "NEON intrinsics version of CollectHistogram" 2014-04-15 03:00:45 -07:00
95203d2d1b NEON intrinsics version of CollectHistogram
apparently faster, but we might save some load/store to/from memory
once we settle for the intrinsics-based FTransform()

(also: fixed some #ifdef USE_INTRINSICS problems)

Change-Id: I426dea299cea0c64eb21c4d81a04a960e0c263c7
2014-04-14 16:47:20 +02:00
7ca2e74bb4 replace some mult-long (vmull_u8) with mult-long-accumulate (vmlal_u8)
saves few instructions

Change-Id: If8f464bb2894a209bba94825a4db9267df126d47
2014-04-14 15:14:45 +02:00
41c6efbdc5 fix lossless_neon.c
* some extra {xx , 0 } in initializers
* replaced by vget_lane_u32() where appropriate

Change-Id: Iabcd8ec34d7c853920491fb147a10d4472280a36
2014-04-14 14:27:11 +02:00
8ff96a027a NEON intrinsics version of FTransform
as little bit slower than inlined asm it seems.
So disabled for now.

Change-Id: I8c942846f9bedaed57275675ea9dbbcb8dfd9ccd
2014-04-14 09:58:35 +02:00
0214f4a908 Merge "MIPS: MIPS32r1: Added optimizations for FastLog2" 2014-04-10 08:54:12 -07:00
baabf1ea3a MIPS: MIPS32r1: Added optimizations for FastLog2
Functions VP8LFastLog2Slow and VP8LFastSLog2Slow

also: replaced some "% y" by "& (y-1)" in the C-version
(since y is a power-of-two)

Change-Id: I875170384e3c333812ca42d6ce7278aecabd60f0
2014-04-10 08:32:51 -07:00
3d49871dbe NEON functions for lossless coding
Verified OK, but right now they don't seem faster.
So they are disabled behind a USE_INTRINSICS flag (off for now)

Change-Id: I72a1c4fa3798f98c1e034f7ca781914c36d3392c
2014-04-10 15:32:08 +02:00
3fe0291530 MIPS: MIPS32r1: Added optimizations for SSE functions.
Change-Id: I1287fa65064192cc2edc5c4be2b1974be665b9b4
2014-04-09 11:02:13 +02:00
c503b485b6 Merge "fix the gcc-4.6.0 bug by implementing alternative method" 2014-04-08 23:25:59 -07:00
abe6f48709 fix the gcc-4.6.0 bug by implementing alternative method
previous functions are a bit faster with gcc-4.8, so we keep them
for now.

Change-Id: I4081e5af66fbf606295d8a83875c1b889729b4dc
2014-04-09 07:53:55 +02:00
5598bdecd8 enc_mips32.c: fix file mode
Change-Id: I5a43320e2ea2eebc88c65398acb9ea59b63af1fd
2014-04-08 15:12:54 -07:00
2b1b4d5ae9 MIPS: MIPS32r1: Add optimization for GetResidualCost
+ reorganize the cost-evaluation code by moving some functions
to cost.h/cost.c and exposing VP8Residual

Change-Id: Id976299b5d4484e65da8bed31b3d2eb9cb4c1f7d
2014-04-08 15:28:49 +02:00
f0a1f3cd51 Merge "MIPS: MIPS32r1: Added optimization for FTransform" 2014-04-08 04:17:27 -07:00
7231f610aa MIPS: MIPS32r1: Added optimization for FTransform
Change-Id: I9384dac483e8f98bcfdd277a0a3d6ec7c7a7b297
2014-04-08 04:16:44 -07:00
869eaf6c60 ~30% encoding speedup: use NEON for QuantizeBlock()
also revamped the signature to avoid having to pass the 'first' parameter

Change-Id: Ief9af1747dcfb5db0700b595d0073cebd57542a5
2014-04-08 03:08:22 -07:00
f758af6b73 enc_neon: convert FTransformWHT to intrinsics
slightly faster than the inline asm
in practice not much faster than the C-code in a full NEON build, but
still better overall in an Android-like one that only enables NEON for
certain files.

Change-Id: I69534016186064fd92476d5eabc0f53462d53146
2014-04-08 00:20:19 -07:00
7dad095bb4 MIPS: MIPS32r1: Added optimization for Disto4x4 (TTransform)
Change-Id: Ieb20c5c52b964247cfe46f45f9a7415725bf7c02
2014-04-07 15:04:23 +02:00
2298d5f301 MIPS: MIPS32r1: Added optimization for QuantizeBlock
Change-Id: I6047ab107e4d474e35b5af1dac391d5b3d8c049b
2014-04-07 09:22:35 +02:00
e88150c9b6 Merge "MIPS: MIPS32r1: Add optimization for ITransform" 2014-04-05 10:36:05 -07:00
de693f2502 lossless_neon: disable VP8LConvert* functions
due to breakage with NDK/gcc-4.6 builds

Change-Id: Id96258e710ee33e08a023354b3227f27da986620
2014-04-04 20:38:29 -07:00
4143332b22 NEON intrinsics for encoding
* inverse transform is actually slower with intrinsics + gcc-4.6,
  so is left disabled for now.
  With gcc-4.8, it's a bit faster than inlined assembly.

* Sum of Square error function provide a 2-3% speed up
  There's enabled by default (since there's no inlined-asm equivalent)

Change-Id: I361b3f0497bc935da4cf5b35e330e379e71f498a
2014-04-04 15:02:56 -07:00
0ca2914b23 MIPS: MIPS32r1: Add optimization for ITransform
Change-Id: Ie4c8b9bc3a7826bd443cdebf05386786fafe8c56
2014-04-04 10:50:35 +02:00
71bca5ecf3 dec_neon: use vst_lane instead of vget_lane
results in fewer instructions, small speed improvement

Change-Id: I98de632d09ff09f295368c0d744cb4397b585084
2014-04-03 14:56:26 -07:00
bf06105293 Intrinsics NEON version of TransformOne
+ misc cosmetics

* seems 4% slower than inlined-asm with gcc-4.6
* is a tad faster (<1%) with gcc-4.8
(disabled for now)

Change-Id: Iea6cd00053a2e9c1b1ccfdad1378be26584f1095
2014-04-03 14:41:56 -07:00
19c6f1ba74 Merge "dec_neon: use vld?_lane instead of vset?_lane" 2014-04-03 01:16:29 -07:00
7a94c0cf75 upsampling_neon: drop NEON suffix from local functions
Change-Id: I6583ad74aacf78dcbeb5a0ff0218a39bc3460e5a
2014-04-02 23:24:39 -07:00
d14669c83c upsampling_sse2: drop SSE2 suffix from local functions
Change-Id: I2349c1a8e5e15e1d204642096f84f3202721c297
2014-04-02 23:24:39 -07:00
2ca42a4fb7 enc_sse2: drop SSE2 suffix from local functions
Change-Id: I5d61605a9d410761d50b689b046114f0ab3ba24e
2014-04-02 23:24:36 -07:00
d038e6193b dec_sse2: drop SSE2 suffix from local functions
Change-Id: Ie171778b84038d5b04c5dc6972f6015caf555882
2014-04-02 23:10:39 -07:00
fa52d7525f dec_neon: use vld?_lane instead of vset?_lane
results in fewer instructions, small speed improvement

Change-Id: I61ab48d09a5ce7c5158eac8244d28287457edc7a
2014-04-02 23:03:18 -07:00
c520e77d94 cosmetic: fix long line
Change-Id: Id04b368aea5784a98c705f323b32d35b362742ea
2014-04-02 23:00:50 -07:00
4b0f2dae6f Merge "add intrinsics NEON code for chroma strong-filtering" 2014-04-02 22:57:44 -07:00
e351ec0759 add intrinsics NEON code for chroma strong-filtering
The nice trick is to pack 8 u + 8 v samples into a single uint8x16x_t
register, and re-use the previous (luma) functions

Change-Id: Idf50ed2d6b7137ea080d603062bc9e0c66d79f38
2014-04-03 06:58:21 +02:00
aaf734b8b0 Merge "Add SSE2 version of forward cross-color transform" 2014-04-02 14:18:59 -07:00
c90a902eff Add SSE2 version of forward cross-color transform
Encoding speed is roughly the same.

Change-Id: I6b976d0eb24e1847714e719762cb8403768da66c
2014-04-02 12:21:20 -07:00
bc374ff39e Use histogram_bits to initalize transform_bits.
This change gains back 1% in compression density for method=3 and 0.5% for
method=4, at the expense of 10% slower compression speed.

Change-Id: I491aa1c726def934161d4a4377e009737fbeff82
2014-04-02 11:46:40 -07:00
2132992d47 Merge "Add strong filtering intrinsics (inner and outer edges)" 2014-04-02 00:10:01 -07:00
5fbff3a646 Add strong filtering intrinsics (inner and outer edges)
+ added some work-around gcc-4.6 to make it compile (except one function).
+ lots of revamping

All variants tested ok.
Speed-up is ~5-7%

Change-Id: I5ceda2ee5debfada090907fe3696889eb66269c3
2014-04-02 08:28:55 +02:00
d4813f0cb2 Add SSE2 function for Inverse Cross-color Transform
Lossless decoding is now ~3% faster.

Change-Id: Idafb5c73e5cfb272cc3661d841f79971f9da0743
2014-04-01 15:52:25 -07:00
26029568b7 dec_neon: add strong loopfilter intrinsics
vertical only currently, 2.5-3% faster
placed under USE_INTRINSICS as this change depends on the simple
loopfilter
improves the simple loopfilter slightly thanks to some reorganization

Change-Id: I6611441fa54228549b21ea74c013cb78d53c7155
2014-04-01 01:13:50 -07:00
cca7d7ef0f Merge "add intrinsics version of SimpleHFilter16NEON()" 2014-04-01 00:57:11 -07:00
1a05dfa7f5 windows: fix dll builds
WebPSafe* need to be marked external to allow mux/demux to access them
through libwebp.dll

Change-Id: Ib6620e00d376f7aa5a0550e1e244f759977f97a0
2014-03-31 17:46:12 -07:00
d6c50d8ac2 Merge "add some colorspace conversion functions in NEON" 2014-03-31 13:15:18 -07:00
4fd7c82e6a SSE2 variants of Subtract-Green: Rectify loop condition
When 4 pixels are left, they should be processed with SSE2.

Decoding is marginally faster (~0.4%).
Encoding speed: No observable difference.

Change-Id: I3cf21c07145a560ff795451e65e64faf148d5c3e
2014-03-31 10:51:45 -07:00
97e5fac389 add some colorspace conversion functions in NEON
new file: lossless_neon.c
speedup is ~5%

gcc 4.6.3 seems to be doing some sub-optimal things here,
storing register on stack using 'vstmia' and such.
Looks similar to gcc.gnu.org/bugzilla/show_bug.cgi?id=51509

I've tried adding  -fno-split-wide-types and it does help
the generated assembly. But the overall speed gets worse with
this flag. We should only compile lossless_neon.c with it -> urk.

Change-Id: I2ccc0929f5ef9dfb0105960e65c0b79b5f18d3b0
2014-03-31 17:47:46 +02:00
b9a7a45f1f add intrinsics version of SimpleHFilter16NEON()
It's disable for now, because it crashes gcc-4.6.3 during compilation
with -O2 or -O3. It's been tested OK with -O1.

Code is still globally disabled with USE_INTRINSICS, though.

Change-Id: I3ca6cf83f3b9545ad8909556f700758b3cefa61c
2014-03-31 16:31:31 +02:00
daccbf400d add light filtering NEON intrinsics
disabled for now (but tested OK), thanks to the USE_INTRINSICS #define
We'll activate the code when we're on par with non-intrinsics

Change-Id: Idbfb9cb01f4c7c9f5131b270f8c11b70d0d485ff
2014-03-30 22:15:55 -07:00
af44460880 fix typo in STORE_WHT
was working ok because dst == out

Change-Id: I27095129a11f468422250dd2b8fad8b3bd4e5bbd
2014-03-28 10:34:44 -07:00
6af6b8e1b6 Tune HistogramCombineBin for large images.
Tune HistogramCombineBin for hard images that are larger than 1-2 Mega
pixel and represent photographic images.

This speeds up lossless encoding on 1000 image corpus by 10-12% and compression
penalty of 0.1-0.2%.

Change-Id: Ifd03b75c503b9e886098e5fe6f86be0391ca8e81
2014-03-28 07:09:59 -07:00
af93bdd6bc use WebPSafe[CM]alloc/WebPSafeFree instead of [cm]alloc/free
there's still some malloc/free in the external example
This is an encoder API change because of the introduction
of WebPMemoryWriterClear() for symmetry reasons.

The MemoryWriter object should probably go in examples/ instead
of being in the main lib, though.
mux_types.h stil contain some inlined free()/malloc() that are
harder to remove (we need to put them in the libwebputils lib
and make sure link is ok). Left as a TODO for now.

Also: WebPDecodeRGB*() function are still returning a pointer
that needs to be free()'d. We should call WebPSafeFree() on
these, but it means exposing the whole mechanism. TODO(later).

Change-Id: Iad2c9060f7fa6040e3ba489c8b07f4caadfab77b
2014-03-27 15:50:59 -07:00
51f406a5d7 lossless_sse2: relocate VP8LDspInitSSE2 proto
this is in line with the other dsp files and silences a build warning.

Change-Id: I03ee3032c11d4c731cc10bfa0a2dcb6866756ba2
2014-03-27 15:07:43 -07:00
0f4f721b12 separate SSE2 lossless functions into its own file
expose the predictor array as function pointers instead
of each individual sub-function

+ merged Average2() into ClampedAddSubtractHalf directly
+ unified the signature as "VP8LProcessBlueAndRedFunc"

no speed diff observed

Change-Id: Ic3c45dff11884a8330a9ad38c2c8e82491c6e044
2014-03-27 21:43:55 +01:00
514fc251df VP8LConvertFromBGRA: use conversion function pointers
Change-Id: I863b97119d7487e4eef337e5df69e1ae2a911d4c
2014-03-27 09:00:35 +01:00
6d2f35273d dsp/dec: TransformDCUV: use VP8TransformDC
rather than forcing the C version; this is similar to TransformUV

Change-Id: I2778194f05fca33e9b2b71323e92947c0b395e9a
2014-03-26 16:43:47 -07:00
defc8e1b01 Merge "fix out-of-bound read during alpha-plane decoding" 2014-03-26 15:22:42 -07:00
fbed36433d Merge "dsp: reuse wht transform from dec in encoder" 2014-03-26 15:13:07 -07:00
d846708400 Merge "Add SSE2 version of ARGB -> BGR/RGB/... conversion functions" 2014-03-26 15:01:46 -07:00
207d03b484 fix out-of-bound read during alpha-plane decoding
With -bypass_filter switched on, the lossless-compressed
data is decoded ahead of time (before being transformed and
display). Hence, the last row was called twice.

http://code.google.com/p/webp/issues/detail?id=193

Change-Id: I9e13f495f6bd6f75fa84c4a21911f14c402d4b10
2014-03-26 22:45:03 +01:00
d1b33ad58b 2-5% faster trellis with clang/MacOS
(and ~2-3% on ARM)

We don't need to store cost/score for each node, but only for
the current and previous one -> simplify code and save some memory.

Also made the 'Node' structure tighter.

Change-Id: Ie3ad7d3b678992b396242f56e2ac387fe43852e6
2014-03-26 22:33:01 +01:00
369c26dd3f Add SSE2 version of ARGB -> BGR/RGB/... conversion functions
~4-6% faster lossless decoding

Change-Id: I3ed1131ff2b2a0217da315fac143cd0d58293361
2014-03-26 22:19:00 +01:00
df230f2723 dsp: reuse wht transform from dec in encoder
Change-Id: Ide663db9eaecb7a37fe0e6ad4cd5f37de190c717
2014-03-22 13:25:08 -07:00
80e218d43a Android.mk: fix build with APP_ABI=armeabi-v7a-hard
added in r9d; relax the check to build neon code

Change-Id: Ic52b3fbd3bf53617ee52b07a55b0ed05f6f9b26f
2014-03-20 23:24:39 -07:00
59daf08362 Merge "cosmetics:" 2014-03-18 04:02:33 -07:00
536220084c cosmetics:
- use VP8ScanUV, separate from VP8Scan[] (for luma)
 - fix indentation
 - few missing consts
 - change TrellisQuantizeBlock() signature

Change-Id: I94b437d791cbf887015772b5923feb83dd145530
2014-03-18 03:34:56 -07:00
3e7f34a3fb AssignSegments: quiet array-bounds warning
nb (enc->segment_hdr_.num_segments_) will be in the range
[1, NUM_MB_SEGMENTS].

Change-Id: I5c2bd0bb82b17c99aff39c98b6b1747fc040dc16
2014-03-14 18:47:52 -07:00
3c2ebf58a4 Merge "UpdateHistogramCost: avoid implicit double->float" 2014-03-14 15:50:57 -07:00
cf821c821f UpdateHistogramCost: avoid implicit double->float
all the functions involved return double and later these locals are used
in double calculations. fixes a vs build warning

Change-Id: Idb547104ef00b48c71c124a774ef6f2ec5f30f14
2014-03-14 11:18:52 -07:00
312e638f30 Extend the search space for GetBestGreenRedToBlue
Get back some of the compression gains by extending the search space for
GetBestGreenRedToBlue. Also removed the SkipRepeatedPixels call, as it was not
helping much in yielding better compression density.

Before:
 1000 files, 63530337 pixels, 1 loops => 45.0s (45.0 ms/file/iterations)
 Compression (output/input): 2.463/3.268 bpp, Encode rate (raw data): 1.347 MP/s

After:
1000 files, 63530337 pixels, 1 loops => 45.9s (45.9 ms/file/iterations)
 Compression (output/input): 2.461/3.268 bpp, Encode rate (raw data): 1.321 MP/s

Change-Id: I044ba9d3f5bec088305e94a7c40c053ca237fd9d
2014-03-14 09:56:00 -07:00
1c58526fe1 Fix few nits
Add/remove few casts, fixed indentation.

Change-Id: Icd141694201843c04e476f09142ce4be6e502dff
2014-03-13 13:57:39 -07:00
fef22704ec Optimize and re-structure VP8LGetHistoImageSymbols
Optimize and re-structured VP8LGetHistoImageSymbols method, by using the bin-hash
for merging the Histograms more efficiently, instead of the randomized
heuristic of existing method HistogramCombine.

This change speeds up the Lossless encoding by 40-50% (for method=4 and Q > 50)
with 0.8% penalty in compression density. For lower method, the speed up is 25-30%,
with 0.4% penalty in the compression density.

Change-Id: If61adadb1a041b95def6405aa1fe3b83c3cb25ce
2014-03-13 11:48:37 -07:00
068b14ac57 Optimize lossless decoding.
Restructure PredictorInverseTransform & ColorSpaceInverseTransform to remove
one if condition inside the main/critial loop. Also separated TransformColor &
TransformColorInverse into separate functions and avoid one 'if condition'
inside this critical method.

This change speeds up lossless decoding for Lenna image about 5% and 1000 image
corpus by 3-4%.

Change-Id: I4bd390ffa4d3bcf70ca37ef2ff2e81bedbba197d
2014-03-13 11:27:12 -07:00
5f0cfa80ff Do a binary search to get the optimum cache bits.
This speeds up the lossless encoder by a bit (1-2%), without impacting the
compression density.

Change-Id: Ied6fb38fab58eef9ded078697e0463fe7c560b26
2014-03-13 10:30:32 -07:00
24ca3678f9 Merge "allow 'cwebp -o -' to emit output to stdout" 2014-03-12 14:01:15 -07:00
e12f874eea allow 'cwebp -o -' to emit output to stdout
Change-Id: I423d25898e1ba317ccbf456bb28ce45663a3b3d2
2014-03-12 13:56:15 -07:00
2bcad89b4c allow some more stdin/stout I/O
* allow reading from stdin for dwebp / vwebp
 * allow writing to stdout for gif2webp

by introducing a new function ExUtilReadFromStdin()

Example use: cat in.webp | dwebp -o - -- - > out.png

Note that the '-- -' option must appear *last*
(as per general fashion for '--' option parsing)

Change-Id: I8df0f3a246cc325925d6b6f668ba060f7dd81d68
2014-03-12 19:32:16 +01:00
84ed4b3aa5 fix cwebp.1 typos after patch #69199
Change-Id: I046a54dbb4210319ddb156f49dd9d13d47b0d035
2014-03-11 23:46:50 +01:00
65b99f1c92 add a -z option to cwebp, and WebPConfigLosslessPreset() function
These are presets for lossless coding, similar to zlib.
The shortcut for lossless coding is now, e.g.:
   cwebp -z 5 in.png -o out_lossless.webp

There are 10 possible values for -z parameter:
   0 (fastest, lowest compression)
to 9 (slowest, best compression)

A reasonable tradeoff is -z 6, e.g.
-z 9 can be quite slow, so use with care.

This -z option is just a shortcut for some pre-defined
'-lossless -m xx -q yy' combinations.

Change-Id: I6ae716456456aea065469c916c2d5ca4d6c6cf04
2014-03-11 23:25:35 +01:00
30176619c6 4-5% faster trellis by removing some unneeded calculations.
(We didn't need the exact value of the max_error properly.
We can work with relative values instead of absolute)

Output is bitwise the same as before.

Change-Id: I67aeaaea5f81bfd9ca8e1158387a5083a2b6c649
2014-03-06 15:57:25 +01:00
687a58ecc3 histogram.c: reindent after b33e8a0
b33e8a0 Refactor code for HistogramCombine.

Change-Id: Ia1b4b545c5f4e29cc897339df2b58f18f83c15b3
2014-03-04 00:38:14 -08:00
06d456f685 Merge "~3-4% faster lossless encoding" 2014-03-04 00:17:52 -08:00
c60de26099 ~3-4% faster lossless encoding
by re-arranging some code from SkipRepeatedPixel()

Change-Id: I6c1fd7cd9af22cd9be4234217ff67d7b94f44137
2014-03-04 08:12:59 +01:00
42eb06fc0e Merge "few cosmetics after patch #69079" 2014-03-03 15:13:25 -08:00
82af82644b few cosmetics after patch #69079
Change-Id: Ifa758420421b5a05825a593f6b43504887603ee7
2014-03-03 23:53:08 +01:00
b33e8a05ee Refactor code for HistogramCombine.
Refactor code for HistogramCombine and optimize the code by calculating
the combined entropy and avoid un-necessary Histogram merges.

This speeds up lossless encoding by 1-2% and almost no impact on compression
density.

Change-Id: Iedfcf4c1f3e88077bc77fc7b8c780c4cd5d6362b
2014-03-03 13:50:42 -08:00
ca1bfff53f Merge "5-10% encoding speedup with faster trellis (-m 6)" 2014-03-03 13:09:17 -08:00
5aeeb087d6 5-10% encoding speedup with faster trellis (-m 6)
mostly by:
- storing a single rd-score instead of cost / distortion separately
- evaluating terminal cost only once
- getting some invariants out of the loops
- more consts behind fewer variables

Change-Id: I79451f3fd1143d6537200fb8b90d0ba252809f8c
2014-03-03 22:07:06 +01:00
82ae1bf299 cosmetics: normalize VP8GetCPUInfo checks
- use '!= NULL'
+ dec_neon/STORE_WHT: align '\'s

Change-Id: I0f0ce49bd9c58e771bafb24c51c070d5ebd77e53
2014-02-28 18:47:41 -08:00
e3dd9243cb Merge "Refactor GetBestPredictorForTile for future tuning." 2014-02-28 18:39:27 -08:00
206cc1be5a Refactor GetBestPredictorForTile for future tuning.
This change doesn't impact compression gain or compression speed.

Change-Id: Ia87d8a46c6f1ce0f8974178d75a6b0ba0a6e3696
2014-02-28 11:30:23 -08:00
3cb8406262 Merge "speed-up trellis quant (~5-10% overall speed-up)" 2014-02-27 14:34:01 -08:00
b66f2227c1 Merge "lossy encoding: ~3% speed-up" 2014-02-27 11:42:16 -08:00
4287d0d49b speed-up trellis quant (~5-10% overall speed-up)
store costs[] in node instead of context

Change-Id: I6aeb0fd94af9e48580106c41408900fe3467cc54
also: various cosmetics
2014-02-27 00:06:00 -08:00
390c8b316d lossy encoding: ~3% speed-up
incorporate non-last cost in per-level cost table

also: correct trellis-quant cost evaluation at nodes
(output a little bit different now). Method 6 is ~4% faster.

Change-Id: Ic48bd6d33f9193838216e7dc3a9f9c5508a1fbe8
2014-02-26 05:52:24 -08:00
9a463c4a51 Merge "dec_neon: convert TransformWHT to intrinsics" 2014-02-25 14:36:44 -08:00
e8605e9625 Merge "dec_neon: add ConvertU8ToS16" 2014-02-25 08:56:17 -08:00
4aa3e4122b MIPS: MIPS32r1: rescaler bugfix
Change-Id: I6de6e2488bd5bd58c1f705739e4467feb211f8b4
2014-02-25 14:36:48 +01:00
c16cd99aba Speed up lossless encoder.
Speedup lossless encoder by 20-25% by optimizing:
- GetBestColorTransformForTile: Use techniques like binary search and
  local minima search to reduce the search space.
- VP8LFastSLog2Slow & VP8LFastLog2Slow: Adding the correction factor for
  log(1 + x) and increase the threshold for calling the approximate
  version of log_2 (compared to costly call to log()).

Change-Id: Ia2444c914521ac298492aafa458e617028fc2f9d
2014-02-21 22:13:50 -08:00
9d6b5ff1e6 dec_neon: convert TransformWHT to intrinsics
Change-Id: I34dc1d75ddebab131cfed031764117e3f7b75c6b
2014-02-21 11:23:46 -08:00
2ff0aae2fe dec_neon: add ConvertU8ToS16
Change-Id: Ifc4fb8e7f862e72154d2f2739811b1022d2b9416
2014-02-20 15:35:33 -08:00
77a8f91981 fix compilation with USE_YUVj flag
(not that we'll ever need it, but...)

Change-Id: I9af993c62372097846c5ca6bae8362b59c3502dc
2014-02-20 13:23:18 +01:00
4acbec1bef Merge changes I3b240ffb,Ia9370283,Ia2d28728
* changes:
  dec_neon: TransformAC3: work on packed vectors
  dec_neon: add SaturateAndStore4x4
  dec_neon.c: convert TransformDC to intrinsics
2014-02-19 14:47:33 -08:00
2719bb7e98 dec_neon: TransformAC3: work on packed vectors
pack 2 rows in 1 vector similar to TransformDC

Change-Id: I3b240ffb4f51a632b5c8c2daf54d938333ed4b0d
2014-02-18 19:47:20 -08:00
b7b60ca16c dec_neon: add SaturateAndStore4x4
converts 2 s16 vectors to 2 u8 and store to uint8_t destination;
TransformAC3 can reuse this after a rework

Change-Id: Ia9370283ee3d9bfbc8c008fa883412100ff483d0
2014-02-18 19:42:35 -08:00
b7685d73fe Rescale: let ImportRow / ExportRow be pointer-to-function
Separate the C version from the MIPS32 version and have run-time
initialization during RescalerInit()

Change-Id: I93cfa5691c073a099fe62eda1333ad2bb749915b
2014-02-17 00:58:17 -08:00
e02f16ef45 dec_neon.c: convert TransformDC to intrinsics
no noticeable difference in performance

Change-Id: Ia2d287289c3865ddd0fc99edaf7a030778aa7025
2014-02-14 12:11:58 -08:00
9cba963f9a add missing file
Change-Id: I17eab2fedc64ee3bba941a592ecef765fcd2b402
2014-02-13 21:56:19 -08:00
8992ddb756 use static clipping tables
(shared with mips32)
removed abs1[] table along the way

sub-1% speed-up, but still...

Change-Id: I8c29a8a0285076cb3423b01ffae9fcc465da6a81
2014-02-13 19:32:59 -08:00
0235d5e44b 1-2% faster quantization in SSE2
C-version is a bit faster too (sub-1% faster on ARM)

Change-Id: I077262042f1d0937aba1ecf15174f2c51bf6cd97
2014-02-13 15:55:30 -08:00
b2fbc36c26 fix VC12-x64 warning
"conversion from 'vp8l_atype_t' to 'uint8_t', possible loss of data"

Change-Id: I7607a688d16aca8fae8ce472450f8423c48f3a26
2014-02-12 12:19:32 -08:00
6e37cb942f Merge "cosmetics: backward_references.c: reindent after a7d2ee3" 2014-02-11 16:28:55 -08:00
a42ea9742a cosmetics: backward_references.c: reindent after a7d2ee3
a7d2ee3 Optimize cache estimate logic.

Change-Id: I81dd1eea49f603465dc5f3afae8a101e5205e963
2014-02-11 15:52:22 -08:00
6c32744214 Merge "fix missing __BIG_ENDIAN__ definition on some platform" 2014-02-11 14:51:11 -08:00
a8b6aad155 fix missing __BIG_ENDIAN__ definition on some platform
e.g: mips-gcc doesn't define __BIG_ENDIAN__

Change-Id: Ic06bf453164ddddc69a523e7845a4993e14a1af2
2014-02-11 14:43:44 -08:00
fde2904b8a Increase initial buffer size for VP8L Bit Writer.
Increase the initial buffer size for VP8L Bit Writer from 4bpp to 8bpp.
The resize buffer is expensive (requires realloc and copy) and this additional
memory (0.5 * W * H) doesn't add much overhead on the lossless encoder.

Change-Id: Ic1fe55cd7bc3d1afadc799e4c2c8786ec848ee66
2014-02-11 11:13:21 -08:00
a7d2ee39be Optimize cache estimate logic.
Optimize 'VP8LCalculateEstimateForCacheSize' for lower quality ranges (Q < 50).
The entropy is generally lower for higher cache_bits, so start searching from
higher cache_bits and settle for a local minima, instead of evaluating all
values.

This speeds up the lossless encoding at lower qualities by 10-15%.

Change-Id: I33c1e958515a2549f2e6f64b1aab3f128660dcec
2014-02-11 10:59:01 -08:00
7fb6095b03 Merge "dec_neon.c: add TransformAC3" 2014-02-11 09:17:34 -08:00
bf182e837e VP8LBitWriter: use a bit-accumulator
* simplify the endian logic
* remove the need for memset()
* write 16 or 32 at a time (likely aligned)

Makes the code a bit faster on ARM (~1%)

Change-Id: I650bc5654e8d0b0454318b7a78206b301c5f6c2c
2014-02-11 09:12:45 -08:00
3f40b4a581 Merge "MIPS: MIPS32r1: clang macro warning resolved" 2014-02-11 00:06:36 -08:00
1684f4ee37 WebP Decoder: Mark some truncated bitstreams as invalid
Specifically, check for truncated RIFF and/or VP8(L) chunks.

For more context, see:
https://code.google.com/p/webp/issues/detail?id=185

Change-Id: I91ca2dbf05080660fbc513244fc53adc57fc04b5
2014-02-10 16:35:27 -08:00
acbedac475 MIPS: MIPS32r1: clang macro warning resolved
.set macro - Enables the expansion of macro instructions.

Change-Id: I1e44fe056798aeff803cc97171724d21da1fc2bf
2014-02-10 06:50:11 -08:00
228e4877ab dec_neon.c: add TransformAC3
based on SSE2 version

Change-Id: Icc6782955253c98e83d5984153b596ef5f1c0d34
2014-02-08 12:47:54 -08:00
393f89b763 Android.mk: avoid gcc-specific flags with clang
Change-Id: Idb1ed2bb1dd5d9f65ca07185ef9838e587dc4e64
2014-02-07 20:31:44 -08:00
32aeaf115a revamp VP8LColorSpaceTransform() a bit
-> remove the 'color_transform' multiplier, use more constants, etc.

This function is particularly critical, mostly because of
GetBestColorTransformForTile().
Loop is a bit faster (maybe ~1%)

Change-Id: I90c96a3437cafb184773acef55c77e40c224388f
2014-02-05 10:37:06 +01:00
0c7cc4ca20 Merge "Don't dereference NULL, ensure HashChain fully initialized" 2014-02-03 22:58:37 -08:00
391316fee2 Don't dereference NULL, ensure HashChain fully initialized
Found by clang's static analyzer, they look validly uninitialized
to me.

Change-Id: I650250f516cdf6081b35cdfe92288c20a3036ac8
2014-02-03 21:16:59 -08:00
926ff40229 WEBP_SWAP_16BIT_CSP: remove code dup
and prepare for potentially supporting both RGBA4444 and BARG4444

Change-Id: If5200289bc6338757a2ceb2df1a19de732595052
2014-02-03 13:24:33 -08:00
1d1cd3bbd6 Fix decode bug for rgbA_4444/RGBA_4444 color-modes.
The WEBP_SWAP_16BIT_CSP flag needs to be honored while filling the Alpha (4 bits)
data in the destination buffer and while pre-multiplying the alpha to RGB colors.

Change-Id: I3b07307d60963db8d09c3b078888a839cefb35ba
2014-02-03 09:20:54 -08:00
939e70e7d3 update AUTHORS file
Change-Id: I50e8f20016097cf63eaeb46a8588203a2165b161
2014-01-31 12:08:05 -08:00
8934a622ac cosmetics: *_mips32.c
indent, comments, unused includes

Change-Id: Id0aabc52d05bb633f62aec022155ec27699cf5a0
2014-01-30 18:03:48 -08:00
dd438c9a7d MIPS: MIPS32r1: Optimization of some simple point-sampling functions. PATCH [6/6]
Change-Id: I2020e71e9be5d17d4bf67cabf6c470ca43d5d838
2014-01-29 15:37:31 +01:00
53520911c3 Added support for calling sampling functions via pointers.
Change-Id: Ic4d72e6b175a6b27bcdcc8cd97828e44ea93e743
2014-01-29 15:32:35 +01:00
d16c69749b MIPS: MIPS32r1: Optimization of filter functions. PATCH [5/6]
Change-Id: Ifbd305e0514f09a587db02c3970f22190808503a
2014-01-29 15:03:45 +01:00
04336fc7f8 MIPS: MIPS32r1: Optimization of function TransformOne. PATCH [4/6]
Change-Id: I5b98e2de940977538cf91bfa2128f4d1daa5c170
2014-01-28 20:10:43 -08:00
92d8fc7dd4 MIPS: MIPS32r1: Optimization of function WebPRescalerImportRow. PATCH [3/6]
Change-Id: I32339a8d2d03f1a8d8638563d2b2c9e3a13a4909
2014-01-29 00:12:41 +01:00
bbc23ff34c parse one row of intra modes altogether
(instead of per-macroblock)

speed unchanged.
simplified the context-saving for incremental decoding

Change-Id: I301be581bab581ff68de14c4ffe5bc0ec63f34be
2014-01-28 21:40:40 +01:00
a2f608f9e0 Merge "MIPS: MIPS32r1: Optimization of function WebPRescalerExportRow. [2/6]" 2014-01-28 11:19:25 -08:00
88230854e3 MIPS: MIPS32r1: Optimization of function WebPRescalerExportRow. [2/6]
Change-Id: I420e646deefac5df9a8dcec3b02da8dff02b1167
2014-01-28 11:02:01 -08:00
c5a5b0286f decode mt+incremental: fix segfault in debug builds
VP8GetThreadMethod() may be called with a NULL headers param; correct an
assert.

broken since:
8a2fa09 Add a second multi-thread method

Change-Id: If7b6d1b8f4ec874d343a806cee5f5e6bb6438620
2014-01-27 20:33:05 -08:00
9882b2f953 always use fast-analysis for all methods.
This makes the segmentation overall less prone to
local-optimum  or boundary effect.

(and overall, encoding is a little faster)

Change-Id: I35688098b0f43c28b5cb81c4a92e1575bb0eddb9
2014-01-24 18:17:04 +01:00
000adac011 Merge "autoconf: update ax_pthread.m4" 2014-01-24 01:13:11 -08:00
2d2fc37d98 update .gitignore
- generalize *.pc for libwebp(mux|demux)
- add auto-generated mkinstalldirs

Change-Id: I7543209722d6b64830fa61f88eccf54165920cc4
2014-01-23 19:35:28 -08:00
5bf4255af4 Merge "Make it possible to avoid automagic dependencies" 2014-01-23 12:57:04 -08:00
c1cb1933d5 disable NEON for arm64 platform
The registers and instructions are quite different to 32bit
and the assembly code needs a rewrite.

more info: http://people.linaro.org/~rikuvoipio/aarch64-talk/

Change-Id: Id75dbc1b7bf47f43a426ba2831f25bb8fa252c4f
2014-01-23 12:35:01 -08:00
73a304e953 Make it possible to avoid automagic dependencies
See
 https://wiki.gentoo.org/wiki/Project:Quality_Assurance/Automagic_dependencies
for more info.
This patch makes it possible to request several dependencies not to be
used even if they are present on the system.

Change-Id: Ib32f60c001ade01eda3e89463279725ee4243ca2
2014-01-23 12:29:09 -08:00
4d493f8db2 MIPS: MIPS32r1: Decoder bit reader function optimized. PATCH [1/6]
Solved unaligned load and added MIPS32r1 support for VP8LoadNewBytes.

Change-Id: I7782e668a8f2b9dace0ab6afeaff3449bbc7d90b
2014-01-17 22:58:40 +01:00
c741183c10 make WebPCleanupTransparentArea work with argb picture
the -alpha_cleanup flag was ineffective since we switched cwebp
to using ARGB input always.

Original idea by David Eckel (dvdckl at gmail dot com)

Change-Id: I0917a8b91ce15a43199728ff4ee2a163be443bab
2014-01-17 20:19:16 +01:00
5da185522b add a decoding option to flip image vertically
New API options: WebPDecoderOptions.flip and 'dwebp -flip ...'

it uses negative stride trick.

Also changed the decoder code to support user-supplied
buffers with negative stride, independently of the
WebPDecoderOptions.flip value.

Change-Id: I4dc0d06f0c87e51a3f3428be4fee2d6b5ad76053
2014-01-16 15:48:43 +01:00
00c3c4e114 Merge "add man/vwebp.1" 2014-01-10 17:47:57 -08:00
2c6bb42806 add man/vwebp.1
Change-Id: I3257fdeb7d48af99946f751e3e2cd07660117255
2014-01-10 17:43:03 -08:00
ea59a8e980 Merge "Merge tag 'v0.4.0'" 2014-01-10 17:09:19 -08:00
7574bed43d fix comments related to array sizes
thanks to foivos_g4 at hotmail dot com for spotting this.

Change-Id: I8cd301bae58a6edbc3ef47607654bc21321721ca
2014-01-09 17:30:25 +01:00
0b5a90fdb5 dwebp.1: fix option formatting
Change-Id: I427e003cacb3e71ae6f6adc632dbb93be2eea0e7
2014-01-08 15:16:37 -08:00
effcb0fdfa Merge tag 'v0.4.0'
libwebp 0.4.0
- 12/19/13: version 0.4.0
  * improved gif2webp tool
  * numerous fixes, compression improvement and speed-up
  * dither option added to decoder (dwebp -dither 50 ...)
  * improved multi-threaded modes (-mt option)
  * improved filtering strength determination
  * New function: WebPMuxGetCanvasSize
  * BMP and TIFF format output added to 'dwebp'
  * Significant memory reduction for decoding lossy images with alpha.
  * Intertwined decoding of RGB and alpha for a shorter
    time-to-first-decoded-pixel.
  * WebPIterator has a new member 'has_alpha' denoting whether the frame
    contains transparency.
  * Container spec amended with new 'blending method' for animation.

* tag 'v0.4.0':
  update ChangeLog
  update NEWS description with new general features
  gif2webp: don't use C99 %zu
  cwebp: fix metadata output w/lossy+alpha
  makefile.unix: clean up libgif2webp_util.a
  update Changelog
  bump version to 0.4.0
  update AUTHORS & .mailmap
  update NEWS for 0.4.0

Change-Id: I6df1b512fe0b697192f1f9b29431cd59aa6063d1
2013-12-30 09:57:59 -08:00
7c76255dd4 autoconf: update ax_pthread.m4
from git://git.savannah.gnu.org/autoconf-archive.git
100644 blob d383ad5c6d	m4/ax_pthread.m4

dd94691 AX_PTHREAD: add support for Clang
386b290 AX_PTHREAD: fix support for AIX
e40cfd6 AX_PTHREAD: improve support for AIX

Change-Id: Ic1f1edc656e4e917b88f151493147f650b94242f
2013-12-29 11:56:21 -05:00
fff2a11b03 make -short work with -print_ssim, -print_psnr, etc.
PSNR was always printed when using -short

Change-Id: I826785917961d355a980e4ac27dd1cf1295cb6de
2013-12-23 12:03:00 +01:00
68e7901da5 update ChangeLog
Change-Id: If51472e72adaec0a198a8b09becb8be192153ca8
2013-12-20 00:49:40 -08:00
256e4333e1 update NEWS description with new general features
Change-Id: I22be12d843e84f80965dc5f2cb16ba2475ce16ad
2013-12-20 00:36:47 -08:00
296253407c Merge "gif2webp: don't use C99 %zu" into 0.4.0 2013-12-20 00:06:33 -08:00
3b9f9dd07b gif2webp: don't use C99 %zu
this would require a PRIuS or similar macro for proper platform
compatibility (Visual Studio for instance would be variants of %lu)

Change-Id: I2b9fcb1639db024775fb47dbcf79a2240f3d98f2
2013-12-19 18:52:48 -08:00
b5b2e3c7f5 cwebp: fix metadata output w/lossy+alpha
Change-Id: Ic96da6523fc73a7b67c68ef8a4c9d12081f8a535
2013-12-19 10:17:08 -08:00
ad26df1a05 makefile.unix: clean up libgif2webp_util.a
Change-Id: Iee8650ce91f65f2db568926773d44441633459f3
2013-12-18 23:26:18 -08:00
c3b4557064 update Changelog
Change-Id: I60525ce8dedf0843578c1881f6e140098e01211c
2013-12-18 19:36:44 -08:00
ca84112120 Merge "bump version to 0.4.0" into 0.4.0 2013-12-18 19:33:24 -08:00
8c524db84c bump version to 0.4.0
libwebp{,decoder} - 0.4.0
libwebp libtool - 5.0.0
libwebpdecoder libtool - 1.0.0

mux/demux - 0.2.0
libtool - 1.0.0

Change-Id: Idbd067f95a6af2f0057d6a63ab43176fcdbb767d
2013-12-18 19:20:00 -08:00
eec2398cec update AUTHORS & .mailmap
Change-Id: I5419731cd7ac6a06e42ef12433286a97e8e13bb4
2013-12-18 19:09:11 -08:00
b9bbf6a1a0 update NEWS for 0.4.0
Change-Id: I90327d5169b1dba8245c427a03064d562aa26cc9
2013-12-18 19:05:46 -08:00
c72e08119a Merge "dec/webp.c: don't wait for data before reporting w/h" 2013-12-18 18:47:43 -08:00
5ad653145a dec/frame.c: fix formatting
since 26d842e NEON speed up

+ drop a duplicate and from a comment

Change-Id: I710f46f83b80161064910c7efc16788b88c089fe
2013-12-18 17:16:31 -08:00
f7fc4bc89b dec/webp.c: don't wait for data before reporting w/h
this partially reverts
f626fe2 Detect canvas and image size mismatch in decoder.

the original change would cause calls to e.g., WebPGetInfo to fail until
a portion of the image chunk was available. With lossy+alpha this meant
waiting for the entire ALPH chunk to be received.
this change restores the original behavior -- reporting the values from
VP8X if available -- while retaining some of the added canvas/image size
checks if the image data is available

Change-Id: I6295b00a2e2d0d4d8847371756af347e4a80bc0e
2013-12-18 17:09:04 -08:00
66a32af5e1 Merge "NEON speed up" 2013-12-18 14:17:19 -08:00
26d842eb8f NEON speed up
add TransformDC special case, and make the switch function inlined.
Recovers a few of the CPU lost during the addition of TransformAC3
(only on ARM)

Change-Id: I21c1f0c6a9cb9d1dfc1e307b4f473a2791273bd6
2013-12-18 22:32:58 +01:00
f307f98b21 Merge "webpmux: let -- stop parameter parsing" 2013-12-18 11:05:43 -08:00
fe051da772 Merge "README: add a section on gif2webp" 2013-12-18 11:02:55 -08:00
6fd2bd626f Merge "manpage pedantry" 2013-12-18 10:57:27 -08:00
4af19007a4 README: add a section on gif2webp
Change-Id: Ie701da16223df7482f7b017150242ba2d381d0b5
2013-12-18 10:49:49 -08:00
6f36ade926 manpage pedantry
from man-pages (7):
provides a comma-separated list of related man pages, ordered by section
number and then alphabetically by name, possibly followed by other
related pages or documents. Do not terminate this with a period.

Change-Id: I6763b3b3a89f3c2e9ed5c1a4e9d05fb9ce85dd40
2013-12-17 23:30:34 -08:00
f9016cb964 README: update dwebp options
Change-Id: I25300e374215578d091557380ce3dc599d58bd49
2013-12-17 21:51:41 -08:00
b4fa0a47ea webpmux: let -- stop parameter parsing
this enables webpmux to accept input files starting with '-' when using
-get/-set/-strip; -info & -frame expect an input file as one of their
parameters so no changes are necessary there.

Change-Id: I154eb6dc388258a7fb743ec76ba869bf9589be1b
2013-12-17 20:50:46 -08:00
a9a20acfa6 gif2webp: Add a multi-threaded encode option
Change-Id: If16a5f434e0ab2965a7ac9392633ecaf8c4aff46
2013-12-17 17:01:59 -08:00
495bef413d fix bug in TrellisQuantize
the *quantized* level should be clipped to 2047, not the
original coeff.
(similar problem was fixed in the regular quantize function
quite some time ago)

Change-Id: I2fd2f8d94561ff0204e60535321ab41a565e8f85
2013-12-17 11:08:01 -08:00
605a712701 simplify __cplusplus ifdef
drop c_plusplus which is from a quite ancient pre-standard compiler

Change-Id: I9e357b3292a6b52b14c2641ba11f4f872c04b7fb
2013-12-16 20:16:02 -08:00
33109f990a Merge "drop: ifdef __cplusplus checks from C files" 2013-12-16 20:13:09 -08:00
7f9de0b948 Merge changes I994a5587,I8467bb71,I13b50688,I1e2c9c7b
* changes:
  gif2webp: let -- stop parameter parsing
  vwebp: let -- stop parameter parsing
  cwebp: let -- stop parameter parsing
  dwebp: let -- stop parameter parsing
2013-12-16 16:53:27 -08:00
5459030be0 gif2webp: let -- stop parameter parsing
this enables gif2webp to accept input files starting with '-'

Change-Id: I994a5587e16e3af83ca45bfda8caf2dc39068b6c
2013-12-16 15:15:20 -08:00
a4b0aa06ee vwebp: let -- stop parameter parsing
this enables vwebp to accept input files starting with '-'

Change-Id: I8467bb719ba745b2aa14a5c5ce2ff392cd9601d5
2013-12-16 15:14:00 -08:00
98af68fe26 cwebp: let -- stop parameter parsing
this enables cwebp to accept input files starting with '-'

Change-Id: I13b506886c3df8a4e8fb350f3d365eaf7e072a4a
2013-12-16 15:13:54 -08:00
a33831e21a dwebp: let -- stop parameter parsing
this enables dwebp to accept input files starting with '-'

Change-Id: I1e2c9c7bc2963d77be039c99e72f744560f0b0a2
2013-12-16 15:13:32 -08:00
363012497b add some checks on error paths
malloc failure could lead to free'ing non-initialized pointers

Change-Id: I8156aac1fce9a47825cfd0d88eb2bd8c38a630d5
2013-12-16 13:33:45 -08:00
ce4c713904 Merge "autoconf: add --disable-wic" 2013-12-16 10:45:11 -08:00
5227d99146 drop: ifdef __cplusplus checks from C files
the prototypes are already marked in the headers

Change-Id: I172fe742200c939ca32a70a2299809b8baf9b094
2013-12-13 11:42:13 -08:00
f64535591c dwebp.1: fix typo
ICM4 -> IMC4

Change-Id: I065a1ac0dfd0b60efa782bc1a4df1adcb28b90e4
2013-12-12 20:38:23 -08:00
f91034f241 Merge "cwebp: print metadata stats when no output file is given" 2013-12-12 19:28:35 -08:00
d49345533f gif2webp: Backward compatibility for giflib version <= 4.1.3
Fixes https://code.google.com/p/webp/issues/detail?id=172

We use 'int' instead of 'GifWord', which was introduced in version
4.1.4.

Tested OK on 4.1.3
(http://sourceforge.net/projects/giflib/files/giflib-4.x/giflib%204.1.3/)
and 5.0.4

Change-Id: I77628b0f9175a91eb3a22e64fc55dd00633add1f
2013-12-11 08:46:38 -08:00
4c617d3286 gif2webp: Disable output of ICC profile by default
This is to discourage generation of animated WebP images with ICC
profile, as
the real-world use-case for such images is rare at best.

Output of ICC/XMP metadata is now controlled by the '-metadata' option.

Change-Id: I8e3e29878c32bf46cbc661f50661bac602603c43
2013-12-10 14:53:06 -08:00
73b731fb42 introduce a special quantization function for WHT
WHT is somewhat a special case: no sharpen[] bias, etc.
Will be useful in a later CL when precision of input is changed.

Change-Id: I851b06deb94abdfc1ef00acafb8aa731801b4299
2013-12-10 14:21:47 +01:00
41c0cc4b9a Make Forward WHT transform use 32bit fixed-point calculation
This is in preparation for a future change where input will
be 16bit instead of 12bit

No speed diff observed.

Note that the NEON implementation was using 32bit calc already.

Change-Id: If06935db5c56a77fc9cefcb2dec617483f5f62b4
2013-12-10 06:10:52 +01:00
a3359f5d2c Only compute quantization params once
(all quantization params #1..#15 are the same)

Change-Id: If04058bd89fe2677b5b118ee4e1bcce88f0e4bf5
2013-12-10 05:36:23 +01:00
7049043775 cwebp: print metadata stats when no output file is given
this is more consistent with the encode stats

Change-Id: I5793062b3b29f5cb891461d6faaa53b43c0a4482
2013-12-09 20:15:54 -08:00
d513bb62bc * fix off-by-one zthresh calculation
* remove the sharpening for non luma-AC coeffs
* adjust the bias a little bit to compensate for this

Using the multiply-by-reciprocal doesn't always give the same result
as the exact divide, given the QFIX fixed-point precision we use.
-> removed few now-unneeded SSE2 instructions (and checked for
bit-exactness using -noasm)

Change-Id: Ib68057cbdd69c4e589af56a01a8e7085db762c24
2013-12-09 13:56:04 +01:00
ad9dec0c24 Merge "cosmetics: dwebp: fix local function name format" 2013-12-07 13:38:54 -08:00
f737f0376a Merge "dwebp: remove a dead store" 2013-12-07 13:38:42 -08:00
3c3a70da6d Merge "makefile.unix: install binaries in $(DESTDIR)/bin/" 2013-12-07 13:38:28 -08:00
150b655f74 Merge "Android.mk: add some release compile flags" 2013-12-07 13:38:15 -08:00
dbebd33be7 cosmetics: dwebp: fix local function name format
error_function -> PNGErrorFunction

Change-Id: Ic6c0e676cc47bca2c1a1e0d8e95639e780982b1b
2013-12-07 13:26:05 -08:00
2774995185 dwebp: remove a dead store
Change-Id: I48205472e99e997702d25c39f1b4d7a4699c15d6
2013-12-07 13:22:22 -08:00
a01e04fee0 autoconf: add --disable-wic
this allows windows builds to prefer libjpeg, libpng etc. for import and
export

Change-Id: Ibe1648b68a3f7b5016044e82530843dea46a94a4
2013-12-07 11:56:34 -08:00
5009b22746 makefile.unix: install binaries in $(DESTDIR)/bin/
Change-Id: I6c8f87aaa185fc043b80800430d99deaa1e5966b
2013-12-06 20:40:12 -08:00
bab30fcab5 Merge "fix -print_psnr / ssim options" 2013-12-05 14:04:37 -08:00
ebef7fb307 fix -print_psnr / ssim options
original/compressed pictures were not converted to an adequate YUVA
colorspace before computing the distortion.

Change-Id: I37775e9b7dbd6eca16c38e235e1df325858d36a1
2013-12-05 14:03:59 -08:00
cb63785545 Merge "fix bug due to overzealous check in WebPPictureYUVAToARGB()" 2013-12-04 00:54:35 -08:00
8189885b6d Merge "EstimateBestFilter: use an int to iterate WEBP_FILTER_TYPE" 2013-12-03 23:32:41 -08:00
4ad7d33510 Android.mk: add some release compile flags
-ffunction-sections / -fdata-sections
can improve final binary size when used with --gc-sections, speed impact
untested

Change-Id: I37f4b5da2f34acede7965c2da2e1b97125473adc
2013-12-03 23:00:49 -08:00
c12e2369d8 cosmetics: fix a few typos
Change-Id: I73b1900b2d960c4c57ef7078df137c776b321a1b
2013-12-03 22:36:29 -08:00
6f104034a1 fix bug due to overzealous check in WebPPictureYUVAToARGB()
This tests prevented views to be converted to ARGB

https://code.google.com/p/webp/issues/detail?id=178

Change-Id: I5ba66da2791e6f1d2bfd8c55b5fffe6955263374
2013-12-02 15:23:12 +01:00
3f6c35c6f3 EstimateBestFilter: use an int to iterate WEBP_FILTER_TYPE
this change allows the code to be built with a C++ compiler without the
addition of an operator++

Change-Id: I2f2fae720b9772abfc3c540bb2e3bf9107d96cc9
2013-11-27 20:10:45 -08:00
cc55790e37 Merge changes I8bb7a4dc,I2c180051,I021a014f,I8a224a62
* changes:
  mux: add some missing casts
  enc/vp8l: add a missing cast
  idec: add some missing casts
  ErrorStatusLossless: correct return type
2013-11-27 17:06:35 -08:00
c536afb57b Merge "cosmetics: fix some typos" 2013-11-27 17:04:00 -08:00
cbdd3e6e53 add a -dither dithering option to the decoder
Even at high quality setting, the U/V quantizer step is limited
to 4 which can lead to banding on gradient.
This option allows to selectively apply some randomness to
potentially flattened-out U/V blocks and attenuate the banding.

This option is off by default in 'dwebp', but set to -dither 50
by default in 'vwebp'.

Note: depending on the number of blocks selectively dithered,
we can have up to a 10% slow-down in decoding speed it seems.

Change-Id: Icc2446007f33ddacb60b3a80a9e63f2d5ad162de
2013-11-27 00:57:51 -08:00
e812401299 Updated iosbuild.sh for XCode 5.x
Change-Id: I4bf545c4f394c28842cbb85ac70214d2e5477ae0
2013-11-26 20:08:02 -08:00
4931c3294b cosmetics: fix some typos
Change-Id: I0d6efebd817815139db5ae87236fd8911df4d53c
2013-11-26 19:21:14 -08:00
05aacf77c2 mux: add some missing casts
+ fix a return value
+ fix a param type

Change-Id: I8bb7a4dc4c76b11140f8693c909aeb10f660e6e5
2013-11-25 20:53:15 -08:00
617d93480e enc/vp8l: add a missing cast
Change-Id: I2c1800516eb4573ae2599866ace10017b865f23a
2013-11-25 20:48:13 -08:00
46db286572 idec: add some missing casts
Change-Id: I021a014f1f3a597f37ba8d9f4006c8cb4100723c
2013-11-25 20:47:35 -08:00
b524e3369c ErrorStatusLossless: correct return type
int -> VP8StatusCode

Change-Id: I8a224a622e98d401a6e401047780fa6b25cb0ae4
2013-11-25 20:45:53 -08:00
cb261f790f fix a descaling bug for vertical/horizontal U/V interpolation
RGBToU/V calls expects two extra precision bits, they were only
given one by SUM2H and SUM2H macros.

For rounding coherency, also changed SUM1 macro.

Change-Id: I05f96a46f5d4f17b830d0420eaf79b066cdf78d4
2013-11-19 11:24:09 +01:00
bcb3955c41 Merge changes I48968468,I181bc736
* changes:
  demux: split chunk parsing from ParseVP8X
  demux: add a tail pointer for chunks
2013-11-18 17:03:33 -08:00
73f52133a1 gif2webp: Add a mixed compression mode
When '-mixed' option is given, each frame would be heuristically chosen
to be
encoded using lossy or lossless compression.

The heuristic is based on the number of colors in the image:
- If num_colors <= 31, pick lossless compression
- If num_colors >= 194, pick lossy compression
- Otherwise, try both and pick the one that compresses better.

Change-Id: I908c73493ddc38e8db35b7b1959300569e6d3a97
2013-11-17 18:04:07 -08:00
6198715e89 demux: split chunk parsing from ParseVP8X
makes the header and chunk parsing portions slightly more digestible

Change-Id: I48968468b2529506b830e96a2f13e8d29976179b
2013-11-16 11:06:43 -08:00
d2e3f4e6b5 demux: add a tail pointer for chunks
a large number of non-frame chunks could slow the parse

Change-Id: I181bc73626e92263c3c5b2a6dc2bf6e6a0481d52
2013-11-16 10:57:09 -08:00
87cffcc3c9 demux: cosmetics: s/has_frames/is_animation/
animation matches the flag name
s/has_fragments/is_fragmented/ to match.

Change-Id: I86c834e19bab6db6610ea2ccf900ab3ebffafa8a
2013-11-16 10:32:56 -08:00
e18e66779b demux: strictly enforce the animation flag
if the flag is incorrectly set in a VP8L or VP8/ALPH single image file
the demux will now fail.

Change-Id: Id4d5f2d3f6922a29b442c5d3d0acbe3d679e468a
2013-11-14 16:01:36 -08:00
c4f39f4a31 demux: cosmetics: remove a useless break
+ reword a comment

Change-Id: I52b64abcde2c8322b59c594f2f75b509ed367bff
2013-11-13 21:08:07 -08:00
61cb884d79 demux: (non-exp) fail if the fragmented flag is set
otherwise make sure that all frames are marked as a fragment. there's
still some work to do with validation if fragments are expected to cover
the entire canvas.

Change-Id: Id59e95ac01b9340ba8c6039b0c3b65484b91c42f
2013-11-12 21:50:27 -08:00
ff379db317 few % speedup of lossless encoding
mostly visible for method 4 and up

Change-Id: I1561d871bc055ec5f7998eb193d927927d3f2add
2013-11-12 00:09:45 +01:00
df3649a287 remove all disabled code related to P-frames
it's drifting out of sync, and won't be used anyway...

Change-Id: I931b288e1c8480bf3bccd685b3a356bb6bd8e10b
2013-11-04 11:52:05 +01:00
6d0cb3debf Merge "gif2webp: kmin = 0 should suppress key-frame addition." 2013-11-01 12:22:26 -07:00
36555983f0 gif2webp: kmin = 0 should suppress key-frame addition.
This is to conform to man/gif2webp.1
Earlier, one needed to give both '-kmin 0' and '-kmax 0' for this to
work.

Also, suppress further warnings for kmin = 0 and/or kmax = 0 case.

Change-Id: I6f5eeb609aeffc159d0252a40a5734162f7e4e7d
2013-11-01 12:01:59 -07:00
7708e60908 Merge "detect flatness in blocks and favor DC prediction" 2013-11-01 11:24:09 -07:00
06b1503eff Merge "add comment about the kLevelsFromDelta[][] LUT generation" 2013-10-31 21:37:55 -07:00
5935259cd0 add comment about the kLevelsFromDelta[][] LUT generation
Change-Id: Id1a91932bf05aeee421761667af351ef2200c334
2013-10-31 21:35:55 -07:00
e3312ea681 detect flatness in blocks and favor DC prediction
this avoids local-minima that look bad, even if the distortion
looks low (e.g. gradients, sky,...). Mostly visible in the q=50-80 range.
Output size is mostly unchanged.

Change-Id: I425b600ec45420db409911367cda375870bc2c63
2013-11-01 00:47:04 +01:00
ebc9b1eedf Merge "VPLBitReader bugfix: Catch error if bit_pos > LBITS too." 2013-10-31 16:38:15 -07:00
96ad0e0aef VPLBitReader bugfix: Catch error if bit_pos > LBITS too.
Earlier we were only testing for bit_pos == LBITS. But this is not
sufficient,
as bit_pos can jump from < LBITS to > LBITS.

This was resulting in some bit-stream truncation errors not being
caught.

Note: Not a security bug though, as br->pos wasn't incremented in such
cases
and so we weren't reading beyond the buffer.

Change-Id: Idadcdcbc6a5713f8fac3470f907fa37a63074836
2013-10-30 16:33:36 -07:00
a014e9c9cd tune quantization biases toward higher precision
* raise U/V quantization bias to more neutral values
* also raise the non-zero AC bias for Y1/Y2 matrices

(we need all the precision we can for U/V leves, which are often empty)
This will increase quality in the higher range (q >= 90) mostly.
Files size is exacted to raise a little (5-7%). and SSIM accordingly of course.

Change-Id: I8a9ffdb6d8fb6dadb959e3fd392e66dc5aaed64e
2013-10-30 23:57:23 +01:00
1e898619cb add helpful PrintBlockInfo() function
(protected under a DEBUG_BLOCK compile flag)

Change-Id: Icb8da02dbd00e5cf856c314943c212f1c9578d9b
2013-10-30 19:25:27 +01:00
596a6d73ce make use of 'extern' consistent in function declarations
Change-Id: I18e050db3111e52acfe97da09cdf1860f3e15936
2013-10-30 03:23:21 -07:00
c8d48c6e0d Merge "extract random utils to their own file util/random.[ch]" 2013-10-30 02:07:28 -07:00
98aa33cf1e extract random utils to their own file util/random.[ch]
they'll be used for decoding too, probably.

Change-Id: Id9cbb250c74fc0e876d4ea46b1b3dbf8356d6725
2013-10-30 02:00:33 -07:00
432a723e0b Merge "swig: add basic go bindings" 2013-10-30 01:03:32 -07:00
fab618b5fb Merge "rename libwebp.i -> libwebp.swig" 2013-10-30 01:02:05 -07:00
e4e7fcd69b swig: add basic go bindings
WebPGetDecoderVersion
WebPGetInfo

Change-Id: Icb66207c2f492c9d20642544c0b31cc92b91cdcc
2013-10-29 21:44:20 +01:00
d3408720d8 Merge "fast auto-determined filtering strength" 2013-10-29 12:47:58 -07:00
f8bfd5cd1e fast auto-determined filtering strength
kLevelsFromDelta[sharpness][delta] is an inverse look-up table
that tells the minimum filtering strength needed to trigger the
filtering of a step with amplitude 'delta'. We use this table
in various situations:

a) when computing the initial (/global) filtering
strength for each segment. We look at the quantization
step and deduce the proper filtering strength needed
to result this quantization noise (talking the -f option
into account).

b) during intra16 calculation, when a block ends up
very empty (only DC coeffs are non-zero, all ACs have
vanished). We'll rely on the in-loop filtering to
restore the smoothness (if the source was gradient-like
smooth. That's why we look at the distortion too before
triggering the filtering).

Step b) goes _in addition_ to a), potentially raising
the filtering strength if blockiness is likely.

Change-Id: Icaeca93ef21da195b079e6587a44d9edfc8e9efa
2013-10-29 20:13:29 +01:00
ac0bf951ca small clean-up in ExpandMatrix()
Change-Id: Ib06cb1658a6548f06bb7320310b3864881b606a7
2013-10-29 19:58:57 +01:00
1939607e7f rename libwebp.i -> libwebp.swig
.swig provides better tool compatibility

Change-Id: I35587b84dd32e12e8cedad14b36ac518b63896bc
2013-10-29 19:51:04 +01:00
43148b6cd2 filtering: precompute ilimit and hev_threshold
no speed change, just simplifying the logic

Change-Id: I518800494428596733d4fbae69072049828aec3c
2013-10-28 13:37:33 +01:00
18f992ec0f simplify f_inner calculation a little
by incorporating the is_4x4 flag at init

Change-Id: I042e04aacb15181db0bf86f3212c880087519189
2013-10-28 01:49:09 -07:00
241d11f141 add missing const
Change-Id: Id1c767d21d52197ed2e4497005eb9c4795c602f0
2013-10-25 20:34:14 +02:00
86c0031eb2 add a 'format' field to WebPBitstreamFeatures
Change-Id: I79a688e4c34fb77527127bbdf4bc844efa6aa9a4
2013-10-25 20:34:06 +02:00
dde91fde96 Demux: Correct the extended format validation
Earlier "f = f->next_" was executing for both inner and outer loop, thus
skipping validation of some frames.

Change-Id: Ice5cdb4ff5da78384aa0573addd3a5e5efa0b10c
2013-10-23 17:25:23 -07:00
5d6c5bd2a5 add entry for '-resize' option in cwebp's man
Change-Id: I04b2853825527b03cfa73377004b1a2a40b4c94f
2013-10-23 02:22:15 -07:00
7c098d1814 Use some gamma-curve range compression when computing U/V average
This helps for discolorated chroma-subsampled edges.

Change-Id: I1d8ce87b66cb7e8b3572e6722905beabf0f50554
2013-10-18 21:28:05 +02:00
0b2b05049f Use deterministic random-dithering during RGB->YUV conversion
-> helps debanding (sky, gradients, etc.)

This dithering can only be triggered when using -preset photo
or -pre 2 (as a preprocessing). Everything is unchanged otherwise.

Note that this change is likely to make the perceived PSNR/SSIM drop
since we're altering the input internally.

Change-Id: Id8d4326245d9b828141de162c94ba381b1fa5813
2013-10-17 22:36:49 +02:00
8a2fa099cc Add a second multi-thread method
method 1 grouping: [parse + reconstruction] // [filtering + output]
method 2 grouping: [parse] // [reconstruction+filtering + output]

Depending on some heuristics (see VP8ThreadMethod()), we
can pick one of the other when -mt flag (or option.use_threads)
is selected.

Conservatively, we always use method #2 for now until the heuristic
is refined (so, timing should be the same the before this patch)

+ replace 'use_threads' by 'mt_method'
+ define MIN_WIDTH_FOR_THREADS constant
+ fix comment alignment

Change-Id: I11a756dea9070d6e21b1a9481d357a1e8aa0663e
2013-10-15 23:58:31 +02:00
7d6f2da075 Merge "up to 20% faster multi-threaded decoding" 2013-10-15 14:51:12 -07:00
266f63ea89 Merge "libwebp.jar: build w/Java 1.6 for Android compat" 2013-10-15 02:04:41 -07:00
0532149c8a up to 20% faster multi-threaded decoding
Mostly visible for large images.
Reconstruction+filtering is now done in parallel to bitstream-parsing.

Change-Id: I4cc4483d803b255f4d97a2fcd9158b1c291dd900
2013-10-15 00:25:21 +02:00
38efdc2e9c Simplify the gif2webp tool: move the optimization details to util
Specifically:
- Merge OptimizeAndEncodeFrame with WebPFrameCacheAddFrame: they use the same
  if-else structure.
- Move maintenance of 'prev_canvas' and 'curr_canvas' to util.
- Move ReduceTransparency() and FlattenPixels() calls to SetFrame(): This is in
  preparation for the next patch: which will try try lossless encoding for
  each frame, even when '-lossy' option is given.
- Make most methods static inside util.

No changes to output expected.

Change-Id: I1f65af25246665508cb20f0f6e338f9aaba9367b
2013-10-14 14:39:46 -07:00
de899516c7 libwebp.jar: build w/Java 1.6 for Android compat
broken since:
 a5c297c swig/java: reduce wrapper function code duplication

this was a part of v0.3.1, but not v0.3.0.

Change-Id: I001d4bd0a7a1aa1b2d267bc63bc1d8226bff00c1
2013-10-11 17:59:37 +02:00
cb22155201 Decode a full row of bitstream before reconstructing
Needs more memory but allows for future parallelization.
Noticeably faster on ARM, slightly faster on x86

also: remove dec->filter_row_ unnecessary field

Change-Id: I044a808839b4e000c838a477e3e8688820436d9a
2013-10-10 21:29:58 +02:00
dca8a4d315 Merge "NEON/simple loopfilter: avoid q4-q7 registers" 2013-10-10 01:58:41 -07:00
9e84d901d2 Merge "NEON/TransformWHT: avoid q4-q7 registers" 2013-10-09 09:32:59 -07:00
fc10249b36 NEON/simple loopfilter: avoid q4-q7 registers
very tiny speed improvement

Change-Id: I3024f120feb7275ce20bfff21af31ea8650a5a03
2013-10-09 18:17:31 +02:00
2f09d63e30 NEON/TransformWHT: avoid q4-q7 registers
very tiny speed improvement

Change-Id: Iace78b9038af412d0a794845ff19f54afa88ccdc
2013-10-09 18:17:23 +02:00
77585a2be6 Merge "use a macrofunc for setting NzCoeffs bits" 2013-10-09 03:00:49 -07:00
d155507cb9 Merge "use HINT_GRAPH as image_hint for gif source" 2013-10-09 02:58:15 -07:00
9c561646ac Merge "only print GIF_DISPOSE_WARNING once" 2013-10-09 02:56:45 -07:00
05879865da use HINT_GRAPH as image_hint for gif source
quite rarely, it gives a different output
then without the HINT, but that's often for
a smaller size (tested with default -m and -m 6)

Change-Id: I51d221ab61f8e007983325031345728e8d80b241
2013-10-09 11:55:51 +02:00
0b28d7ab08 use a macrofunc for setting NzCoeffs bits
(avoids code dup)

Change-Id: I776f065538e562673ca08f3bc43c7167d13254d9
2013-10-09 11:46:32 +02:00
f9bbc2a034 Special-case sparse transform
If the number of non-zero coeffs is <= 3, use a
simplified transform for luma.

Change-Id: I78a1252704228d21720d4bc1221252c84338d9c8
2013-10-08 22:05:38 +02:00
00125196f3 gif2webp: detect and flatten uniformly similar blocks
helps during lossless compression.

10% average saving, but that's mostly on what was previously
'difficult' cases, where the gain is ~30-50% actually.
Non-difficult cases are mostly unchanged.
Tested over ~7k random web gifs.

Change-Id: I09db4560e4ab09105d1cad28e6dbf83842eda8e9
2013-10-08 15:04:52 +02:00
0deaf0fa44 only print GIF_DISPOSE_WARNING once
Change-Id: Iece235a6ee767cc2e3866bb6c9bb1d56d9a9ffb9
2013-10-08 15:02:33 +02:00
6a8c0eb718 Merge "small optimization in segment-smoothing loop" 2013-10-08 04:13:37 -07:00
f7146bc1e6 small optimization in segment-smoothing loop
probably not much of a speed difference

Change-Id: I08c41d82c3c2eb5ff9ec9ca9d81af2bb09b362de
2013-10-07 07:44:51 -07:00
5a7533ceb3 small gif2webp fix
the old kmin value was printed instead of the new one.

Change-Id: I0dcf23a29b7ce6bad08013a1980c5ce027b1bfe9
2013-10-04 21:13:35 +02:00
4df0c89e24 Merge changes Ic697660c,I27285521
* changes:
  Android.mk: add a dwebp target
  Android.mk: update build flags
2013-10-04 05:02:13 -07:00
5b2e6bd3e8 Android.mk: add a dwebp target
Change-Id: Ic697660c1a5f7185d2ad00934b314b44870cec00
2013-10-04 11:26:37 +02:00
f910a84ea5 Android.mk: update build flags
- split out release specific flags
- set LOCAL_ARM_MODE to arm

Change-Id: I272855216583d6c8d0a4106e8b3fde46aa59dfa9
2013-10-04 11:18:09 +02:00
63f9aba4b3 special-case WHT transform when there's only DC
happens surprisingly often at low quality, so we might
as well hard-code a simplified TransformWHT() directly.

Change-Id: Ib7a858ef74e8f334bd59d6512bf5bd3e455c5459
2013-10-02 14:27:36 +02:00
80911aef38 Merge "7-8% faster decoding by rewriting GetCoeffs()" 2013-10-02 01:51:53 -07:00
606c4304c4 gif2webp: Improved compression for lossy animated WebP
We reduce transparency by turning some transparent pixels into
corresponding RGB values from previous canvas.

This improves compression by about 23%.

Change-Id: I02d70a43a1d0906ac09a7e2dc510be3b2d38f593
2013-09-30 16:48:39 -07:00
fb887f7fe6 gif2webp: Different kmin/kmax defaults for lossy and lossless
These were the best values found considering the compression gain and
decoding speed.

Change-Id: Iddae4c5b78c6aa42b1f8a034d1c1b93843071a81
2013-09-30 14:25:58 -07:00
2a98136667 7-8% faster decoding by rewriting GetCoeffs()
Change-Id: Ib7c27e985d3b5222e8fa1f98cec462458caa9541
2013-09-30 23:17:34 +02:00
92d47e4ca9 improve VP8L signature detection by checking the version bits too
Change-Id: I20bea00b9582d7ea8c7b643616c78f717ce1bdf2
2013-09-27 18:17:23 +02:00
5cd43e4316 Add -incremental option to dwebp
useful for testing. Not listed in the man or README, since
it's only useful for testing the incremental decoding
(e.g. measuring the timing difference compared to non-incremental)

Change-Id: I8df8046e031d21006242babb5bcac09f8ff9f710
2013-09-19 13:20:45 +02:00
54b8e3f6e2 webpmux: DisplayInfo(): remove unnecessary error checks.
As WebPMuxCreate() would have succeeded by then, many of the calls
cannot fail.

Change-Id: I3220c59e9aa47c948da9f8741b4098c47b91a8fc
2013-09-18 11:44:24 -07:00
40ae3520b1 fix memleak in WebPIDelete()
happens when decoding is partial (past Partition0), without error and
interrupted by calling WebPIDelete()

WebPIDelete() needs to call VP8ExitCritical() to free in-flight resources

Change-Id: Id4faef1b92f7edd8c17d642c58860e70dd570506
2013-09-17 15:45:43 -07:00
d9662658d9 mux.h doc: WebPMuxGetFrame() can return WEBP_MUX_MEMORY_ERROR too.
Change-Id: Icc0305f162d1f5d15ad1b4713ac08e210c85c306
2013-09-17 14:37:12 -07:00
0e6747f88d webpmux -info: display dimensions and has_alpha per frame
Also, more readable dispose and blend methods.

Change-Id: I318431f94dcdee4c5da296a48e6f3762aa254c1f
2013-09-16 15:29:24 -07:00
d78a82c407 Sanity check for underflow
Change-Id: I52dbdcbd02c344c6260f196afad30005d14d3ee0
2013-09-16 13:35:13 -07:00
8498f4bfe2 Merge "remove -Wshadow warnings" 2013-09-16 13:19:39 -07:00
e89c6fc867 Avoid a potential memleak
Change-Id: I76f30fb40743a989bce25b40238cf0db55bd07e0
2013-09-16 13:12:33 -07:00
3ebe175781 Merge "break down the proba 4D-array into some handy structs" 2013-09-14 03:14:30 -07:00
6a44550a8c break down the proba 4D-array into some handy structs
Makes it easy to later add derived satellite fields...

Change-Id: I445767ea78cc788d11aec367479e74e485fdabe5
2013-09-14 03:12:09 -07:00
2f5e893400 remove -Wshadow warnings
"warning: declaration of ‘index’ shadows a global declaration"

Change-Id: I65f079aa4cd300cd1b3887a040b75c6b0f36ca1d
2013-09-14 02:02:09 -07:00
bf3a29b302 Merge "add proper WEBP_HAVE_GIF and WEBP_HAVE_GL flags" 2013-09-14 01:57:36 -07:00
2b0a759335 Merge "fix some warnings from static analysis" 2013-09-13 13:00:12 -07:00
22dd07cee9 mux.h: Some doc corrections
Change-Id: Ia2840a489d87001de241a9a8fbc88a127af55ff9
2013-09-13 12:51:36 -07:00
79ff03460a add proper WEBP_HAVE_GIF and WEBP_HAVE_GL flags
...and make gif2webp and vwebp compile without them.

Makefile.vc still to be updated...
Meanwhile the CL environment variable can be supplemented with

set CL=/DWEBP_HAVE_GL /IC:\opt\freeglut\include

Change-Id: I37a60b8c32aafd125bffa98b6cc9f57c022ebbd0
2013-09-13 12:46:41 -07:00
d51f45f047 fix some warnings from static analysis
http://code.google.com/p/webp/issues/detail?id=138

Change-Id: I21470e965357cc14eab356e2c477c7846ff76ef2
2013-09-13 11:33:30 +02:00
d134307b7f fix conversion warning on MSVC
"src\enc\frame.c(88) : warning C4244: '=' : conversion from 'const double' to 'float', possible loss of data"

Change-Id: I143cb0bb6b69e1b8befe9b4f24b71adbc28095c2
2013-09-12 18:57:51 -07:00
d538cea8c2 gif2webp: Support a 'min' and 'max' key frame interval
Change-Id: If910c8849d7210e7227db0f45affa26fce7da102
2013-09-12 13:41:09 -07:00
80b54e1c69 allow search with token buffer loop and fix PARTITION0 problem
The convergence algo is noticeably faster and more accurate.

Try it with: 'cwebp -size xxxxx -pass 8 ...' or 'cwebp -psnr 39 -pass 8 ...'
for instance

Allow full-looping with TokenBuffer case, and make the non-TokenBuffer
case match too.

In case Partition0 is likely to overflow, retry encoding with harder
limits on max_i4_header_bits_.

This CL should make -partition_limit option somewhat useless,
since the fix made automatically (albeit in a non-optimal way yet).

Change-Id: I46fde3564188b13b89d4cb69f847a5f24b8c735b
2013-09-11 21:15:28 +02:00
b7d4e04255 add VP8EstimateTokenSize()
estimates final size of coded tokens given a set of probabilities

Change-Id: Ia5a459422557d98b78b3cd8e1a88cb30835825b6
2013-09-11 10:08:49 +02:00
10fddf53bb enc/quant.c: silence a warning
score_t -> int: rd_i4.H contains a value from a uint16_t
lookup

Change-Id: I7227de2dfab74b4f796abbc47955197ffa0e6110
2013-09-11 00:04:11 -07:00
399cd4568b Merge "fix compile error on ARM/gcc" 2013-09-10 15:12:30 -07:00
9f24519e82 encoder: misc rate-related fixes
* fix VP8FixedCostsI4ÆÅ table
   (the constant cost '211' was erronenously included)
* use the rd-score for '211' correctly (calling SetRDScore() for good)
* count partition0 bits separately during rd-opt

No meaningful difference in rd-curve.

Change-Id: I6c49a150cf28928d9a92c32fff097600d7145ca4
2013-09-10 00:25:32 -07:00
c663bb214a Merge "simplify VP8IteratorSaveBoundary() arg passing" 2013-09-06 14:21:42 -07:00
fa46b31269 Demux.h: Correct a method name reference
Change-Id: I5638a4e40d9fcb44860952028f8b5ef2ea78621d
2013-09-06 11:26:00 -07:00
f8398c9dab fix compile error on ARM/gcc
use of uint8_t type was causing error like:
src/dsp/upsampling.c:223:1: internal compiler error: in vect_determine_vectorization_factor, at tree-vect-loop.c:349

with gcc 4.6.3

Change-Id: Ieb6189a1375c47fc4ff992e6c09b34a7f1f605da
2013-09-06 03:07:28 -07:00
f691f0e461 simplify VP8IteratorSaveBoundary() arg passing
we only need to save yuv_out_, so no need for the arg

Change-Id: I7bad5d910e81ed2eda5c9787821fd1cfe905bd92
2013-09-06 02:11:16 -07:00
42542be855 up to 6% faster encoding with clang compiler
mostly by revamping the main loop of GetResidualCost() and avoiding some branches

Change-Id: Ib05763e18a6bf46c82dc3d5d1d8eb65e99474207
2013-09-05 10:38:22 -07:00
93402f02db multi-threaded segment analysis
When -mt is used, the analysis pass will be split in two
and each halves performed in parallel. This gives a 5%-9% speed-up.

This was a good occasion to revamp the iterator and analysis-loop
code. As a result, the default (non-mt) behaviour is a tad (~1%) faster.

Change-Id: Id0828c2ebe2e968db8ca227da80af591d6a4055f
2013-09-05 09:13:36 +02:00
7e2d65950f Merge "remove the PACK() bit-packing tricks" 2013-09-04 23:55:41 -07:00
c13fecf908 remove the PACK() bit-packing tricks
was too smart for its own good :)
This is more ARM-friendly, since it removes a mult.

Change-Id: If146034c8efa2e71e3eaaf1230cb553884a42ebb
2013-09-05 08:53:36 +02:00
2fd091c9ae Merge "use NULL for lf_stats_ testing, not bool" 2013-09-04 07:18:42 -07:00
b11c9d6284 dwebp: use default dct_method
No significant speed diff was observed.
Avoids idct mismatch artifacts.

Change-Id: I9ca64d165d313f23b4aa231e7a97a20213ff86c7
2013-09-03 15:48:41 -07:00
4bb8465f8c Merge "(de)mux.h: wrap pseudo-code in /* */" 2013-09-03 15:47:42 -07:00
cfb56b1707 make -pass option work with token buffers
-pass 2 can be useful sometimes. More passes usually don't help more.
This change is a step toward being able to re-code the whole picture
with varying parameter (when token buffer is used).

Change-Id: Ia2538e2069a53c080e2ad248c18a1e04623a9304
2013-09-03 23:37:42 +02:00
5416aab479 (de)mux.h: wrap pseudo-code in /* */
easier to copy / read as a block

Change-Id: Ia22689a13afd8ea2325dcdf432e35fc802d8177a
2013-09-03 14:31:02 -07:00
35dba337a3 use NULL for lf_stats_ testing, not bool
Change-Id: I14c6341bce1c745b7f2d1b790f2d4f8441d01be6
2013-09-03 08:45:59 -07:00
733a7faae4 enc->Iterator memory cleanup
* move yuv_in_/out_* scratch buffers to iterator
* add y_top_/uv_top_ shortcuts in iterator

That's ~3k of stack size instead of heap.
But it allows having several iterators work in parallel.

Change-Id: I6a437c0f2ef1e5d398c1d6a2fd4974fa0869f0c1
2013-08-31 23:38:11 +02:00
e81fac86dd Add support for "no blend" in webpmux binary
Change-Id: I6d07b120626317df73f1a6f026931c5b9485a340
2013-08-26 18:04:52 -07:00
3b80bc4859 gif2webp: Separate out each step into a method
We now have ReadFrame(), OptimizeFrame(), EncodeFrame() and
DisposeFrame()
methods.

Change-Id: I522834bad18dd6a7a3ddac7c00dfd829c48248f8
2013-08-22 11:14:51 -07:00
bef7e9ccd1 Add doc precision about demux object keeping pointers to data.
Change-Id: I3d2139f975eedcce36606e586e0cbd6fa7d207e6
2013-08-21 11:09:37 -07:00
61405a143d dwebp: enable stdout output with WIC
Change-Id: Ieb73a414784480945bba6cb2687468517e24e755
2013-08-20 19:59:30 -07:00
6eabb88637 Merge "Animated WebP: add "do no blend" option to spec" 2013-08-20 19:14:17 -07:00
be20decb5c fix compilation for BITS 24
in_bits is const. Trying to apply bswap on it, one gets the error message:
error: read-only variable 'in_bits' used as 'asm' output

Change-Id: I0bef494b822c83d8ea87b1938b0e486d94de4742
2013-08-20 18:55:00 -07:00
e58cc13706 Merge "dwebp: s/unsigned char/uint8_t/" 2013-08-20 15:03:46 -07:00
72501d4309 dwebp: s/unsigned char/uint8_t/
Change-Id: I579e9b0a4d03998ca1dd8683d83d30d852551e45
2013-08-20 14:57:35 -07:00
2c9633e8e0 Merge "gif2webp: Insert independent frames at regular intervals." 2013-08-20 13:59:50 -07:00
f0d6a14b64 gif2webp: Insert independent frames at regular intervals.
We use the 'do not blend' option for creating independent frames.
We also mark the already independent frames as 'do not blend'.

This bounds the maximum number of frames that need to be decoded to
decode a given frame, thus leading to a much better decoding performance.

Change-Id: I7cef98af2b53751ec36993fd2bd54f7f4c4aad2b
2013-08-20 11:47:48 -07:00
b25a6fbfdc yuv.h: fix indent
Change-Id: I0c0bd5f7f71bc44e10134bd4f788769ec25cec1f
2013-08-19 18:06:15 -07:00
ede3602e5d Merge "cosmetics: fix indent" 2013-08-19 17:56:21 -07:00
3a65122a53 dwebp: fix stdout related output
logic was incorrect for the error output

Change-Id: I89e665f8065490e12e1bf3d3008087d42daee16b
2013-08-19 17:52:33 -07:00
388a7249c9 cosmetics: fix indent
Change-Id: Iad0fce79886bed0d61ddf2510ce133a5355ebc1f
2013-08-19 17:51:04 -07:00
4c7322c86f Merge "dsp: msvc compatibility" 2013-08-19 17:42:16 -07:00
d50c7e3275 Merge "5-7% faster SSE2 versions of YUV->RGB conversion functions" 2013-08-19 17:27:44 -07:00
b8ab784745 Merge "simplify upsampler calls: only allow 'bottom' to be NULL" 2013-08-19 17:27:36 -07:00
df6cebfa9e 5-7% faster SSE2 versions of YUV->RGB conversion functions
The C-version gets ~7-8% slower in order to match the SSE2
output exactly. The old (now off-by-1) code is kept under
the WEBP_YUV_USE_TABLE flag for reference.

(note that calc rounding precision is slightly better ~= +0.02dB)

on ARM-neon, we somehow recover the ~4% speed that was lost by mimicking
the initial C-version (see https://gerrit.chromium.org/gerrit/#/c/41610)

Change-Id: Ia4363c5ed9b4c9edff5d932b002e57bb7814bf6f
2013-08-19 17:05:58 -07:00
ad6ac32d7c simplify upsampler calls: only allow 'bottom' to be NULL
If 'top' was meant to be NULL, then bottom and top can be
swapped. Logic is simpler.

+ fix compilation in non-FANCY_UPSAMPLING mode

Change-Id: I7c62bbb59454017f072c0945d1ff2d24d89286ff
2013-08-19 16:47:51 -07:00
a5e8afafcb output to stdout if file name is "-"
Doesn't work with WIC

+ redirect some info messages from stdout to stderr
+ fix the error reporting upon output-writing error

Change-Id: I92b8bd7a15e656a3f3cdfbf56299f024e39453f8
2013-08-19 13:30:27 -07:00
f358450feb dsp: msvc compatibility
intrin.h is available after VS2003

patch from the FreeImage project

Change-Id: I58a18a0db00e247f871d05e3ba99772704f0e079
2013-08-16 20:46:16 -07:00
43a7c8ebee Merge "cosmetics" 2013-08-15 11:24:30 -07:00
4c5f19c148 Merge "bit_reader.h: cosmetics" 2013-08-15 11:11:03 -07:00
f72fab7045 cosmetics
Change-Id: Ib6fa2a7e1db8c5c48607c7097520ffca34a6cb66
2013-08-15 04:16:37 -07:00
14dd5e781a fix const-ness
Change-Id: I09c85fdb90b4380c8fc03c8b5652bb9cf29b2021
2013-08-15 00:21:15 -07:00
b20aec4949 Merge "Support for 'do not blend' option in vwebp" 2013-08-14 20:01:38 -07:00
dcf652223a Support for 'do not blend' option in vwebp
Change-Id: I563e192fa727816d11d8647c559ec407205ef40b
2013-08-14 19:51:46 -07:00
d5bad03328 Animated WebP: add "do no blend" option to spec
Marking certain frames as "do not blend" helps avoiding alpha-blending
at decode/render time.

It also helps inserting I-frames (frames which can be independently
decoded) into the animation.

Change-Id: Iaa222805db88d2f1c81104ce9d882e7c7ff8cfdb
2013-08-14 11:50:15 -07:00
a2f5f73de3 Merge "Support for "Do not blend" in mux and demux libraries" 2013-08-14 09:27:58 -07:00
e081f2f359 Pack code & extra_bits to Struct (VP8LPrefixCode).
Also created variant VP8LPrefixEncodeBits that returns the
code & extra_bits only.
There's no impact on compression density and compression speed.

Change-Id: I2cafdd3438ac9270cd72ad9d57b383cdddfdfa4c
2013-08-12 11:56:42 -07:00
6284854bd5 Support for "Do not blend" in mux and demux libraries
Change-Id: I9566a8e2d059fe1ebd9ca99c7e13311bf3f8f281
2013-08-12 11:49:00 -07:00
f486aaa9f8 Merge "slightly faster ParseIntraMode" 2013-08-09 02:17:16 -07:00
d17186328c slightly faster ParseIntraMode
+ cosmetics

Change-Id: Icb906d5f84f025ef9e04b71a73801a22cc990ee5
2013-08-09 02:15:21 -07:00
3ceca8ad31 bit_reader.h: cosmetics
- use const where applicable
- drop unnecessary string.h include

Change-Id: I560eef84fe17d3925768f6817c02ea79604c4379
2013-08-06 14:25:26 -07:00
69257f70df Create LUT for PrefixEncode.
This speeds up lossless compression by 5%.
Change-Id: Ifd114b1d9850dc3aac74593809e7d48529d35e3d
2013-08-05 10:20:18 -07:00
988b70844e add WebPWorkerExecute() for convenient bypass
This is mainly for re-using the worker structs without using the
thread.

Change-Id: I8e1be29e53874ef425b15c192fb68036b4c0a359
2013-08-02 12:20:15 -07:00
06e24987e7 Merge "VP8EncIterator clean-up" 2013-08-02 00:40:02 -07:00
de4d4ad598 VP8EncIterator clean-up
- remove unused fields from iterator
- introduce VP8IteratorSetRow() too
- rename 'done_' to 'countdown_'
- bring y_left_/u_left_/v_left_ from VP8Encoder

Change-Id: Idc1c15743157936e4cbb7002ebb5cc3c90e7f92a
2013-08-01 23:05:54 -07:00
7bbe95293f Merge "cosmetics: thread.c: drop a redundant comment" 2013-07-31 23:56:06 -07:00
da41148560 cosmetics: thread.c: drop a redundant comment
+ fix #if/#else/#endif comment

Change-Id: I76bfd3b123ed181897ed0feba721d5c1a3a2b0d7
2013-07-31 22:55:51 -07:00
feb4b6e6b3 thread.h: #ifdef when checking WEBP_USE_THREAD
prevents a warning with -Wundef and is consistent with thread.c

Change-Id: I60fa337c3b9daeea7302e86802402cb943cdb262
2013-07-31 22:50:57 -07:00
8924a3a704 thread.c: drop WebPWorker prefix from static funcs
Change-Id: I7cd39c9e41bbf11157c488aff18631ef17fde464
2013-07-31 19:22:44 -07:00
1aed8f2afc Merge "fix indent" 2013-07-26 17:08:37 -07:00
4038ed154d fix indent
Change-Id: I7f226ec4276e5e1b46896086a7d96cb67f36de6a
2013-07-26 17:03:19 -07:00
1693fd9b16 Demux: A new state WEBP_DEMUX_PARSE_ERROR
WebPDemuxPartial() returns NULL for both of the following cases:
- There was a parsing error.
- It doesn't have enough data to start parsing.

Now, one can differentiate between these two cases by checking the value
of 'state' returned by WebPDemuxPartial().

Change-Id: Ia2377f0c516b3fcfae475c0662c4932d2eddcd0b
2013-07-26 14:35:46 -07:00
8dcae8b3cf fix rescaling-with-alpha inaccuracy
(still missing YUVA decoding case for now)

https://code.google.com/p/webp/issues/detail?id=160

Change-Id: If723b4a5c0a303d0853ec9d839f995adce056095
2013-07-26 12:10:26 -07:00
11249abfc7 Merge changes I9b4dc36c,I4e0eef4d
* changes:
  Mux: support parsing unknown chunks within a frame/fragment.
  Stricter check for presence of alpha when writing lossless images
2013-07-22 17:05:27 -07:00
52508a1fe4 Mux: support parsing unknown chunks within a frame/fragment.
Change-Id: I9b4dc36c5ccc4b46f60cd64c1ee21008e20c8b95
2013-07-22 17:00:41 -07:00
05db0572f8 WebPMuxSetChunk: remove unused variable
and unnecessary call to ChunkGetIndexFromFourCC()

Change-Id: Ic1ed53750a3be43df827a6fb9a4b9ff3eb25c6c7
2013-07-19 13:03:25 -07:00
8ba1bf61a0 Stricter check for presence of alpha when writing lossless images
Earlier, all lossless images were assumed to contain alpha.
Now, we use the 'alpha_is_used' bit from the VP8L bitstream to determine
the
same.

Detecting an absence of alpha can sometimes lead to much more efficient
rendering, especially for animated images.

Related: refine mux code to read width/height/has_alpha information only
once
per frame/fragment. This avoid frequent calls to VP8(L)GetInfo().

Change-Id: I4e0eef4db7d94425396c7dff6ca5599d5bca8297
2013-07-19 11:55:09 -07:00
a03c3516cb Demux: WebPIterator now also denotes if the frame has alpha.
Change-Id: Ia300385a49c1ee5afa8f114f2560ee8d1c7664bb
2013-07-18 19:41:38 -07:00
6df743a33e Decoder: handle fragments case correctly too.
Exit early from ParseHeaderInternal() in case of fragmented image too.

Change-Id: I3e24be2c869cc2d87c43b705257f21be81127dbd
2013-07-18 19:23:57 -07:00
faa4b07eda Support for unknown chunks in mux library
WebPMuxSetChunk/WebPMuxGetChunk/WebPMuxDeleteChunk now correctly handle
unknown chunks.

Change-Id: I2b75106ef08260f2bce03eb1782924b620643746
2013-07-17 16:34:50 -07:00
7d60bbc6d9 Speed up HashChainFindCopy function.
Speed up HashChainFindCopy by optimizing on number of calls to
FindMatchLength method.
This change speeds up the lossless & lossy (Alpha) encoding by 20%
without loss of compression density.
At method=3, lossy (Alpha) compression speed (and density) remains
unchanged, as at that settings, the costly Backward Refs method is not
called

Change-Id: Ia1797148e9e4ee2787011837fa248afbae2242cb
2013-07-16 19:58:18 -07:00
6674014077 Speedup Alpha plane encoding.
Disable costly 'BackwardReferencesTraceBackwards' for encoding Alpha plane.
Increase the threshold for triggering 'BackwardReferencesTraceBackwards' to
quality 25 and above. Also lower the Alpha quality (at method 3) to be
lesser than this threshold (25).

Change-Id: Ic29fb2e6943472c564223df9fe099b19ccda0f31
2013-07-12 11:02:13 -07:00
b7346a1ed2 0.1 % speedup to decoding
Change-Id: If2add8a8b6f339f1d4b6a9581ce8d3d0f792d372
2013-07-09 18:47:06 -07:00
c606182edd webp-container-spec: Tighten language added by last
Change-Id: Id7719ba7f1ddfd7b54a1985771b2811318a7c0d7
2013-07-09 18:45:39 -07:00
a34a502989 pngdec: output error messages from libpng
Change-Id: I1981562eeab2ad07eb797cea589a033943e7f21d
2013-07-09 17:33:21 -07:00
e84c625d92 Merge "Detect canvas and image size mismatch in decoder." 2013-07-03 00:51:26 -07:00
f626fe2e9f Detect canvas and image size mismatch in decoder.
Will probably have to be re-visited when FRGM are
switched on.

Change-Id: I51c15e4c3887ab8f04d92ec783deca274cd09f41
2013-07-02 16:19:08 -07:00
f5fbdee0ba demux: stricter image bounds check
- validate x/y offset vs. canvas size
- with single images verify image res. == canvas res.

Change-Id: I737451d7f75c0c43c88180a903d5227f1d90cec1
2013-07-02 16:17:28 -07:00
30c8158a53 add extra assert in Huffman decode code
Change-Id: Ic0372d30827f11b727d63eac6c5eac01d1e9870d
2013-06-29 01:36:53 -07:00
8967b9f37e SSE2 for lossless decoding (critical) functions.
This speeds up WebP lossless decoding by 20%. In particular, the
photographic images get 35% speedup.

Change-Id: Idb94750342a140ec05df52c07e12be4bba335adc
2013-06-27 11:42:45 -07:00
699d80ea6b Jump-lookup for Huffman coding
speeds up those codes that are not part of the main lookup.
This gives a 10 % speedup for a photographic image.

Change-Id: Ief54b0ad77db790a01314402ad351b40ac9a7be4
2013-06-27 08:59:55 +02:00
c34307abda fix some VS9 warnings about type conversion
Change-Id: Ia6db5f70cecb1d0c29536d710a22cc5107e242ea
2013-06-27 08:49:01 +02:00
eeada35cd6 pngdec: add missing include
strcmp -> string.h

Change-Id: I07392d07cbad420f5d4f3abfd3ffde8626f0c0f2
2013-06-25 23:32:19 -07:00
54b65108ad gif2webp: If aligning to even offsets, extra pixels should be transparent
This is to ensure that the output WebP image is consistent with original
GIF when displayed against any background color.

Change-Id: I14218848153eb40358aa4ce331b2543d2fc2e86c
2013-06-24 15:18:35 -07:00
0bcf5ce39a Merge "remove a malloc() in case we're using only FILTER_NONE for alpha" 2013-06-24 12:55:40 -07:00
2c07143b9d remove a malloc() in case we're using only FILTER_NONE for alpha
+ some revamp and cleanup of the alpha-filter trial loop
+ EncodeAlphaInternal() now just takes a FilterTrial param

Change-Id: Ief84385083b1cba02678bbcd3dbf707245ee962f
2013-06-24 02:07:52 -07:00
a4d5f59d9e Faster lossless decoding
Specialize and simplify the alpha-decoding case, which is used when:
 - no color-cache is use
 - all red/blue/alpha values are the same (and hence their Huffman tree has
 only 1 symbol. We don't need to consume any bits for reading these).

 + revamped the loop to use size_t and offsets instead of pointers.

 ~2-3% faster on Unix (gcc) but up to 25% faster lossy+alpha decoding
 on Mac (llvm) and ARM.

Change-Id: I43c9688d1e4811cab0ecf0108a5b8f45781083e6
2013-06-24 09:34:30 +02:00
fd53bb758e Merge "alternate LUT-base reverse-bits code" 2013-06-24 00:32:39 -07:00
d1c166ef3f Merge "Container spec: a clarification on background color." 2013-06-21 00:53:12 -07:00
fdb9177917 Rename a method
Change-Id: Idc5f4ea1019a828a5fa1fbd81804fa51cd7e8673
2013-06-21 00:35:39 -07:00
5e9675329c Container spec: a clarification on background color.
Change-Id: Ifeb565bd162abfa03dfcbf8b576657fe83956a6c
2013-06-20 17:38:08 -07:00
30e77d0f66 Merge branch '0.3.0'
* 0.3.0: (57 commits)
  update ChangeLog
  Regression fix for alpha channels using color cache:
  wicdec: silence a format warning
  muxedit: silence some uninitialized warnings
  update ChangeLog
  update NEWS
  bump version to 0.3.1
  Revert "add WebPBlendAlpha() function to blend colors against background"
  Simplify forward-WHT + SSE2 version
  probe input file and quick-check for WebP format.
  configure: improve gl/glut library test
  update copyright text
  configure: remove use of AS_VAR_APPEND
  fix EXIF parsing in PNG
  add doc precision for WebPPictureCopy() and WebPPictureView()
  remove datatype qualifier for vmnv
  fix a memory leak in gif2webp
  fix two minor memory leaks in webpmux
  remove some cruft from swig/libwebp.jar
  README: update swig notes
  ...

Conflicts:
	NEWS
	examples/gif2webp.c
	src/dec/alpha.c
	src/dec/idec.c
	src/dec/vp8l.c
	src/enc/alpha.c
	src/enc/vp8l.c

Change-Id: Ib202fad7825a090c3b3a5169acd171369cface47
2013-06-20 14:47:48 -07:00
1b631e291a alternate LUT-base reverse-bits code
Not faster on Unix/x86. Left the code for reference though.

Change-Id: I7d419e9835e7746b85b8f8cc6f2af92db0eb8b03
2013-06-20 19:58:11 +02:00
24cc307ae3 ~20% faster lossless decoding
We use help from small LUTs for Huffman decoding.

Change-Id: I58db4ecd37282822094519f2aa14cf544beba975
2013-06-20 09:41:29 +02:00
313d853fa9 Speedup for decoding lossless WebP photographs:
use bit_pos instead num_bit to update the bit-reader
37.69 MB/s -> 39.79 MB/s, 5.6 %

Change-Id: Ica476cc3e2fc2db084d6961bea8586b050bb221d
2013-06-18 17:26:52 +02:00
24ee098a00 change the bytes_per_pixels_ field into more evocative use_8b_decode
+ split AllocateInternalBuffers() into two 32b/8b variants instead of
trying to do everything in one function.

Change-Id: I35cac9fcd990a2194c95da4b2a4046ca3a514343
2013-06-18 17:24:14 +02:00
2a04b034f7 update ChangeLog
Change-Id: Idea3464bbcb28896179c99488e7b96a4341b508a
2013-06-17 16:53:22 -07:00
7288950b88 Regression fix for alpha channels using color cache:
Considering the fact that insert to/lookup from the color cache is always 32
bit, use DecodeImageData() variant in that case.

Conflicts:
	src/dec/vp8l.c

Change-Id: I6c665a6cfbd9bd10651c1e82fa54e687cbd54a2b
(cherry picked from commit a37eff47d6)
2013-06-17 16:29:09 -07:00
2e377b53b0 wicdec: silence a format warning
from x86_64-w64-mingw32-gcc

examples/wicdec.c: In function ‘ExtractICCP’:
examples/wicdec.c:131:21: warning: format ‘%u’ expects argument of type
‘unsigned int’, but argument 4 has type ‘size_t’ [-Wformat]

Change-Id: I6642dae62265a2276ae9ac96dd8ce6f1e2d37ca5
(cherry picked from commit ffae9f31e8)
2013-06-17 15:43:33 -07:00
ad9e42a6fe muxedit: silence some uninitialized warnings
src/mux/muxedit.c:490: warning: 'x_offset' may be used uninitialized in this function
src/mux/muxedit.c:490: warning: 'y_offset' may be used uninitialized in this function

Change-Id: I4fd27f717e59a556354d0560b633d0edafe7a4d8
(cherry picked from commit 14cd5c6c40)
2013-06-17 15:43:33 -07:00
3307c16327 Don't set alpha-channel to 0xff for alpha->green uplift
usually saves ~4 bytes on average (but, up to 10 -or even 16- sometimes).

Change-Id: Ib500e1a35471a2f3da453ffc8c7e95d28b8d34fe
2013-06-18 00:03:32 +02:00
5130770cd3 Merge "wicdec: silence a format warning" 2013-06-17 14:45:01 -07:00
a37eff47d6 Regression fix for alpha channels using color cache:
Considering the fact that insert to/lookup from the color cache is always 32
bit, use DecodeImageData() variant in that case.

Change-Id: I6c665a6cfbd9bd10651c1e82fa54e687cbd54a2b
2013-06-17 03:49:30 -07:00
241cf99bc0 Merge "muxedit: silence some uninitialized warnings" 2013-06-16 23:23:20 -07:00
c8f9c84d5e Regression fix for alpha unfiltering:
For vertical filter, correctly initialize 'preds' when not starting at
row 0.

Change-Id: I69697d73dde8a2f701f376ff3986d09fa6f7fee3
2013-06-16 02:00:44 -07:00
14cd5c6c40 muxedit: silence some uninitialized warnings
src/mux/muxedit.c:490: warning: 'x_offset' may be used uninitialized in this function
src/mux/muxedit.c:490: warning: 'y_offset' may be used uninitialized in this function

Change-Id: I4fd27f717e59a556354d0560b633d0edafe7a4d8
2013-06-15 14:30:22 -07:00
a368db81c6 dec/vp8l: quiet vs9 x64 type conversion warning
src\dec\vp8l.c(816) : warning C4244: '=' : conversion from '__int64' to
'int', possible loss of data
src\dec\vp8l.c(817) : warning C4244: '=' : conversion from '__int64' to
'int', possible loss of data

Change-Id: I1d376d5dea909395bff8741aba16e8eed83a6e8f
2013-06-14 19:24:54 -07:00
ffae9f31e8 wicdec: silence a format warning
from x86_64-w64-mingw32-gcc

examples/wicdec.c: In function ‘ExtractICCP’:
examples/wicdec.c:131:21: warning: format ‘%u’ expects argument of type
‘unsigned int’, but argument 4 has type ‘size_t’ [-Wformat]

Change-Id: I6642dae62265a2276ae9ac96dd8ce6f1e2d37ca5
2013-06-14 18:44:59 -07:00
8cf0701eb0 Alpha encoding: never filter in case of NO_COMPRESSION
This is because, filtering would never affect compression density for
this case.

Change-Id: I4bb14d3eb7da0a3805fda140eb1dfbf9ccc134f5
2013-06-14 13:34:25 -07:00
825e73b1a6 update ChangeLog
Change-Id: I2e67e5d80cb8f8e4453cee45144bcc01e9a3efeb
2013-06-12 23:32:59 -07:00
abf6f6915f update NEWS
Change-Id: Ie831ecc6995679acaf238686e2f287bfaa0221a7
2013-06-12 23:25:09 -07:00
5a92c1a5e9 bump version to 0.3.1
libwebp{,decoder} - 0.3.1
libwebp libtool - 4.3.0 (compatible release)
libwebpdecoder libtool - 0.1.0 (compatible release)

mux/demux - 0.1.1
libtool - 0.1.0 (compatible release)

Change-Id: Icc8329a6bcd9eea5a715ea83f1535a66d6ba4b58
2013-06-12 23:19:13 -07:00
86daf77c47 store top Y/U/V samples in packed fashion
More cache-line friendly than storing them split.

Change-Id: Ifb23cc3518ff1b5c37afe007558d4278868d75ea
2013-06-13 06:01:27 +02:00
67bc353e6d Revert "add WebPBlendAlpha() function to blend colors against background"
This reverts commit dcbb1ca54a.

Dropping this for now to maintain compatibility for 0.3.1.

Change-Id: I44e032a072d317bb67e1439c42cff923e603038f
2013-06-12 15:02:09 -07:00
068db59e26 Intertwined decoding of alpha and RGB
This will reduce the time to first decoded pixel.

Change-Id: I07b900c0ed4af3aac806b2731e11cd18ec16d016
2013-06-12 14:10:59 -07:00
38cc011408 Simplify forward-WHT + SSE2 version
no precision loss observed
speed is not really faster (0.5% at max), as forward-WHT isn't called often.

also: replaced a "int << 3" (undefined by C-spec) by a "int * 8"
( supersedes https://gerrit.chromium.org/gerrit/#/c/48739/ )

Change-Id: I2d980ec2f20f4ff6be5636105ff4f1c70ffde401
(cherry picked from commit 9c4ce971a8)
2013-06-12 13:48:11 -07:00
3fa595a571 Support decoding upto given row in DECODE_DATA_FUNC
This is in preparation for supporting Intertwined decoding of RGB and
alpha.

Change-Id: Ie1905d1212f4a00718a64dca020be3f4b1b870ec
2013-06-11 16:00:58 -07:00
520f005f85 DequantizeLevels(): Add 'row' and 'num_rows' args
Change-Id: I0032e25c30f34362105d942f2dbb9ac75200f911
2013-06-11 15:59:21 -07:00
47374b8273 Alpha unfilter for given set of rows
Support reconstruction of small number of rows at a time.

Change-Id: Ief1bc78c7ad011ec6df856551f3beb5f907fd8e0
2013-06-11 15:57:42 -07:00
f32097e0df probe input file and quick-check for WebP format.
Error message is clearer that 'can't create demux object'.

Change-Id: Iec008601892f7cd8399e1948751747ac23305eef
(cherry picked from commit 830f72b7e9)
2013-06-11 15:03:23 -07:00
a2aed1d08c configure: improve gl/glut library test
add a check for a libGL function (glOrtho) in addition to glutMainLoop
when establishing the need for libGL at link time.

fixes vwebp link failure on ubuntu 13.04+

Change-Id: I537e9a5cab5cf4cd8875e06268d2107f377e625e
(cherry picked from commit 2ccf58d648)
2013-06-11 15:03:23 -07:00
c7e89cbb02 update copyright text
rather than symlink the webm/vpx terms, use the same header as libvpx to
reference in-tree files

based on the discussion in:
https://codereview.chromium.org/12771026/

Change-Id: Ia3067ecddefaa7ee01550136e00f7b3f086d4af4
(cherry picked from commit d640614d54)
2013-06-11 15:03:22 -07:00
a00380d2ed configure: remove use of AS_VAR_APPEND
This wasn't used often and benefits were likely minimal. Dropping it
outright is a bit simpler than adding a compatibility ifdef.

provides some compatibility with older versions of autoconf.
tested with autoconf 2.59/automake 1.7/aclocal 1.7

Change-Id: Ifed892346cf2329597985704830a96fc58d65607
(cherry picked from commit 9326a56f8d)
2013-06-11 15:03:22 -07:00
a94a88dd62 fix EXIF parsing in PNG
'exiftool' puts an 'APP1' chunk for exif, e.g.:
https://metacpan.org/source/EXIFTOOL/Image-ExifTool-5.87/lib/Image/ExifTool/PNG.pm#L305

Change-Id: I313d3e6945898526b8a4baf3d9016a2591a1a817
(cherry picked from commit bec11092ca)
2013-06-11 15:03:22 -07:00
a71e5d84e9 add doc precision for WebPPictureCopy() and WebPPictureView()
output picture object is overwritten, not free'd or destroyed.

Change-Id: Ibb47ab444063e7ad90ff3d296260807ffe7ddbf9
(cherry picked from commit 23d28e216d)
2013-06-11 15:03:21 -07:00
8287012ec7 remove datatype qualifier for vmnv
this fix is for clang (LLVM v4.2). gcc was fine.

Change-Id: Id4076cda84813f6f9548a01775b094cff22b4be9
(cherry picked from commit 3fe91635df)
2013-06-11 15:03:21 -07:00
e190843029 fix a memory leak in gif2webp
(rgba->yuv allocates memory)
Also fixed few warning and cleaned the code up.

Change-Id: Id904ad3ad8802ea9fc3d34247d27193dfa7b0b99
(cherry picked from commit 764fdffaac)
2013-06-11 15:03:21 -07:00
0b18b9eef6 fix two minor memory leaks in webpmux
(only occur in case of error)

Change-Id: Icab69bb364b77f8eae6cae91047354c27e610602
(cherry picked from commit 3e59a74d72)
2013-06-11 15:03:21 -07:00
db5095d5b6 remove some cruft from swig/libwebp.jar
picked up a few unnecessary classes from a dirty tree in the last commit

Change-Id: I98be16a0bc8716476ce440da542d113f254aee78
(cherry picked from commit 325d15ff30)
2013-06-11 15:03:21 -07:00
850e956f9b README: update swig notes
add python, required version notes

Change-Id: Iec2e94075f6cf54455ce5a658f9b7258109f4d01
(cherry picked from commit 4a7627c215)
2013-06-11 15:03:21 -07:00
bddd9b0a93 swig/python: add minimal documentation
uses autodoc to display the function arguments rather than the
inscrutable va_args (*args).

Change-Id: Iec2ff8276c1533b14c3032836d822fbdae632521
(cherry picked from commit 825b64db53)
2013-06-11 15:00:48 -07:00
d573a8d53f swig: add python encode support
wraps the simple interface similar to java.

Change-Id: Ib922bbcae322b2345b6dce5dee08faad705a77fd
(cherry picked from commit 14677e11d4)
2013-06-11 15:00:47 -07:00
6b931875ac swig/java: reduce wrapper function code duplication
define a macro to emit the wrapper code

Change-Id: I672416016162d6d9ce6f455d224044e0837e3ace
(cherry picked from commit a5c297c842)
2013-06-11 15:00:47 -07:00
6fe536f4ba swig/java: rework uint8_t typemap
reuse the declarations from arrays_java.i for signed char to make an
explicit uint8_t mapping. this avoids sign conversion build warnings.

Change-Id: Icfb5b865cf1fd404e89f2cd889111f0a94e3c604
(cherry picked from commit ad4a367dba)
2013-06-11 15:00:47 -07:00
a2ea46439e Fix the bug in ApplyPalette.
The auto-infer logic of detecting the 'Alpha' use case
(via check '(palette[i] & 0x00ff00ffu) != 0' is failing
for this corner case image with all black pixels (rgb = 0)
and different Alpha values.

-> switch generic use-LUT detection

Change-Id: I982a8b28c8bcc43e3dc68ac358f978a4bcc14c36
(cherry picked from commit afa3450c11)
2013-06-11 15:00:47 -07:00
7bb28d2a55 webp/lossless: fix big endian BGRA output
Change-Id: I3d4b3d21f561cb526dbe7697a31ea847d3e8b2c1
(cherry picked from commit 2ca83968ae)
2013-06-11 15:00:47 -07:00
f036d4bfa6 Speed up ApplyPalette for ARGB pixels.
Added 1 pixel cache for palette colors for faster lookup.
This will speedup images that require ApplyPalette by 6.5% for lossless
compression.

Change-Id: Id0c5174d797ffabdb09905c2ba76e60601b686f8
(cherry picked from commit 742110ccce)
2013-06-11 15:00:46 -07:00
8112c8cf54 remove some warnings:
* "declaration of ‘index’ shadows a global declaration [-Wshadow]"
* "signed and unsigned type in conditional expression [-Wsign-compare]"

Change-Id: I891182d919b18b6c84048486e0385027bd93b57d
(cherry picked from commit 87a4fca25f)
2013-06-11 15:00:46 -07:00
cc128e0bfc Further reduce memory to decode lossy+alpha images
Earlier such images were using roughly 9 * width * height bytes for
decoding. Now, they take 6 * width * height memory.

Change-Id: Ie4a681ca5074d96d64f30b2597fafdca648dd8f7
(cherry picked from commit 64c844863a)
2013-06-11 15:00:46 -07:00
07db70d20f fix for big-endian
(Issue #150: https://code.google.com/p/webp/issues/detail?id=150)

Change-Id: Iad46d375a8c5eabae37cde8f55b3e7448601f264
(cherry picked from commit 4437061735)
2013-06-11 15:00:46 -07:00
eda8a7dec5 gif2webp: Fix signed/unsigned comparison mismatch
Change-Id: I355f0614424276550db71b24e5bb1948e5c6894c
(cherry picked from commit 043e1ae4bd)
2013-06-11 15:00:46 -07:00
31f346fe0c Makefile.vc: fix libwebpdemux dll variable typo
Fixes issue #149

Patch by: Jason Stevens  (cypher497 at gmail dot com)

Change-Id: I65cceaad37d22b96e5e92cb78f859fc0b7c38b67
(cherry picked from commit 3eeedae1bc)
2013-06-11 15:00:45 -07:00
6c76d28e4b swig: add python (decode) support
similar to Java, simple interface only

Change-Id: I8a3d344e5d89f73627e4e0cb2067512260d46fdd
(cherry picked from commit f980faf417)
2013-06-11 15:00:45 -07:00
b4f5bb6ca3 swig: cosmetics
normalize formatting
- update decode prototypes
- match project function name style

Change-Id: Ib481b5602171b72dbb1a5d462e6d5166e9b8566e
(cherry picked from commit 7f5f42bb36)
2013-06-11 15:00:45 -07:00
498d4dd634 WebP-Lossless encoding improvements.
Lossy (with Alpha) image compression gets 2.3X speedup.
Compressing lossless images is 20%-40% faster now.

Change-Id: I41f0225838b48ae5c60b1effd1b0de72fecb3ae6
(cherry picked from commit 8eae188a62)
2013-06-11 15:00:45 -07:00
26e7244221 swig: ifdef some Java specific code
no implementation change

Change-Id: I077c707e1f6293188e6fa11ba24757009a709f77
(cherry picked from commit c7247c4c68)
2013-06-11 15:00:45 -07:00
8ecec68652 configure: add warning related flags
adds TEST_AND_ADD_CFLAGS function
uses AM_CFLAGS to allow CFLAGS override

Change-Id: I9352aec6e5d905a41d832bf5ad0c8dcd154f7e97
(cherry picked from commit bba4c2b2a6)
2013-06-11 15:00:44 -07:00
e676b04309 configure: add GLUT detection; build vwebp
Change-Id: I7f0964db2d04c22ff9ec274e8cd1cbed7379a165
(cherry picked from commit 0e513f7ae3)
2013-06-11 15:00:44 -07:00
b0ffc43700 Alpha decoding: significantly reduce memory usage
Simply get rid of an intermediate buffer of size width x height, by
using the fact that stride == width in this case.

Change-Id: I92376a2561a3beb6e723e8bcf7340c7f348e02c2
(cherry picked from commit edccd19436)
2013-06-11 15:00:44 -07:00
20aa7a8dd5 configure: add --enable-everything
Change-Id: Ie1b3abd42459de7f789fe985759c465c2a196727
(cherry picked from commit 3cafcc9a8d)
2013-06-11 15:00:44 -07:00
b8307cc08b configure.ac: add some helper macros
library check related variable maintenance -> *_INCLUDES / *_LIBS

CLEAR_LIBVARS / LIBCHECK_PROLOGUE / LIBCHECK_EPILOGUE

Change-Id: I72e292dc1f69b02f69a26639308f247db0471e2b
(cherry picked from commit 4ef1447792)
2013-06-11 15:00:44 -07:00
980e7ae951 Remove the gcc compilation comments
They went out of sync some time ago, and are
no longer really required since we have them
buildable from makefile.unix

Change-Id: Ica2dcf5c55f44365598f832f55204d123d7aa601
(cherry picked from commit a4e1cdbbe8)
2013-06-11 15:00:44 -07:00
7f25ff99fd gif2webp: Fix ICC and XMP support
Change-Id: Ib5aafef388bd191610e4cc2f8180f35cd454f1d3
(cherry picked from commit b26e5ad540)
2013-06-11 15:00:43 -07:00
d8e5321144 Add missing name to AUTHORS
Change-Id: I00092e5bb676b48abc05b94080b589b48c911c82
(cherry picked from commit 46089b207d)
2013-06-11 15:00:43 -07:00
11edf5e24b Demux: Fix a potential memleak
Change-Id: Ic0dcac010da088b791c130be4abacdd8c31e92cf
(cherry picked from commit 94328d6457)
2013-06-11 15:00:43 -07:00
c7b92184df don't forward declare enums
doing so is not part of ISO C; removes some pedantic warnings

Change-Id: I739ad8c5cacc133e2546e9f45c0db9d92fb93d7e
(cherry picked from commit 96e948d7b0)
2013-06-11 15:00:43 -07:00
7a650c6ad6 prevent signed int overflow in left shift ops
force unsigned when shifting by 24.

Change-Id: Ie229d252e2e4078107cd705b09397e686a321ffd
(cherry picked from commit f4f90880a8)
2013-06-11 15:00:43 -07:00
31bea32408 add precision about dynamic output reallocation with IDecoder
The output surface CAN be changed inbetween calls to
WebPIUpdate() or WebPIAppend(), but with precautions.

Change-Id: I899afbd95738a6a8e0e7000f8daef3e74c99ddd8
(cherry picked from commit ff885bfe1f)
2013-06-11 15:00:43 -07:00
c22877f70f Add incremental support for extended format files
This applies to images with optional chunks (e.g. images with ALPH
chunk,
ICCP chunk etc). Before this, the incremental decoding used to work like
non-incremental decoding for such files, that is, no rows were decoded
until
all data was available.

The change is in 2 parts:
- During optional chunk parsing, don't wait for the full VP8/VP8L chunk.
- Remap 'alpha_data' pointer whenever a new buffer is allocated/used in
WebPIAppend() and WebPIUpdate().

Change-Id: I6cfd6ca1f334b9c6610fcbf662cd85fa494f2a91
(cherry picked from commit ead4d47859)
2013-06-11 15:00:42 -07:00
5051245f3a Makefile.vc: have 'all' target build everything
default is still the core examples as makefile.unix

Change-Id: Ica3fe6123f4359aefa130b39d2b0739b65e34c0b
(cherry picked from commit 69d0f92658)
2013-06-11 15:00:42 -07:00
8191decae9 Makefile.vc: flags cleanup
- drop some unnecessary link flags
- use lib.exe directly for creating libraries
- factorize /nologo and use it consistently

Change-Id: Ie76119bc051e9bc53e4d6bba1a0a3f124f9062fc
(cherry picked from commit 52967498b3)
2013-06-11 15:00:42 -07:00
b9d747351a Makefile.vc: drop /FD flag
breaks under wine; from MSDN:
/FD is only used by the development environment, and it should not be
used from the command line or a build script.

Change-Id: I180c9813e721b163cc645b9b7f14fe36556019d3
(cherry picked from commit c61baf0c10)
2013-06-11 15:00:42 -07:00
5568dbcfe6 update gitignore
*.a, new examples and new automake-1.12 file (ar-lib)

Change-Id: I28d7bc59a2977a7c5959940936e3d13a71dd149c
(cherry picked from commit 3a15125d2f)
2013-06-11 15:00:42 -07:00
f4c7b6547b WebPEncode: An additional check.
Start VP8EncLoop/VP8EncTokenLoop only if VP8EncStartAlpha succeeded.

Change-Id: Id1faca3e6def88102329ae2b4974bd4d6d4c4a7a
(cherry picked from commit 67708d6701)
2013-06-11 15:00:42 -07:00
1fb04bec99 pngdec: Avoid a double-free.
Earlier, at line#275, if ok == 0, it would have triggered a double free
of 'rgb'.

Change-Id: Iaee1f35824a66f6e4b488e523416f73b87c5ec30
(cherry picked from commit b68912af2c)
2013-06-11 15:00:42 -07:00
dcbb1ca54a add WebPBlendAlpha() function to blend colors against background
new option: -blend_alpha 0xrrggbb
also: don't force picture.use_argb value for lossless. Instead,
delay the YUVA<->ARGB conversion till WebPEncode() is called.
This make the blending more accurate when source is ARGB
and lossy compression is used (YUVA).
This has an effect on cropping/rescaling. E.g. for PNG, these
are now done in ARGB colorspace instead of YUV when lossy compression
is used.

Change-Id: I18571f1b1179881737a8dbd23ad0aa8cddae3c6b
(cherry picked from commit e7d9548c9b)
2013-06-11 15:00:41 -07:00
bc9f5fbe0f configure.ac: add AM_PROG_AR for automake >= 1.12
fixes:
automake-1.12/am/ltlibrary.am: warning: 'libwebp.la': linking libtool libraries using a non-POSIX
automake-1.12/am/ltlibrary.am: archiver requires 'AM_PROG_AR' in 'configure.ac'

Change-Id: I223f93e5f075aaf23cfefceef55e2ab8eeb34ccd
(cherry picked from commit ed4dc71769)
2013-06-11 15:00:41 -07:00
bf867bf296 Tuned cross_color parameter (step) for lower qual
Tuned the cross_color transform parameter (step) for lower quality
levels. This change gives speedup of 20% at lower qualities (25) and 10% at
moderate quality level (50) with a loss of 0.25% in compression density.
Also removed TODO for cross_color transform. Observed good correlation of
this with the predict transform.

Change-Id: I8a1044e9f24e6a5f84295c030fd444d0eec7d154
2013-06-11 12:15:07 -07:00
90e2ec5a1b Merge "probe input file and quick-check for WebP format." 2013-06-10 12:29:58 -07:00
7180d7ffbd Merge "update copyright text" 2013-06-10 12:23:44 -07:00
830f72b7e9 probe input file and quick-check for WebP format.
Error message is clearer that 'can't create demux object'.

Change-Id: Iec008601892f7cd8399e1948751747ac23305eef
2013-06-10 05:46:22 -07:00
2ccf58d648 configure: improve gl/glut library test
add a check for a libGL function (glOrtho) in addition to glutMainLoop
when establishing the need for libGL at link time.

fixes vwebp link failure on ubuntu 13.04+

Change-Id: I537e9a5cab5cf4cd8875e06268d2107f377e625e
2013-06-07 20:15:53 -07:00
d640614d54 update copyright text
rather than symlink the webm/vpx terms, use the same header as libvpx to
reference in-tree files

based on the discussion in:
https://codereview.chromium.org/12771026/

Change-Id: Ia3067ecddefaa7ee01550136e00f7b3f086d4af4
2013-06-06 23:09:14 -07:00
c2113ad4f9 Merge "configure: remove use of AS_VAR_APPEND" 2013-06-06 00:23:29 -07:00
9326a56f8d configure: remove use of AS_VAR_APPEND
This wasn't used often and benefits were likely minimal. Dropping it
outright is a bit simpler than adding a compatibility ifdef.

provides some compatibility with older versions of autoconf.
tested with autoconf 2.59/automake 1.7/aclocal 1.7

Change-Id: Ifed892346cf2329597985704830a96fc58d65607
2013-06-06 00:14:02 -07:00
ea63d61937 fix a type warning on VS9 x86
"warning C4244: 'function' : conversion from 'uint64_t' to 'size_t', possible loss of data"

Change-Id: Ibd9f6a24993518d658d08127d616a17d7b99e0e4
2013-06-05 10:14:04 +02:00
bec11092ca fix EXIF parsing in PNG
'exiftool' puts an 'APP1' chunk for exif, e.g.:
https://metacpan.org/source/EXIFTOOL/Image-ExifTool-5.87/lib/Image/ExifTool/PNG.pm#L305

Change-Id: I313d3e6945898526b8a4baf3d9016a2591a1a817
2013-06-05 10:07:48 +02:00
b6e65f3d35 Merge "fix warnings for vs9 x64" 2013-06-03 22:27:03 -07:00
438946dcc6 fix warnings for vs9 x64
Change-Id: Id022d48a0a898a8bf7dce437b078da6c98afd75c
2013-06-01 22:48:08 -07:00
f4710e3b89 collect macroblock reconstruction data in VP8MBData struct
This is to better separate bitstream parsing from reconstruction.

Change-Id: I872b58e9940c4b14f72ebee50fba545468ff754c
2013-05-31 22:38:12 +02:00
23d28e216d add doc precision for WebPPictureCopy() and WebPPictureView()
output picture object is overwritten, not free'd or destroyed.

Change-Id: Ibb47ab444063e7ad90ff3d296260807ffe7ddbf9
2013-05-31 10:41:19 +02:00
518f2cd738 cosmetics: gif2webp: fix indent
Change-Id: I9b7aaefb33b4101bcb572577ce17fb3953599c2b
2013-05-29 16:00:05 -07:00
af358e68ed Merge "remove datatype qualifier for vmnv" 2013-05-23 06:12:06 -07:00
3fe91635df remove datatype qualifier for vmnv
this fix is for clang (LLVM v4.2). gcc was fine.

Change-Id: Id4076cda84813f6f9548a01775b094cff22b4be9
2013-05-23 13:52:24 +02:00
764fdffaac fix a memory leak in gif2webp
(rgba->yuv allocates memory)
Also fixed few warning and cleaned the code up.

Change-Id: Id904ad3ad8802ea9fc3d34247d27193dfa7b0b99
2013-05-22 23:49:24 +02:00
3e59a74d72 fix two minor memory leaks in webpmux
(only occur in case of error)

Change-Id: Icab69bb364b77f8eae6cae91047354c27e610602
2013-05-22 00:58:53 +02:00
47b9862f30 Merge "README: update swig notes" 2013-05-21 15:09:30 -07:00
325d15ff30 remove some cruft from swig/libwebp.jar
picked up a few unnecessary classes from a dirty tree in the last commit

Change-Id: I98be16a0bc8716476ce440da542d113f254aee78
2013-05-21 15:01:15 -07:00
4a7627c215 README: update swig notes
add python, required version notes

Change-Id: Iec2e94075f6cf54455ce5a658f9b7258109f4d01
2013-05-21 14:58:32 -07:00
5da81e3383 Merge "swig/python: add minimal documentation" 2013-05-21 14:49:46 -07:00
f39e08f2e3 Merge "swig: add python encode support" 2013-05-21 14:48:36 -07:00
6ca4a3e385 Merge "swig/java: reduce wrapper function code duplication" 2013-05-21 14:44:16 -07:00
8f8702b034 Merge "swig/java: rework uint8_t typemap" 2013-05-21 14:42:58 -07:00
91413be2f9 reduce memory for VP8MB and remove bitfields use
~1% faster on ARMv7

Change-Id: I3e3524e0c25ebd31a04269aae0d304932f1a781a
2013-05-21 23:20:04 +02:00
7413394e7f Fix the memory leak in ApplyFilters.
Change-Id: Iba1b1adf3088ea9c43e4f602a93e77450f6c6170
2013-05-21 14:00:26 -07:00
2053c2cff2 simplify the alpha-filter testing loop
Change-Id: Iacebae749c37edc87a3c94c76cd589a2565ee642
2013-05-21 10:29:27 +02:00
825b64db53 swig/python: add minimal documentation
uses autodoc to display the function arguments rather than the
inscrutable va_args (*args).

Change-Id: Iec2ff8276c1533b14c3032836d822fbdae632521
2013-05-20 17:14:51 -07:00
14677e11d4 swig: add python encode support
wraps the simple interface similar to java.

Change-Id: Ib922bbcae322b2345b6dce5dee08faad705a77fd
2013-05-20 17:14:50 -07:00
a5c297c842 swig/java: reduce wrapper function code duplication
define a macro to emit the wrapper code

Change-Id: I672416016162d6d9ce6f455d224044e0837e3ace
2013-05-20 17:13:27 -07:00
ad4a367dba swig/java: rework uint8_t typemap
reuse the declarations from arrays_java.i for signed char to make an
explicit uint8_t mapping. this avoids sign conversion build warnings.

Change-Id: Icfb5b865cf1fd404e89f2cd889111f0a94e3c604
2013-05-20 13:16:14 -07:00
0d25876bad use uint8_t for inv_palette[]
Change-Id: I5005ce68d89bfb657d46ad8acc4368c29fa0c4fd
2013-05-18 17:13:58 +02:00
afa3450c11 Fix the bug in ApplyPalette.
The auto-infer logic of detecting the 'Alpha' use case
(via check '(palette[i] & 0x00ff00ffu) != 0' is failing
for this corner case image with all black pixels (rgb = 0)
and different Alpha values.

-> switch generic use-LUT detection

Change-Id: I982a8b28c8bcc43e3dc68ac358f978a4bcc14c36
2013-05-18 17:03:18 +02:00
2d6ac422cf Merge "webp/lossless: fix big endian BGRA output" 2013-05-17 00:36:15 -07:00
2ca83968ae webp/lossless: fix big endian BGRA output
Change-Id: I3d4b3d21f561cb526dbe7697a31ea847d3e8b2c1
2013-05-17 00:32:01 -07:00
742110ccce Speed up ApplyPalette for ARGB pixels.
Added 1 pixel cache for palette colors for faster lookup.
This will speedup images that require ApplyPalette by 6.5% for lossless
compression.

Change-Id: Id0c5174d797ffabdb09905c2ba76e60601b686f8
2013-05-16 15:44:21 -07:00
2451e47dca misc code cleanup
* remove dec->skip_
* fix some naming

(no speed diff observed)

Change-Id: I12545ef79d29dd6f893c344d8fb171b0a8c7cc46
2013-05-15 20:03:15 +02:00
83db404390 Merge "swig: add python (decode) support" 2013-05-15 00:42:36 -07:00
eeeea8b530 Merge "swig: cosmetics" 2013-05-15 00:42:08 -07:00
d5f9b8f383 Merge "libwebp: fix vp8 encoder mem alloc offsetting" 2013-05-15 00:41:14 -07:00
d8edd83551 libwebp: fix vp8 encoder mem alloc offsetting
'mem' was being offset once by DO_ALIGN() then shifted 'nz_size' which
would end up accounting for more than ALIGN_CST and exceed the allocation.

broken since:
  9bf3129 align VP8Encoder::nz_ allocation

Change-Id: I04a4e0bbf80d909253ce057f8550ed98e0cf1054
2013-05-15 00:31:23 -07:00
8983b83ee1 remove use of bit-fields in VP8FInfo
(in favor of just plain uint8_t's)

Change-Id: I6187587a4d8a9f5c304a132d98ec42ce24fd244a
2013-05-15 09:21:30 +02:00
87a4fca25f remove some warnings:
* "declaration of ‘index’ shadows a global declaration [-Wshadow]"
* "signed and unsigned type in conditional expression [-Wsign-compare]"

Change-Id: I891182d919b18b6c84048486e0385027bd93b57d
2013-05-14 22:28:32 +02:00
ba8f74e229 Merge "fix for big-endian" 2013-05-14 01:58:06 -07:00
a65067fa77 Merge "Further reduce memory to decode lossy+alpha images" 2013-05-14 01:56:54 -07:00
64c844863a Further reduce memory to decode lossy+alpha images
Earlier such images were using roughly 9 * width * height bytes for
decoding. Now, they take 6 * width * height memory.

Change-Id: Ie4a681ca5074d96d64f30b2597fafdca648dd8f7
2013-05-13 16:24:49 -07:00
332130b9b3 Mux: make a few methods static
Change-Id: I8a8b0b403116c89933e84c93502a8230026f819e
2013-05-13 13:26:33 -07:00
4437061735 fix for big-endian
(Issue #150: https://code.google.com/p/webp/issues/detail?id=150)

Change-Id: Iad46d375a8c5eabae37cde8f55b3e7448601f264
2013-05-13 10:19:29 -07:00
5199eab516 Merge "add uncompressed TIFF output support" 2013-05-13 08:59:48 -07:00
a3aede9739 add uncompressed TIFF output support
new option: 'dwebp -tiff ...'
This is a very simple uncompressed-tiff writing method.

Change-Id: Ie2182c8498bce570de3cde363abe1099e18596cb
2013-05-11 01:46:24 -07:00
f975b67f66 Merge "gif2webp: Fix signed/unsigned comparison mismatch" 2013-05-11 00:53:20 -07:00
5fbc734b90 Merge "GetFeatures: Detect invalid VP8X/VP8/VP8L data" 2013-05-11 00:51:39 -07:00
d5060c873c Merge "mux.h: A comment fix + some consistency fixes" 2013-05-11 00:41:35 -07:00
352d0dee99 GetFeatures: Detect invalid VP8X/VP8/VP8L data
This facilitates early error detection during decode/render.
Also, related refactoring.

Change-Id: Ia6c7cd91dec202a2a68dae2118f5981cf1eaa83d
2013-05-10 14:27:11 -07:00
3ef79fefec Cosmetic: "width * height"
Change-Id: I567c0d95355160a9f6721f949b38e2b8b6270b7a
2013-05-10 13:39:58 -07:00
043e1ae4bd gif2webp: Fix signed/unsigned comparison mismatch
Change-Id: I355f0614424276550db71b24e5bb1948e5c6894c
2013-05-10 13:37:20 -07:00
5818cff770 mux.h: A comment fix + some consistency fixes
Change-Id: I0aee1090322bac3ae3dabf9a48661cbb6de3ca52
2013-05-10 13:35:16 -07:00
1153f888c9 Merge "swig: ifdef some Java specific code" 2013-05-10 02:00:02 -07:00
3eeedae1bc Makefile.vc: fix libwebpdemux dll variable typo
Fixes issue #149

Patch by: Jason Stevens  (cypher497 at gmail dot com)

Change-Id: I65cceaad37d22b96e5e92cb78f859fc0b7c38b67
2013-05-09 23:49:39 -07:00
f980faf417 swig: add python (decode) support
similar to Java, simple interface only

Change-Id: I8a3d344e5d89f73627e4e0cb2067512260d46fdd
2013-05-09 23:29:35 -07:00
7f5f42bb36 swig: cosmetics
normalize formatting
- update decode prototypes
- match project function name style

Change-Id: Ib481b5602171b72dbb1a5d462e6d5166e9b8566e
2013-05-08 18:00:30 -07:00
8eae188a62 WebP-Lossless encoding improvements.
Lossy (with Alpha) image compression gets 2.3X speedup.
Compressing lossless images is 20%-40% faster now.

Change-Id: I41f0225838b48ae5c60b1effd1b0de72fecb3ae6
2013-05-08 17:22:11 -07:00
c7247c4c68 swig: ifdef some Java specific code
no implementation change

Change-Id: I077c707e1f6293188e6fa11ba24757009a709f77
2013-05-08 17:13:40 -07:00
4cb234d5b5 Merge "Mux: make ValidateForSingleImage() method static" 2013-05-08 01:54:28 -07:00
ed6f53086b Merge "Add GetCanvasSize() method to mux" 2013-05-08 01:53:22 -07:00
1d530c9a7e Mux: make ValidateForSingleImage() method static
Change-Id: I96ac5e3be26b8e8ecd9f055501a5feb7710bc324
2013-05-07 12:57:51 -07:00
bba4c2b2a6 configure: add warning related flags
adds TEST_AND_ADD_CFLAGS function
uses AM_CFLAGS to allow CFLAGS override

Change-Id: I9352aec6e5d905a41d832bf5ad0c8dcd154f7e97
2013-05-07 12:48:12 -07:00
fffefd18c3 Add GetCanvasSize() method to mux
Change-Id: If910f5024f4c301a92e6c2e8ee9c315a103c5df7
2013-05-07 12:47:48 -07:00
732da8d0f0 Merge "configure: add GLUT detection; build vwebp" 2013-05-07 12:15:50 -07:00
0e513f7ae3 configure: add GLUT detection; build vwebp
Change-Id: I7f0964db2d04c22ff9ec274e8cd1cbed7379a165
2013-05-07 11:42:15 -07:00
55d1c150ea Merge "Alpha decoding: significantly reduce memory usage" 2013-05-07 09:14:56 -07:00
13d99fb58b Merge "configure: add --enable-everything" 2013-05-07 08:50:57 -07:00
2bf698fe49 Merge "configure.ac: add some helper macros" 2013-05-07 08:49:21 -07:00
edccd19436 Alpha decoding: significantly reduce memory usage
Simply get rid of an intermediate buffer of size width x height, by
using the fact that stride == width in this case.

Change-Id: I92376a2561a3beb6e723e8bcf7340c7f348e02c2
2013-05-02 18:24:46 -07:00
3cafcc9a8d configure: add --enable-everything
Change-Id: Ie1b3abd42459de7f789fe985759c465c2a196727
2013-05-01 18:25:00 -07:00
4ef1447792 configure.ac: add some helper macros
library check related variable maintenance -> *_INCLUDES / *_LIBS

CLEAR_LIBVARS / LIBCHECK_PROLOGUE / LIBCHECK_EPILOGUE

Change-Id: I72e292dc1f69b02f69a26639308f247db0471e2b
2013-05-01 18:24:49 -07:00
a4e1cdbbe8 Remove the gcc compilation comments
They went out of sync some time ago, and are
no longer really required since we have them
buildable from makefile.unix

Change-Id: Ica2dcf5c55f44365598f832f55204d123d7aa601
2013-05-01 15:01:37 -07:00
6393fe4b7c Cosmetic fixes
Change-Id: I7d5a337077ba1d0406769190fef9b47146ed8b24
2013-04-26 15:55:42 -07:00
9c4ce971a8 Simplify forward-WHT + SSE2 version
no precision loss observed
speed is not really faster (0.5% at max), as forward-WHT isn't called often.

also: replaced a "int << 3" (undefined by C-spec) by a "int * 8"
( supersedes https://gerrit.chromium.org/gerrit/#/c/48739/ )

Change-Id: I2d980ec2f20f4ff6be5636105ff4f1c70ffde401
2013-04-26 08:57:18 +02:00
878b9da5bf fix missed optim
it's not often the case, but could happen, that chroma has non-zero
coeff but luma hasn't. In such case, we should skip luma right away

Change-Id: I9515573ffaec8aad8b069d2c02ffbda4a6eff97c
2013-04-25 22:46:12 +02:00
00046171a5 VP8GetInfo(): Check for zero width or height.
Change-Id: I0bf40621ed0776e1a185ad8abab5a914a3d29d69
2013-04-25 12:08:40 -07:00
9bf312938f align VP8Encoder::nz_ allocation
prevents unaligned uint32_t load/store

Change-Id: I3f5e1b434a7452f618009d5e4bbe4f3260e3e321
2013-04-25 02:55:39 -07:00
5da165cfad fix CheckMode() signature
should have been 'const VP8Decoder* const dec', but actually
we just need to pass mb_x_ and mb_y_

Change-Id: I21ca0d67ab33302d6eaa45698d53ed6c2de76981
2013-04-24 14:33:44 +02:00
0ece07dcb1 Merge "explicitly pad bitfields to 32-bits" 2013-04-22 13:13:29 -07:00
9dbc9d1909 explicitly pad bitfields to 32-bits
suggested by fbarchard@chromium; may affect alignment in some cases

Change-Id: I63552eb1a0f9e81754d30ce6e9b1cfe5748bdbc9
2013-04-22 13:00:28 -07:00
5369a80fd4 Merge "prevent signed int overflow in left shift ops" 2013-04-19 00:13:16 -07:00
70e3971260 Merge "cosmetics: remove unnecessary ';'s" 2013-04-19 00:11:10 -07:00
d3136ce27d Merge "don't forward declare enums" 2013-04-19 00:10:39 -07:00
b26e5ad540 gif2webp: Fix ICC and XMP support
Change-Id: Ib5aafef388bd191610e4cc2f8180f35cd454f1d3
2013-04-18 14:19:25 -07:00
46089b207d Add missing name to AUTHORS
Change-Id: I00092e5bb676b48abc05b94080b589b48c911c82
2013-04-18 11:29:36 +02:00
94328d6457 Demux: Fix a potential memleak
Change-Id: Ic0dcac010da088b791c130be4abacdd8c31e92cf
2013-04-16 14:13:45 -07:00
96e948d7b0 don't forward declare enums
doing so is not part of ISO C; removes some pedantic warnings

Change-Id: I739ad8c5cacc133e2546e9f45c0db9d92fb93d7e
2013-04-13 11:08:42 -07:00
f4f90880a8 prevent signed int overflow in left shift ops
force unsigned when shifting by 24.

Change-Id: Ie229d252e2e4078107cd705b09397e686a321ffd
2013-04-13 10:57:31 -07:00
0261545e0b cosmetics: remove unnecessary ';'s
Change-Id: I5fefd9a5b2fe3795c2b5d785c30335b85bac0b43
2013-04-13 10:49:35 -07:00
7ebdf110af Merge "Fix few missing comparisons to NULL" 2013-04-13 10:42:51 -07:00
1579989e7b Fix few missing comparisons to NULL
Change-Id: I0d2ff8e8b507d17e80669b2b59fd5b017af995ed
2013-04-13 10:36:33 -07:00
ea1b21cfdb Cleaned up VP8GetHeaders() so that it parses only frame header
Removed a call to WebPParseHeaders() inside VP8GetHeaders(). This was not needed
anyway, as all call flows already call WebPParseHeaders() before calling
VP8GetHeaders().

This avoids duplicate calls to WebPParseHeaders().

Change-Id: Icb2d618bd26c44220d956c17a69c9c45a62d5237
2013-04-11 11:35:18 -07:00
b66caee410 dwebp: add support for BMP output
Supports alpha output too.

Change-Id: I42ea0bf7b6bbb420f0e537d372a3b13fe00528a9
2013-04-09 18:52:34 -07:00
ff885bfe1f add precision about dynamic output reallocation with IDecoder
The output surface CAN be changed inbetween calls to
WebPIUpdate() or WebPIAppend(), but with precautions.

Change-Id: I899afbd95738a6a8e0e7000f8daef3e74c99ddd8
2013-04-09 18:05:11 -07:00
79241d5a0d Merge "Makefile.vc: have 'all' target build everything" 2013-04-09 14:02:22 -07:00
ac1c729bd8 Merge "Makefile.vc: flags cleanup" 2013-04-08 17:21:24 -07:00
118a055c3d Merge "Makefile.vc: drop /FD flag" 2013-04-08 17:20:32 -07:00
ecad0109d5 Merge "update gitignore" 2013-04-08 17:20:02 -07:00
a681b4f4e5 Rename PRE_VP8 state to WEBP_HEADER
Also, rename state VP8_FRAME_HEADER to VP8_HEADER (to be consistent with
VP8L_HEADER).

Change-Id: Ief2d2f483e36d37f00d8d0db87026ad059f27327
2013-04-08 14:46:05 -07:00
ead4d47859 Add incremental support for extended format files
This applies to images with optional chunks (e.g. images with ALPH
chunk,
ICCP chunk etc). Before this, the incremental decoding used to work like
non-incremental decoding for such files, that is, no rows were decoded
until
all data was available.

The change is in 2 parts:
- During optional chunk parsing, don't wait for the full VP8/VP8L chunk.
- Remap 'alpha_data' pointer whenever a new buffer is allocated/used in
WebPIAppend() and WebPIUpdate().

Change-Id: I6cfd6ca1f334b9c6610fcbf662cd85fa494f2a91
2013-04-08 14:29:14 -07:00
69d0f92658 Makefile.vc: have 'all' target build everything
default is still the core examples as makefile.unix

Change-Id: Ica3fe6123f4359aefa130b39d2b0739b65e34c0b
2013-04-05 19:21:01 -07:00
52967498b3 Makefile.vc: flags cleanup
- drop some unnecessary link flags
- use lib.exe directly for creating libraries
- factorize /nologo and use it consistently

Change-Id: Ie76119bc051e9bc53e4d6bba1a0a3f124f9062fc
2013-04-05 18:47:18 -07:00
c61baf0c10 Makefile.vc: drop /FD flag
breaks under wine; from MSDN:
/FD is only used by the development environment, and it should not be
used from the command line or a build script.

Change-Id: I180c9813e721b163cc645b9b7f14fe36556019d3
2013-04-05 14:54:05 -07:00
3a15125d2f update gitignore
*.a, new examples and new automake-1.12 file (ar-lib)

Change-Id: I28d7bc59a2977a7c5959940936e3d13a71dd149c
2013-04-05 14:51:02 -07:00
5167ca4759 Merge "WebPEncode: An additional check. Start VP8EncLoop/VP8EncTokenLoop only if VP8EncStartAlpha succeeded." 2013-04-05 12:00:46 -07:00
67708d6701 WebPEncode: An additional check.
Start VP8EncLoop/VP8EncTokenLoop only if VP8EncStartAlpha succeeded.

Change-Id: Id1faca3e6def88102329ae2b4974bd4d6d4c4a7a
2013-04-05 11:33:44 -07:00
b68912af2c pngdec: Avoid a double-free.
Earlier, at line#275, if ok == 0, it would have triggered a double free
of 'rgb'.

Change-Id: Iaee1f35824a66f6e4b488e523416f73b87c5ec30
2013-04-05 11:24:59 -07:00
82abbe12fb Merge "configure.ac: add AM_PROG_AR for automake >= 1.12" 2013-04-04 20:09:00 -07:00
e7d9548c9b add WebPBlendAlpha() function to blend colors against background
new option: -blend_alpha 0xrrggbb
also: don't force picture.use_argb value for lossless. Instead,
delay the YUVA<->ARGB conversion till WebPEncode() is called.
This make the blending more accurate when source is ARGB
and lossy compression is used (YUVA).
This has an effect on cropping/rescaling. E.g. for PNG, these
are now done in ARGB colorspace instead of YUV when lossy compression
is used.

Change-Id: I18571f1b1179881737a8dbd23ad0aa8cddae3c6b
2013-04-02 19:14:30 -07:00
ed4dc71769 configure.ac: add AM_PROG_AR for automake >= 1.12
fixes:
automake-1.12/am/ltlibrary.am: warning: 'libwebp.la': linking libtool libraries using a non-POSIX
automake-1.12/am/ltlibrary.am: archiver requires 'AM_PROG_AR' in 'configure.ac'

Change-Id: I223f93e5f075aaf23cfefceef55e2ab8eeb34ccd
2013-04-02 18:45:02 -07:00
df4a406d8d Merge branch '0.3.0'
* 0.3.0: (65 commits)
  Update ChangeLog
  Cosmetic fixes
  misc style fix
  add missing YUVA->ARGB automatic conversion in WebPEncode()
  Container spec: Clarify frame disposal
  container doc: add a note about the 'ANMF' payload
  Container spec: clarify the background color field
  container doc: move RIFF description to own section
  libwebp/mux: fix double free
  use WebPDataCopy() instead of re-coding it.
  demux: keep a frame tail pointer; used in AddFrame
  add doc precision about WebPParseHeaders() return codes
  gif2webp: Bgcolor fix for a special case
  fix bad saturation order in QuantizeBlock
  vwebp/animation: fix background dispose
  Makefile.vc: fix dynamic builds
  update ChangeLog
  examples: don't use C99 %zu
  update ChangeLog
  update NEWS
  ...

Conflicts:
	src/webp/format_constants.h

Change-Id: Ie659644d3ea5592cde64ec3af90a00cd17838247
2013-04-01 19:11:52 -07:00
1e0d4b8c8b Update ChangeLog
Change-Id: I381ab93458df3d1851aec36161cc4b2cbd1265be
2013-03-29 15:55:16 -07:00
d52b405dbd Cosmetic fixes
Change-Id: Ia878115086edc3fdfee3f0ca76e5e74ea5906f21
(cherry picked from commit e9a7990bc5)
2013-03-29 15:49:15 -07:00
6cb4a61825 misc style fix
(cherry picked from commit 142c46291e)

Conflicts:
	src/webp/format_constants.h

Change-Id: Ib764cb09bd78ab6e72c60f495d55b752ad4dbe4d
2013-03-29 15:49:05 -07:00
68111ab02f add missing YUVA->ARGB automatic conversion in WebPEncode()
user can now call WebPEncode() with any YUVA or ARGB format, for
lossy or lossless compression

also: simplified error reporting, which is done in WebPPictureARGBToYUVA()
and WebPPictureYUVAToARGB()

Change-Id: Ifb68909217175bcf5a050e5c68d06de9849468f7
(cherry picked from commit 07d87bda1b)
2013-03-29 15:33:14 -07:00
e9a7990bc5 Cosmetic fixes
Change-Id: Ia878115086edc3fdfee3f0ca76e5e74ea5906f21
2013-03-29 14:21:56 -07:00
403bfe820c Container spec: Clarify frame disposal
- Add a note that disposal only applies to the frame rectangle
- Add the formula for alpha-blending.
- Note that alpha-blending would occur for the common rectangle
- Also note the case when both color profile and disposal are
present.

Change-Id: I214787dd64453edf3b0cdaff3951015281a32ee4
2013-03-29 11:42:17 -07:00
2aaa423b20 Merge "add missing YUVA->ARGB automatic conversion in WebPEncode()" 2013-03-29 11:39:04 -07:00
07d87bda1b add missing YUVA->ARGB automatic conversion in WebPEncode()
user can now call WebPEncode() with any YUVA or ARGB format, for
lossy or lossless compression

also: simplified error reporting, which is done in WebPPictureARGBToYUVA()
and WebPPictureYUVAToARGB()

Change-Id: Ifb68909217175bcf5a050e5c68d06de9849468f7
2013-03-29 04:31:37 -07:00
142c46291e misc style fix
Change-Id: Ib764cb09bd78ab6e72c60f495d55b752ad4dbe4d
2013-03-29 03:13:43 -07:00
3e7a13a008 Merge "Container spec: clarify the background color field" into 0.3.0 2013-03-26 17:38:07 -07:00
14af77452b container doc: add a note about the 'ANMF' payload
this consists of padded chunks, so ANMF should require none

Change-Id: I5dff623b56d8a466dc9be03ee87d1d2d19efc088
2013-03-26 17:25:27 -07:00
cc635efa01 Container spec: clarify the background color field
Change-Id: I03f634cbd147c2851eb06ddbc7b1014e04e21038
2013-03-26 17:22:18 -07:00
e3e339497e container doc: move RIFF description to own section
- remove some little used terms
- condense file header description
- add description of FourCC

Change-Id: Ia873652f41789811f3fb2ec97182a068ac727961
2013-03-26 17:16:12 -07:00
4299f39852 libwebp/mux: fix double free
transfer ownership of chunk passed in ChunkSetNth(). prevents freeing
the chunk in e.g., MuxImageParse() when a partial assignment (alpha but
no image) has occurred.

Change-Id: Ia69656b04fdf50f098f3816b54abd4e191248de3
2013-03-26 13:31:47 -07:00
33f9a692d9 Merge "demux: keep a frame tail pointer; used in AddFrame" into 0.3.0 2013-03-26 13:30:10 -07:00
a2a7b95916 use WebPDataCopy() instead of re-coding it.
also: fix some 0 vs NULL tests

Change-Id: I2b6f65a1e658211e5b4a323c4f9f502744206ec7
2013-03-26 20:40:24 +01:00
6f18f12f99 demux: keep a frame tail pointer; used in AddFrame
this speeds up the parse of a file with a large number of frames.

Change-Id: Ibc61324eb50a04438f811a6f7787d378d763c104
2013-03-26 11:27:51 -07:00
e5af49e9c0 add doc precision about WebPParseHeaders() return codes
Change-Id: I970900f4a5abb4877a716bd4eb15939655ef5dad
2013-03-25 17:54:46 -07:00
db46daab97 Merge "Makefile.vc: fix dynamic builds" into 0.3.0 2013-03-25 16:41:26 -07:00
53c77afc52 Merge "gif2webp: Bgcolor fix for a special case" into 0.3.0 2013-03-25 16:33:51 -07:00
a5ebd143d6 gif2webp: Bgcolor fix for a special case
When transparent color index and background color index are same,
we should set background color to 0x00ffffff (transparent).

For this, we delay setting the background color until we have read the
first frame.

Change-Id: I443609b9c7697a2b94a66992460cff8465b3c127
2013-03-25 16:30:27 -07:00
6378f23876 Merge "vwebp/animation: fix background dispose" into 0.3.0 2013-03-25 16:24:02 -07:00
3c8eb9a806 fix bad saturation order in QuantizeBlock
Saturation was done on input coeff, not quantized one.

This saturation is not absolutely needed: output of FTransformWHT
is in range [-16320, 16321]. At quality 100, max quantization steps is 8,
so the maximal range used by QuantizeBlock() is [-2040, 2040].
But there's some extra bias (mtx->bias_[] and mtx->sharpen_[]) so
it's better to leave this saturation check for now.

addresses issue #145

Change-Id: I4b14f71cdc80c46f9eaadb2a4e8e03d396879d28
2013-03-25 14:53:29 -07:00
04c7a2ecf0 vwebp/animation: fix background dispose
buffer the last frame's details to perform DISPOSE_BACKGROUND on the
image's area, rather than the entire canvas.

also fixes transparent backgrounds with animated images

Change-Id: I53e4d70c441e1eeb136f1d01e7c88de4f9ecff53
2013-03-25 13:39:27 -07:00
81a50695de Makefile.vc: fix dynamic builds
broken since:
e2feefa Makefile.vc: split mux into separate lib

broken even more since:
b65c4b7 Makefile.vc: add libwebpdecoder target

Change-Id: Ibb7a7f2c71ae63434a60d988ce15f0a4ed8fcaee
2013-03-21 19:30:34 -07:00
5f25c396ab update ChangeLog
Change-Id: I52d96e616bb8687f69c6eaa2f28d40939a0e7813
2013-03-20 17:09:12 -07:00
14d42af207 examples: don't use C99 %zu
this would require a PRIuS or similar macro for proper platform
compatibility (Visual Studio for instance would be variants of %lu)

Change-Id: I1af530c7c358c91b845acde1d8c12ef46c2ef746
2013-03-20 16:59:35 -07:00
5ccf1fe540 update ChangeLog
Change-Id: If845005a1d62730d23f7f138ffad4f45acdd2bfe
2013-03-20 15:02:23 -07:00
2560c243f3 update NEWS
Change-Id: Ic17003de4451ae50901b9a9fbffa15f2929561b8
2013-03-20 14:59:58 -07:00
f43bafc3e6 Merge changes Iecccb09c,If5ee9fd2,I3e181ce4 into 0.3.0
* changes:
  dwebp: warn when decoding animated webp's
  Decode: return more meaningful error for animation
  WebPBitstreamFeatures: add has_animation field
2013-03-20 14:56:29 -07:00
a788644f93 dwebp: warn when decoding animated webp's
the decode will fail; provide a bit more background info

Change-Id: Iecccb09cf0fa9f8c1c3e87636a55e1f251dee023
2013-03-20 13:59:38 -07:00
302efcdb41 Decode: return more meaningful error for animation
VP8_STATUS_NOT_ENOUGH_DATA -> VP8_STATUS_UNSUPPORTED_FEATURE

Change-Id: If5ee9fd2c99fc5502996d3c786848fd9cc118fe7
2013-03-20 13:59:22 -07:00
ad452735c3 WebPBitstreamFeatures: add has_animation field
Change-Id: I3e181ce463b0e4833bfd29f8052b21ebe0bca977
2013-03-20 13:49:56 -07:00
783dfa4995 disable FRGM decoding for good in libwebpmux
Change-Id: I2f24d100f93488f6b0bf9ccc5818f9177d73948b
2013-03-20 13:31:14 -07:00
4b956be095 Update ChangeLog
Change-Id: I5f74413ec584442aa824238ccc390a53f9fd8638
2013-03-19 18:12:49 -07:00
ad8b86d707 update NEWS
Change-Id: I72598ecd3e7e6f41f8554c645cf25cd21304fe61
2013-03-19 17:36:38 -07:00
3e084f63f5 Merge "demux cosmetics: comments/rename internal function" into 0.3.0 2013-03-19 17:09:07 -07:00
d3f8c621b5 Merge "move WebPFeatureFlags declaration" into 0.3.0 2013-03-19 17:08:31 -07:00
7386fe5047 Merge "libwebp{demux,mux}: install mux_types.h" into 0.3.0 2013-03-19 17:07:32 -07:00
d6cd4e9056 Merge "bump decode abi" into 0.3.0 2013-03-19 16:52:06 -07:00
17f8da5c51 bump decode abi
treating as a patch number in this case to disambiguate releases.

Change-Id: Ica1379c66473a961f2dcd5f3282281b8bf1bc276
2013-03-19 16:48:56 -07:00
97684ae269 Merge "add doc precision about WebPDemuxPartial()" into 0.3.0 2013-03-19 16:44:26 -07:00
f933fd2a27 move WebPFeatureFlags declaration
from private format_constants.h to public mux_types.h
also do the reverse for MKFOURCC()

Change-Id: I3aa86b007e9dbfed37a170989164ac3a77de2bd5
2013-03-19 16:10:41 -07:00
289bc47b65 libwebp{demux,mux}: install mux_types.h
required by demux.h and mux.h

Change-Id: Ib33cee1d95e575233204e70b62caf7a6366772c7
2013-03-19 14:54:04 -07:00
224e8d4630 add doc precision about WebPDemuxPartial()
it wasn't clear the data can be incomplete

Change-Id: I1482379aaea31e08a65c90f15e32edec2472e17e
2013-03-19 14:25:59 -07:00
4c18e80cf7 demux cosmetics: comments/rename internal function
ParseFrame -> ParseAnimationFrame

Change-Id: I27538927d16285e0793be5be78b0f15f4155dd83
2013-03-19 13:55:29 -07:00
7cfd1bf1fc update AUTHORS
Change-Id: I8d90f49439c04f86e8570ecca25e18339cb46917
2013-03-19 00:26:05 -07:00
401f7b856f Merge "speed-up lossless (~3%) with ad-hoc histogram cost evaluation" into 0.3.0 2013-03-18 17:48:59 -07:00
1fc8ffca35 Merge "makefile.unix: dist related changes" into 0.3.0 2013-03-18 16:53:46 -07:00
8a89c6ed28 Merge changes I466c377f,Ib761ebd3,I694857fc into 0.3.0
* changes:
  gif2webp: only write error messages to stderr
  gif2webp: fix crash on open failure with libgif5
  gif2webp: silence a unused param warning
2013-03-18 16:52:28 -07:00
f4ffb2d59a speed-up lossless (~3%) with ad-hoc histogram cost evaluation
* merge cost calculation functions (BitsEntropy() and HuffmanCost())
* have HistogramAdd() specialized into separate functions
* use threshold to bail-out early
* revamp code a bit

* also: save memory by freeing free(histogram_image)

Change-Id: I8ee5d2cfa1462d5d6ea6361f5c89925a3720ef55
2013-03-18 22:34:32 +01:00
723847d5d7 gif2webp: only write error messages to stderr
also output something if -o is not given, but the process succeeded

Change-Id: I466c377f0cbf8c9f45bb1839191b04dada9c5f0f
2013-03-18 11:13:35 -07:00
701b9e2af4 makefile.unix: dist related changes
* make the 'all' target really build everything (default is still the
    core examples).
  * add demux/mux.h to HDRS_INSTALLED, install the corresponding libs
    too
  * install vwebp, webpmux, gif2webp and related manpages

Change-Id: Ib6036f2a1a05e40f106914c4bdbe9e3ad7336464
2013-03-18 11:10:02 -07:00
bb85b43727 Merge "update NEWS" into 0.3.0 2013-03-17 23:39:21 -07:00
59423a2486 gif2webp: fix crash on open failure with libgif5
output the current gif_error and use it instead of the NULL context to
retrieve an error message.

Change-Id: Ib761ebd36b3ddd6288375de46e671022d2381083
2013-03-17 18:06:39 -07:00
9acb17dea4 gif2webp: silence a unused param warning
Change-Id: I694857fc6adb011f19d14780de4f8c71e2719707
2013-03-17 17:04:54 -07:00
7d9fdc2389 Merge "README updates" into 0.3.0 2013-03-17 02:40:44 -07:00
5621934e82 Merge "build: fix install race on shared headers" into 0.3.0 2013-03-17 02:38:16 -07:00
70809d89bb Merge "bump version to 0.3.0" into 0.3.0 2013-03-17 02:32:37 -07:00
d851cd1d85 demux: make the parse a bit more strict
* VP8L shouldn't have an alpha chunk
 * expect an animation to only contain frames, not a mix of image chunks
 * enforce ANIM/ANMF order
 * expect a full frame in a complete file

Change-Id: I953a8b6058f9bc00f1d042635548f158abdf6fce
2013-03-16 16:37:31 -07:00
28bb4107b1 update NEWS
Change-Id: Icb277027ee6209527d82978ebcec03391940aac2
2013-03-16 15:02:31 -07:00
cef9388283 bump version to 0.3.0
libwebp{,decoder} - 0.3.0
libwebp libtool - 4.2.0 (compatible release)
libwebpdecoder libtool - 0.0.0 (new release)

mux/demux - 0.1.0
libtool - 0.0.0 (new release)

Change-Id: Ied6efa390b2f97f1f41fc8349a365613c639d6cc
2013-03-16 14:08:14 -07:00
9048494df6 build: fix install race on shared headers
subdirectories with more than one target can have the install targets
run in parallel with make -jN. group the shared headers in one place to
produce a common install target.

Change-Id: I1f3aa338a8ee6d681de1e5d0b2c6244d2c3d5451
2013-03-16 13:29:49 -07:00
1e67e8ef9e README updates
* build related notes
  * merge vwebp descriptions
  * miscellaneous cosmetics

Change-Id: Ic4e580127bd2c4dff8e5a81ccb10b15a3568f8b1
2013-03-16 12:35:49 -07:00
42b611a491 Merge "configure: drop experimental from mux/demux" into 0.3.0 2013-03-16 12:05:30 -07:00
096a8e321d Merge "vwebp: add color profile support" into 0.3.0 2013-03-16 11:58:19 -07:00
ddfee5dce5 vwebp: add color profile support
uses qcms from Mozilla / Chromium:

http://hg.mozilla.org/mozilla-central/file/0e7639e3bdfb/gfx/qcms
http://src.chromium.org/viewvc/chrome/trunk/src/third_party/qcms

Change-Id: I674e16adb6ca085719816e984acbf00721b28fb0
2013-03-16 11:55:00 -07:00
0d6927d3cd Merge "Mark fragment options as experimental in webpmux" into 0.3.0 2013-03-16 10:45:52 -07:00
5dbd403029 Mark fragment options as experimental in webpmux
This is to disallow any accidental creation/parsing of fragmented images
by users.

Change-Id: I970a4bd5ec5a522867b24a0c9efb45164ae67047
2013-03-16 04:07:19 -07:00
a0a6648cc2 configure: drop experimental from mux/demux
--enable-libwebpdemux
--enable-libwebpmux

These are going stable with any remaining experimental features under
--enable-experimental

Change-Id: I8da0736438b2a58a2ea58b37b2630911ce300632
2013-03-15 20:55:54 -07:00
ee65bad8f2 Merge "add support for BITS > 32" into 0.3.0 2013-03-15 19:00:14 -07:00
744930dbe2 add support for BITS > 32
on x86_64 desktop, it's a little faster to use BITS=56
on MacOS (/llvm) it's _much_ faster (~10%)

Change-Id: I47c66ab7488341d8d1696d9301954b86b241b36d
2013-03-15 18:37:08 -07:00
7dd288f098 cwebp: fix build
METADATA_ICCP was renamed to METADATA_ICC in
  d8dc72a examples: normalize icc related program arguments
but was merged without rebasing after
  0bc4268 cwebp: output metadata statistics

Change-Id: Ie317208488cc851d5d21300591c91cebf5abd4a7
2013-03-15 16:42:58 -07:00
19a8dd0154 Merge "Makefile.vc: add vwebp.exe target" into 0.3.0 2013-03-15 16:38:40 -07:00
50eeddad3d Merge "examples: normalize icc related program arguments" into 0.3.0 2013-03-15 16:37:30 -07:00
757f637f33 Merge "Makefile.vc: add libwebpdecoder target" into 0.3.0 2013-03-15 16:33:37 -07:00
b65c4b7cbc Makefile.vc: add libwebpdecoder target
Change-Id: I43e5974dd4ec7280ee49d3dd258db227db757064
2013-03-15 16:32:58 -07:00
f8db7b4a05 Merge "vwebp: replace doubles w/floats where appropriate" into 0.3.0 2013-03-15 15:07:09 -07:00
d99aa56fbf Makefile.vc: add vwebp.exe target
Change-Id: I4de63628fef66fe2b1000cbc62c7db28f68c2cb8
2013-03-15 12:18:25 -07:00
013023e771 vwebp: replace doubles w/floats where appropriate
Change-Id: Ief1ef5213a5f357004922989e6e5d97ef3561a23
2013-03-15 12:17:45 -07:00
9b3db89473 README.mux: add version reference
Change-Id: Ic37de8303c4e04ccb7b4964844a1094cf8c737a4
2013-03-14 19:38:02 -07:00
7b6a26cff9 Merge "cwebp: output metadata statistics" into 0.3.0 2013-03-14 19:09:58 -07:00
d8dc72a039 examples: normalize icc related program arguments
use 'icc' rather than 'iccp'.

Change-Id: I9667f286bfa1cfeb0ac49148ba341d268b051b98
2013-03-14 19:05:22 -07:00
7bfc9056ad Merge "make alpha unfilter work in-place" into 0.3.0 2013-03-14 18:48:45 -07:00
0037b2d280 Merge "add LUT-free reference code for YUV->RGB conversion." into 0.3.0 2013-03-14 18:44:29 -07:00
166bf744b9 Merge "demux: disable fragment parsing" into 0.3.0 2013-03-14 18:39:06 -07:00
126974b45b add LUT-free reference code for YUV->RGB conversion.
Reported to eventually be 4% on ARM
(see https://code.google.com/p/webp/issues/detail?id=134 for details)
We might activate it selectively later...

Output values is not bitwise the same as the LUT-based
version, but difference is only +/-1 at max.

Change-Id: I1cc790ff4459885ed2ae2e72f31c5f3740095f07
2013-03-15 01:37:55 +01:00
0aef3ebdea make alpha unfilter work in-place
* remove a malloc
* remove the unused 'bpp' argument from filter/unfilter functions

Change-Id: I28d78baaaddc20f1d5a3bb2bd0b4e96a12a920d8
2013-03-15 01:36:38 +01:00
14ef5005a2 Merge "Remove 'status: experimental' from container spec" into 0.3.0 2013-03-14 00:04:58 -07:00
d40c98e172 Merge "webpmux binary: tiny style fix" into 0.3.0 2013-03-14 00:02:58 -07:00
0bc42689e4 cwebp: output metadata statistics
Change-Id: Ida33555bab3c9330e82158863c355e51f90d0a76
2013-03-13 22:57:54 -07:00
bc03980336 Merge "autoconf: normalize experimental define" into 0.3.0 2013-03-13 22:24:33 -07:00
d1e21b13b7 Remove 'status: experimental' from container spec
For features that are to be released in v0.3.0.

Change-Id: Ib8961f8cde0474aeaad5796bd0821db812edffcd
2013-03-13 18:16:30 -07:00
7681bb961d webpmux binary: tiny style fix
Change-Id: I195929d79940cd3d060977ef7feee9cd13f7d041
2013-03-13 18:10:56 -07:00
a3dd3d0f9e avoid installing example_util.h
older versions of automake (1.9) it seems would install the headers
regardless of the fact that the library was marked noinst_

this change follows some of the header guidance found here:
http://www.gnu.org/software/automake/manual/automake.html#Headers

Change-Id: I80acc00935097ebf36004e9871574fb9ef09aabf
2013-03-13 15:48:34 -07:00
252320e287 demux: disable fragment parsing
put this feature under WEBP_EXPERIMENTAL_FEATURES

Change-Id: I6405c5e6bed3ad1196aa1d111c83cca4c70c4c41
2013-03-13 13:54:53 -07:00
537bde05cc autoconf: normalize experimental define
EXPERIMENTAL -> WEBP_EXPERIMENTAL_FEATURES
the former is not used in the source; this adds
WEBP_EXPERIMENTAL_FEATURES to config.h

Change-Id: I4822bd3be1ea631e96629ae249dc778cdb5d8bb6
2013-03-13 13:53:02 -07:00
5e338e0b9a Merge changes I33e8a613,I8e8a7b44 into 0.3.0
* changes:
  automake: add reference to libwebp for mux/demux
  libwebp{,decoder}.pc: add pthread flags
2013-03-13 13:17:24 -07:00
d9d0ea1bf9 Merge changes If21e3ec7,I991fc30b into 0.3.0
* changes:
  add libwebpmux.pc
  add libwebpdemux.pc
2013-03-13 12:53:32 -07:00
627f5ca66b automake: add reference to libwebp for mux/demux
this allows DLLs to be built under mingw and sets up a more obvious
dependency in the shared objects

Change-Id: I33e8a6132a16ca49563492438a1b3b74be9ed6a1
2013-03-13 12:29:37 -07:00
eef73d07a3 don't consolidate proba stats too often
adds a minimum count before FinalizeToken() is called for update.

Change-Id: I445be6a3e347620583d87c33067cefa656a25039
2013-03-13 13:50:08 +01:00
05ec4cc2d3 libwebp{,decoder}.pc: add pthread flags
expands to e.g., -lpthread/-pthread, etc. if --enable-threading is used
and additional libs/flags are required

Change-Id: I8e8a7b44450bee32ddc58097e1e309d972b1092a
2013-03-12 23:02:12 -07:00
1bfcf5bf42 add libwebpmux.pc
Change-Id: If21e3ec73f2eb451c6042d1aecda8d03259f601f
2013-03-12 22:58:37 -07:00
26ca843d71 add libwebpdemux.pc
Change-Id: I991fc30b5287016066fae1ba11ec842c88994c41
2013-03-12 22:58:37 -07:00
69e2590642 Merge "Tune Lossless compression for lower qualities." 2013-03-12 22:08:29 -07:00
0478b5d214 Tune Lossless compression for lower qualities.
This is required for WebP lossy+Alpha images, where Alpha channel is taking
60-70% of the compression (CPU) cycles.

Also evaluated on 1000 PNG corpus and overall compression speed
is 15-40% better for lossy (PNG+Alpha) compression.
The pure lossless compression numbers are almost same (or little
better) with this change.

Change-Id: I9e5ae7372ed6227a9a5b64cd9cff84c747195a57
2013-03-12 14:17:28 -07:00
39f7586f31 add a mention of parallel alpha encoding in the NEWS
Change-Id: I3ef53fab45069b874faaa853c6f6c188e999ffda
2013-03-11 17:14:25 -07:00
5a21d96741 Merge "1.5x-2x faster encoding for method 3 and up" 2013-03-11 17:14:18 -07:00
9bfbdd144f 1.5x-2x faster encoding for method 3 and up
using token-buffer (that is: slightly more memory. O(output_size))

This change is ON by default. To return to previous behaviour, use
'cwebp -low_memory' or set config.low_memory to true.

Side-effect of this new mode: it forces 1 partition only (which was
default anyway), and makes some statistics about the bitstream
no longer available. cwebp will no longer report 'intra4-coeffs', etc.

This mode also doesn't work (yet) with multi-pass, and -low_memory
is currently forced for multi-pass.

also: reversed the flag: USE_TOKEN_BUFFER -> DISABLE_TOKEN_BUFFER
also: fixed the kAverageBytesPerMB estimate

Change-Id: I4ea80382038d6df4309663e0cb7bd88d9bca9cf1
2013-03-11 17:01:33 -07:00
27dc741bda Correct frame options order in README.mux
Change-Id: Ia65f5f0f0d0fc50c3b360cd010112ae5ecece91a
2013-03-11 13:58:34 -07:00
be2fd1735a Mux: fix a scenario with bad ANMF/FRGM size
When a ANMF/FRGM chunk size (read from file) is smaller than ANMF/FRGM header
size (which is constant and implicit), the parser should report an error.

Change-Id: I91d71889937f5133a97f1e83d5254cb2d7f37028
2013-03-08 17:34:20 -08:00
19eb012c55 Merge "Demux: Add option to get frame count using GetI()" 2013-03-08 16:11:37 -08:00
7368b8cbb2 Merge "WebPGetFeatures() out of if condition for clarity." 2013-03-08 16:07:47 -08:00
f604c9a4a2 Merge "fix windows build" 2013-03-08 15:51:07 -08:00
153f94e8b5 fix windows build
broken since:
ad25032 Merge "multi-threaded alpha encoding for lossy"

this produced an error due to an empty VP8TBuffer struct.

Change-Id: I640809d07d20092c1d660e2b59b58a62a12e4371
2013-03-08 15:50:04 -08:00
847b49243e Merge "vwebp: use magenta for 'i'nfo display" 2013-03-08 05:17:57 -08:00
25ea46bdee Merge "vwebp: add keyboard shortcuts to help output" 2013-03-08 05:15:17 -08:00
bea7ccaffd vwebp: use magenta for 'i'nfo display
replaces black

Change-Id: I8ca52c187c7b4b890378dec2a526e51c7819f7e1
2013-03-07 19:42:41 -08:00
8fab161a3f webpmux: correct -frame param order in help output
params were reordered to +duration+x offset+...

Change-Id: I99e8a70c8a645552238294ab82c3f7ffe01e70bd
2013-03-07 19:15:37 -08:00
03cc23d6f9 vwebp: add keyboard shortcuts to help output
Change-Id: Ida94b3f99115ddeb6b6eec1411918f99e964ed91
2013-03-07 19:13:00 -08:00
068eba8d58 Demux: Add option to get frame count using GetI()
Also tweak the code for single image and fragmented image cases, so that
dmux->num_frames_ is always correct.

Change-Id: I31e6904222e4d96a54a0d8c8aa73d43b7a9094e7
2013-03-06 13:14:05 -08:00
988b8f56b3 WebPGetFeatures() out of if condition for clarity.
Also, some comment tweaks in decode.h

Change-Id: I9d4e80f2ffdc51d35bd3215486e26448bddd143b
2013-03-05 18:05:12 -08:00
6933d91057 Merge "gif2webp: Be lenient about background color index." 2013-03-05 17:04:16 -08:00
4d0f7c5543 Merge "WebPGetFeatures() behavior change:" 2013-03-05 17:03:20 -08:00
fdeeb01dc6 gif2webp: Be lenient about background color index.
Change-Id: I4440cffff4e8cefb3b0327a9b4925e05a7bbfc50
2013-03-05 13:41:55 -08:00
ad2503203a Merge "multi-threaded alpha encoding for lossy" 2013-03-01 16:00:10 -08:00
4e32d3e1e7 Merge "fix compilation of token.c" 2013-03-01 01:07:56 -08:00
f817930a55 multi-threaded alpha encoding for lossy
new option: 'cwebp -mt ...'
new config flag: config.thread_level
(allowed thread_level are 0 or 1 for now. Maybe more later...)
If -mt is activated (and WEBP_USE_THREAD is used for compile), the alpha-compression
will be done in parallel to RGB coding for lossy. Can save quite a bit of latency...
Has no effect for lossless encoding.

Change-Id: I769d0bf90e7380cf99344ad62cd77277f4df5a46
2013-03-01 10:04:08 +01:00
88050351f4 fix compilation of token.c
(TOKEN_BUFFER still disabled)
also: made VP8TBufferClear() always visible

Change-Id: Iff353fe70b2f3c5b0ab4ef7f143e1d65b0ab2b0d
2013-03-01 09:58:14 +01:00
fc816219e1 code using the actual values for num_parts_, not the ones from config
Change-Id: Icb961c66fe62cb703a12c5ff8a9aa4fc884bac1c
2013-03-01 09:48:33 +01:00
72655350ea Merge "move the config check from .c to .h" 2013-02-28 12:25:53 -08:00
dd9e76f7b4 move the config check from .c to .h
+ minor doc cosmetics

Change-Id: I351ce63f4463fd1c1546f58697440ad01eac860c
2013-02-28 21:23:39 +01:00
956b217a8b WebPGetFeatures() behavior change:
It should return VP8_STATUS_NOT_ENOUGH_DATA when it doesn't have enough
data.

Change-Id: I5acff04f9ba51dab150dc6d137c5ad00ea61c64a
2013-02-27 15:27:43 -08:00
df02e4ce93 WebPDemuxGetI behavior change:
It now returns ALPHA_FLAG for lossless images with alpha, that don't
have a VP8X chunk.

This is consistent with similar methods WebPMuxGetFeatures() and
WebPGetFeatures().

Change-Id: Ia3a4ca8f3e0f102f478bd33e0727ca5be98593df
2013-02-27 11:49:26 -08:00
633c004db1 Merge "rebalance method tools (-m) for methods [0..4]" 2013-02-27 10:20:27 -08:00
58ca6f65b7 rebalance method tools (-m) for methods [0..4]
(methods 5 and 6 are still untouched).

Methods #0 and #1 got much faster
Method #2 gets vastly improved in quality
Method #3 is noticeably faster for little lower quality
Method #4 (default) is 10-20% faster for comparable quality

+ update the internal doc about the methods' tools.

Example of speed difference:

Time to encode picture:
Method | Before | After
-m 0   | 1.272s | 0.517s
-m 1   | 1.295s | 0.623s
-m 2   | 2.217s | 0.834s
-m 3   | 2.816s | 2.243s
-m 4   | 3.235s | 3.014s
-m 5   | 3.668s | 3.654s
-m 6   | 8.296s | 8.235s

Change-Id: Ic41fda5de65066b3a6586cb8ae1ebb0206d47fe0
2013-02-27 02:19:20 -08:00
7648c3ccb8 Merge "describe rd-opt levels introduce VP8RDLevel enum" 2013-02-27 01:45:14 -08:00
67fb1003bf Merge "autoconf: enable silent-rules by default" 2013-02-27 01:43:42 -08:00
a5042a3240 GetVersion() methods for mux and demux
Also use the same in example binaries.

Change-Id: Id4bb4c4231a6b8fe9ed4370a6f46567c52a04a17
2013-02-26 14:22:06 -08:00
5189957e07 describe rd-opt levels introduce VP8RDLevel enum
makes things somehow clearer compared to using magic constants

Change-Id: I9115cee71252511f722806427ee8a97f1a1cd95f
2013-02-26 02:20:59 -08:00
4e094ace8c autoconf: enable silent-rules by default
simplify macro check: use m4_ifdef rather than
m4_define_default/AM_SILENT_RULES

Change-Id: I1746aaa6b22bd6a8c4804e742e1071165094b150
2013-02-25 16:11:14 -08:00
b7eaa85d6a inline VP8LFastLog2() and VP8LFastSLog2 for small values
larger values are still dealt with in the .cc

~5% faster encoding
Output size is slightly different (variably), because of
different floating-point calculation ordering.

Change-Id: I6ede18b09c753997cf78aa1199a807d9ddb5d4b4
2013-02-25 22:46:52 +01:00
5cf7792e40 split quant_levels.c into decoder and encoder version
-> split libraries further into decoder / encoder
-> add libwebpdecoder.a in Makefile.unix
-> make dwebp link against libwebpdecoder.a in Makefile.unix

also: in makefile.unix, pass EXTRA_FLAGS to LDFLAGS too
(otherwise, -m32 wouldn't work, e.g.)

Change-Id: Ief3da02a729dd86bbaf949ed048836716941657f
2013-02-24 21:40:39 +01:00
e5d3ffe275 Merge "Update code example in README.mux" 2013-02-23 00:52:48 -08:00
ac5a9156b1 Update code example in README.mux
As per changes in code example in demux.h

Change-Id: Idb63e854dc2668ba35517ed9622195a12b6942d7
2013-02-22 15:13:10 -08:00
38a91e990b Add example code snippet for demux API
Change-Id: I4e9f32d030dd7f184e1cedf5b37f6f640ba4845e
2013-02-22 14:16:48 -08:00
5f557f3c1b README.mux: add info about Demux API and vwebp
Also use a naming 'extended format' rather than 'container file' to be
consistent with the container specification.

Change-Id: I3b07f95e0244d3534fe17b03f60db22f61e17836
2013-02-21 16:56:48 -08:00
c0ba090335 backward_references: avoid signed integer overflow
signed integer overflow behavior is undefined, split PrefixEncode() to
two branches to avoid this.

Change-Id: I6e2761d0d77f0aaceafdc4e07232e089c22beb64
2013-02-20 13:35:00 -08:00
943386db4b disable SSE2 for now
(until proper run-time detection is ready)

Change-Id: I7b8eee52b23fce2f1612ad7d4ed603ffb02620a2
2013-02-20 08:20:47 +01:00
9479fb7d2d lossless encoding speedup
* add SSE2 variant for lossless
* speed-up TransformColor calls using specialized TransformColorBlue/Red
* Fuse the Shannon Entropy calls to compute it for X and X+Y simultaneously.

This latter changes the output size a little bit.

Change-Id: Ie5df94da78bf51a58da859c9099b56340da9ec89
2013-02-20 08:13:12 +01:00
ec2030a8a2 merge two lines together
Change-Id: I6f7935cfdac52d793ba08b1c050160d3417b8eb0
2013-02-19 23:01:10 -08:00
b67956c037 Merge "Remove ReadOneBit() and ReadSymbolUnsafe()" 2013-02-19 15:16:21 -08:00
1667bded67 Remove ReadOneBit() and ReadSymbolUnsafe()
Simplify and re-organize the VP8L bit-reader functions
(e.g.: the 40-bit look-ahead code was helping much)

Speed-up with LBITS=64, on arm7-a:

=> before:
./dwebp_justify_24_neon -v bryce_ll.webp
Time to decode picture: 11.393s
File bryce_ll.webp can be decoded (dimensions: 11158 x 2156).
...

=> after (LBITS=64):	Time to decode picture: 9.953s

making the VP8L bit-reader in 32 bit mode is going to be
harder (because we need to be able to read two symbols
at a time, each with max length 15 bits)

Change-Id: I89746fb103b87b5e2fd40a3208a6fbc584b88297
2013-02-20 00:13:23 +01:00
3151669b15 wicdec + dwebp cosmetics: normalize formatting
- drop mixed use of Hungarian notation
- fix some line continuations

Change-Id: I9e6ec5cd6c746eb78048cf3532586fd93cef4ddb
2013-02-15 20:39:45 -08:00
92668da6f2 change default filtering parameters:
* type is now 'strong'
  * strength is now '60'

These help with gradients and blocking

Change-Id: Ie1c8265c557306ef5e9ccefacf43e10946e55370
2013-02-15 01:09:32 -08:00
b7490f8553 introduce WEBP_REFERENCE_IMPLEMENTATION compile option
This flag will make the code use no uint64, no asm, and no fancy
trick, but instead aim at being as simple and straightforward as
possible.
Main use is to help emscripten generate proper JS code.
More code needs to be simplified later.

Also: tune the BITS values to be 24 and make use of WEBP_RIGHT_JUSTIFY
Here are the typical timing for decoding a large image:

        ARM7-a:
        dwebp_justify_32_neon Time to decode picture: 3.280s
        dwebp_justify_24_neon Time to decode picture: 2.640s
        dwebp_justify_16_neon Time to decode picture: 2.723s
        dwebp_justify_8_neon Time to decode picture: 2.802s
        dwebp_justify_32 Time to decode picture: 4.264s
        dwebp_justify_24 Time to decode picture: 3.696s
        dwebp_justify_16 Time to decode picture: 3.779s
        dwebp_justify_8 Time to decode picture: 3.834s
        dwebp_32_neon Time to decode picture: 4.010s
        dwebp_24_neon Time to decode picture: 2.725s
        dwebp_16_neon Time to decode picture: 2.852s
        dwebp_8_neon Time to decode picture: 2.778s
        dwebp_32 Time to decode picture: 4.587s
        dwebp_24 Time to decode picture: 3.800s
        dwebp_16 Time to decode picture: 3.902s
        dwebp_8 Time to decode picture: 3.815s
        REFERENCE (HEAD) Time to decode picture: 3.818s

        x86_64:
        dwebp_justify_32 Time to decode picture: 0.473s
        dwebp_justify_24 Time to decode picture: 0.434s
        dwebp_justify_16 Time to decode picture: 0.450s
        dwebp_justify_8 Time to decode picture: 0.467s
        dwebp_32 Time to decode picture: 0.474s
        dwebp_24 Time to decode picture: 0.468s
        dwebp_16 Time to decode picture: 0.468s
        dwebp_8 Time to decode picture: 0.481s
        REFERENCE (HEAD) Time to decode picture: 0.436s

        i386:
        dwebp_justify_32 Time to decode picture: 0.723s
        dwebp_justify_24 Time to decode picture: 0.618s
        dwebp_justify_16 Time to decode picture: 0.626s
        dwebp_justify_8 Time to decode picture: 0.651s
        dwebp_32 Time to decode picture: 0.744s
        dwebp_24 Time to decode picture: 0.627s
        dwebp_16 Time to decode picture: 0.642s
        dwebp_8 Time to decode picture: 0.642s

Change-Id: Ie56c7235733a24f94fbfc2e4351aae36ec39c225
2013-02-14 15:46:12 +01:00
3383885799 faster decoding (3%-6%)
. revamped the boolean decoder to use less shifts
. added some description and ASCII art as explanations too.
. clarified the types further (bit_t, lbit_t, range_t, etc.)
. changed the negative field 'missing_' into positive 'bits_'

Some stats, decoding some randomly encoded WebP files:

with USE_RIGHT_JUSTIFY:
  BITS=32 => 133 files, 50 loops => 7.3s (1.097 ms/file/iterations)
  BITS=24 => 133 files, 50 loops => 7.3s (1.097 ms/file/iterations)
  BITS=16 => 133 files, 50 loops => 7.4s (1.120 ms/file/iterations)
  BITS=8 => 133 files, 50 loops => 7.5s (1.128 ms/file/iterations)

without USE_RIGHT_JUSTIFY:
  BITS=32 => 133 files, 50 loops => 7.5s (1.131 ms/file/iterations)
  BITS=24 => 133 files, 50 loops => 7.6s (1.142 ms/file/iterations)
  BITS=16 => 133 files, 50 loops => 7.6s (1.143 ms/file/iterations)
  BITS=8 => 133 files, 50 loops => 7.6s (1.149 ms/file/iterations)

Change-Id: I9277fb051676c05582e9c7ea3cb5a4b2a3ffb12e
2013-02-14 15:42:58 +01:00
5c3e381b2f Merge "add a -jpeg_like option" 2013-02-13 22:17:58 -08:00
c23110467e remove unused declaration of VP8Zigzag
Change-Id: I80bdf4b692dcdad1fc2b0cfffcaebb5fef5dde34
2013-02-12 07:14:21 -08:00
36152957af Merge "wicdec: add alpha support for paletted formats" 2013-02-06 23:33:24 -08:00
c9f1649012 wicdec: add alpha support for paletted formats
Fixes issue #141.

Change-Id: I5d8163329a9e363da9db9d70d25edeb29da32e9e
2013-02-06 23:29:32 -08:00
1262f81e37 Merge "wicdec: silence some warnings" 2013-02-06 23:21:26 -08:00
e7ea61eb75 wicdec: silence some warnings
-Wformat, -Wmissing-field-initializers and size type related

Change-Id: I92b1c7cc485bf59f94b5c0f8bb2137d87604f831
2013-02-06 23:16:50 -08:00
23c0f354a6 fix missing intptr_t->int cast for MSVC
Change-Id: I39acdfbe287ef7b7f615d59e0729aab161189bf9
2013-02-06 17:51:10 +01:00
e895059a05 add a -jpeg_like option
This option remaps internal parameters to better match
the expected compression curve of JPEG and produce output files
of similar size, but with better quality.

Change-Id: I96a1cbb480b1f6a0c6845a23c33dfd63f197b689
2013-02-06 14:19:16 +01:00
1f803f645d Merge "Tune alpha quality mapping to more reasonable values." 2013-02-05 10:50:28 -08:00
1267d498dc Tune alpha quality mapping to more reasonable values.
This results in a significant speedup  with minimal increase in file sizes.

Change-Id: I6ecefe33eee219fba4099810d04a916f7efbd292
2013-02-05 19:49:35 +01:00
043076e2ef Merge "speed-up lossless in BackwardTrace" 2013-02-05 10:46:06 -08:00
f3a44dcd83 remove one malloc from TraceBackwards()
Change-Id: I4f77c0240ca2ece86e8beab11d02c74277409921
2013-02-05 19:43:43 +01:00
0fc1a3a072 speed-up lossless in BackwardTrace
we special-case code=2 (with a later TODO to adapt this on quality)

Change-Id: I93d43f5b3f8f1ef9f211cce253bb4b415918ee57
2013-02-05 19:42:23 +01:00
7c732e59f4 cwebp: centralize WebPCleanupTransparentArea()
this can be safely called whether the picture has alpha or not

Change-Id: I0047fd4c110f1072f183f3d340682502bd6623d7
2013-02-04 15:44:26 -08:00
7381254e9a Merge "wicdec: add ICC profile extraction" 2013-02-04 15:43:39 -08:00
e83ff7decd wicdec: add ICC profile extraction
Change-Id: I4522cdd5a529f802f1eb566b6d94539612e0976b
2013-02-02 10:40:49 -08:00
146c6e3be8 Merge "cosmetics: pngdec: normalize default label location" 2013-02-02 00:18:37 -08:00
a8f549d799 Merge "manpages: italicize option parameters" 2013-02-02 00:18:05 -08:00
e118db83b1 Merge "encode.h: note the need to free() WebPMemoryWriter" 2013-02-02 00:12:59 -08:00
1dfee6dbea cosmetics: pngdec: normalize default label location
Change-Id: I25dd0e61898af3fcaff3d17cddedd3d39d4930aa
2013-02-01 20:37:05 -08:00
14c3820038 manpages: italicize option parameters
Change-Id: Id7e4edde2a1c91fe4fbf96ddc280a06132e9986a
2013-02-01 20:35:58 -08:00
7defbfadbe encode.h: note the need to free() WebPMemoryWriter
Change-Id: Iec873764e9f4c085c634498630b8c1ced3283984
2013-02-01 19:18:47 -08:00
88d382a042 cwebp: cleanup after memory_writer
always initialize the memory_writer so it can be unconditionally freed
on exit

Change-Id: I9226addb588309446ec94abadfdde201f23195d2
2013-02-01 19:17:26 -08:00
12d6cecfbd fix extra space in dwebp.1 man
Change-Id: Ifa3d91c73e0efeecb02365bc2168c830a01c759a
2013-01-30 04:50:03 -08:00
b01681a93f Fix for demuxer frame iteration:
Return error in WebPDemuxGetFrame() when static method GetFrame()
returns NULL.

Change-Id: Idbc54037047c3df75209ac67ff8bede3f83042be
2013-01-29 10:58:04 -08:00
56c12aa698 Demuxer creation fix:
If it's not a partial file and parser returns PARSE_NEED_MORE_DATA, then
consider it to be PARSE_ERROR.

Change-Id: Id652a345bd2a9f574970272dd0a00517de113215
2013-01-29 10:53:52 -08:00
66c810bc3c add a -yuv option to dwebp (very similar to -pgm)
It will decode to raw (flat) YUV format, similar to what
cwebp can take as input. Makes the PSNR/SSIM calculation easier.

Change-Id: Iebfaedfc0bedc70c169b24ae4aabc701488d0644
2013-01-28 23:22:14 +01:00
841a3ba5da Merge "Remove -Wshadow warnings." 2013-01-28 13:15:54 -08:00
8fd0252787 Merge "upsampling_neon.c: fix build" 2013-01-28 13:14:39 -08:00
6efed26865 Remove -Wshadow warnings.
Accidentally carried some bad habits from SSE code. Copy over fixes
from 0d19fbf

Change-Id: I763312c9d176c434ba41f95602bada1aeffebfb2
2013-01-28 12:29:12 -08:00
60904aa629 Merge "allow WebPINewRGB/YUVA to be passed a NULL output buffer." 2013-01-28 04:06:16 -08:00
b7adf37621 allow WebPINewRGB/YUVA to be passed a NULL output buffer.
If a NULL pre-allocated buffer is passed, a buffer will be automatically
allocated.

+ add some parameter checks.

reported in http://code.google.com/p/webp/issues/detail?id=139

Change-Id: I9e14ed97db30ee12e46b5e92aac7eeaaeb99bfd5
2013-01-28 00:07:32 -08:00
27f8f7420e upsampling_neon.c: fix build
store values to a temporary variable before calling functions that take
vector types.
removes non-standard constructs such as:
  (uint8x8x2_t){{ a, b }}
fixing:
  src/dsp/upsampling_neon.c:69:32: error: macro "vst2_u8" passed 3
arguments, but takes just 2

Change-Id: Ib4368e16e3a3efac18024f02be94e76243ade2dc
Fixes: https://code.google.com/p/webp/issues/detail?id=140
2013-01-25 19:42:50 -08:00
06b9cdf1e7 gitignore: add IOS related directories
iosbuild / WebP.framework courtesy of iosbuild.sh

Change-Id: I706fd5fada5fab2528e89d6b09fe93fa44486035
2013-01-25 18:25:28 -08:00
f112221e77 Merge "Fix more comments for iobuild.sh" 2013-01-25 17:52:23 -08:00
fe4d25ddad Fix more comments for iobuild.sh
Change-Id: If97af61a00c0f2dfbd09758c121a9ddd9536b6d1
2013-01-25 16:07:59 -08:00
1de3e25271 Merge "NEON optimised yuv to rgb conversion" 2013-01-25 15:51:40 -08:00
090b708a00 NEON optimised yuv to rgb conversion
- along the lines of the SSE chroma upsampling.
Total speedup is ~30%.

4% speed loss on YuvToRgbXX conversion using tables instead
of 14-bit fixed precision. TODO(later): investigate, and compare
to x86.

see http://code.google.com/p/webp/issues/detail?id=134

Change-Id: Idc2261037cd13b4553ca20ecc4c4007099c37009
2013-01-25 15:46:40 -08:00
daa06476e1 Merge "Add ios build script for building iOS library." 2013-01-25 15:26:09 -08:00
79fe39e2f2 Add ios build script for building iOS library.
This build script (iosbuild.sh) will build for following platforms:
iPhoneSimulator, iPhoneOS-V7 & iPhoneOS-V7s

Change-Id: Icbb69e00277a4164f848b8766089302e299506e0
2013-01-25 10:10:50 -08:00
126c035f3f remove some more -Wshadow warnings
Change-Id: Icaba088b9a74732137bd35d82854eed858ec88f8
2013-01-25 00:44:31 -08:00
522e9d6108 Merge "cwebp: enable '-metadata'" 2013-01-24 20:04:09 -08:00
76ec5fa1b6 cwebp: enable '-metadata'
This copies metadata selected by -metadata from the input to the output
if present.
Currently there is no WIC support for Windows builds.

Change-Id: I34fb2443729d80ffe3a6da0979d9f6fa9b3fe536
2013-01-24 19:52:50 -08:00
aeb91a9d49 Merge "cosmetics: break a few long lines" 2013-01-23 15:05:40 -08:00
be7c96b069 cosmetics: break a few long lines
Change-Id: I785763b974b4e7664ad8e9884251aa2d5274b456
2013-01-23 14:50:19 -08:00
cff8ddb61b Merge "add libwebpdecoder.pc" 2013-01-23 14:27:41 -08:00
93148ab867 Merge "libwebp.pc.in: detab" 2013-01-23 14:25:06 -08:00
6477f955b6 Merge "Makefile.vc: normalize path separator" 2013-01-23 14:21:36 -08:00
bed1ed7c28 add libwebpdecoder.pc
Change-Id: Ifc47549a9fe206fa174236664345d3ee064849f5
2013-01-23 13:57:08 -08:00
46168b2d00 libwebp.pc.in: detab
Change-Id: I60f38e9f6e1cdba29163240a394b5be0a14c4bca
2013-01-23 13:31:43 -08:00
a941a3463e Fixed few nits in the build files.
Fixed the nits from last change (Provide an option to build decoder
library).

Change-Id: I7d8675b8156dc63cf21ef64810722552e7fb59f6
2013-01-23 13:22:06 -08:00
dd7a49b21b Makefile.vc: normalize path separator
/ -> \

Change-Id: I691c03683650b8b97a365281e9384f4a3f3fe1ca
2013-01-23 12:46:18 -08:00
9161be863d Merge "cwebp: extract WIC decoding to its own module" 2013-01-23 12:44:22 -08:00
08e7c58ee1 Merge "Provide an option to build decoder library." 2013-01-23 11:54:24 -08:00
0aeba52852 Provide an option to build decoder library.
When the config option '--enable-libwebpdecoder' is specified, the
lean decoder library 'libwebpdecoder' will be created in addition to
libwebp. Also dwebp binary will be linked to libwebpdecoder, if this
config option is specified.

Change-Id: I9de3e149b59c9a8390fae2ba660941749640e54a
2013-01-23 11:43:36 -08:00
757ebcb1c1 catch malloc(0)/calloc(0) with an assert
Actually, it turns out we now should never call these functions
with a zero size, otherwise something is wrong in the logic.

Change-Id: Ie414fcbec95486c169190470a71f2cff0843782a
2013-01-23 20:09:28 +01:00
152ec3d2ee Merge "handle malloc(0) and calloc(0) uniformly on all platforms" 2013-01-23 04:41:36 -08:00
a452a5554a cwebp: extract WIC decoding to its own module
Change-Id: I8e3e20787f6c3cc0616bd33beb2a6ccdda1e04f7
2013-01-22 18:31:28 -08:00
2b252a53a8 Merge "Provide option to swap bytes for 16 bit colormodes" 2013-01-22 15:00:39 -08:00
94a48b4bc3 Provide option to swap bytes for 16 bit colormodes
Color modes: RGB_565 & RGBA_4444
Change-Id: I571b6832b9848e5c4109272978f68623ca373383
2013-01-22 14:51:20 -08:00
42f8f9346c handle malloc(0) and calloc(0) uniformly on all platforms
also change lossless encoder logic, which was relying on explicit
NULL return from WebPSafeMalloc(0)

renamed function to CheckSizeArgumentsOverflow() explicitly

addresses issue #138

Change-Id: Ibbd51cc0281e60e86dfd4c5496274399e4c0f7f3
2013-01-22 23:40:16 +01:00
8b2152c579 Merge "add an extra assert to check memory bounds" 2013-01-22 14:10:02 -08:00
0d19fbff51 remove some -Wshadow warnings
these are quite noisy, but it's not a big deal to remove
them.

Change-Id: I5deb08f10263feb77e2cc8a70be44ad4f725febd
2013-01-22 23:06:28 +01:00
cd22f655e8 add an extra assert to check memory bounds
-> will remove a static-analysis warning about unused value.
addresses issue #138

Change-Id: I8ba4bf71a41e32759da41907aab73108dd230bc4
2013-01-22 13:38:58 +01:00
8189feda50 Merge "Add details and reference about the YUV->RGB conversion" 2013-01-21 07:10:42 -08:00
1d2702b1da Merge "Formatting fixes in lossless bitstream spec" 2013-01-18 14:41:56 -08:00
8425aaee8f Formatting fixes in lossless bitstream spec
- Escape brackets for which kramdown was generating a warning.
Note: This only changes this source file; output HTML would look exactly
the same.
- Also write '5' in words ('five').

Change-Id: I472a03c090a12eb7520719ea463469b36a2736b9
2013-01-18 14:35:47 -08:00
a556cb1ab4 Add details and reference about the YUV->RGB conversion
Originated from the discussion at
   http://code.google.com/p/webp/issues/detail?id=134

Change-Id: I24384e2d2f5cf262d8632fc98303cba5e2d27224
2013-01-18 23:26:55 +01:00
d8f21e0bab add link to SSIM description on Wikipedia
+ a brief description of LSIM

Change-Id: I4344f3e3b28d8bc4109b729dec9000e9c8fcbdbb
2013-01-18 13:13:56 +01:00
18e9167ea6 Merge "WebP-lossless spec clarifications:" 2013-01-18 00:15:01 -08:00
98e25b9b81 Merge "cwebp: add -metadata option" 2013-01-18 00:13:40 -08:00
f01c2a538c WebP-lossless spec clarifications:
- Clarify the BNF using 'Huffman code groups' and 'Huffman code group'.
- Introduce same terminology in 'Interpretation of meta Huffman codes'.
- Make explicit mention of what is the number of Huffman code groups,
  number of Huffman codes and the relation between the two.

Change-Id: I07aa9b62c1d464cd25dc02ac1a68d338b575bdc2
2013-01-17 15:19:09 -08:00
f4a97970de Merge "Disto4x4 and Disto16x16 in NEON" 2013-01-17 11:07:20 -08:00
47b7b0ba47 Disto4x4 and Disto16x16 in NEON
Change-Id: Ic6d9dbbc97b5025ce359332c33ae306d5d8925a5
2013-01-16 16:57:33 -08:00
7eaee9f1ac cwebp: add -metadata option
currently has no effect except to disable metadata extraction from the
input when the value is 'none'.

Change-Id: Ic50d4c9d634cc1f6b72ae4e130e99736c85a6477
2013-01-14 17:44:54 -08:00
36c52c2cf1 tiffdec: use toff_t for exif ifd offset
versions < 4.0.0 used uint32 interchangeably, but with 4.0.0 toff_t
became 64-bit and TIFFTAG_EXIFIFD began returning it rather than
TIFF_LONG/uint32.

Change-Id: I42492bd24613a884c7496e7bfc0c5d892758bce9
2013-01-10 21:33:24 -08:00
7c8111e4a8 Merge "cwebp/tiffdec: add TIFF metadata extraction" 2013-01-10 15:52:05 -08:00
e6409adc2e Remove redundant include from dsp/lossless code.
Change-Id: Ie8a497a486653f907c2a27f4027640a3308c6cc8
2013-01-10 15:09:19 -08:00
1ab5b3a7bd Merge "configure: fix --with-gifincludedir" 2013-01-08 13:54:23 -08:00
03c749ebb8 configure: fix --with-gifincludedir
GIF_INCLUDES were not being used by examples/Makefile.am

Change-Id: I981ad473f6efe24f095e2b9cc8b133d6ae3658b6
2013-01-08 12:39:43 -08:00
8b650635df multiple libgif versions support for gif2webp
Make it work for libgif v5.0+, for which a couple of APIs have changed.

Change-Id: I6dd49bb5bf1b60f96f3a164d58ef2ef19281c96b
2013-01-08 11:52:24 -08:00
476e293fe8 gif2webp: Use DGifOpenFileName()
This removes some unnecessary code.

Change-Id: Ic87baa402362f43b30d7c4a75be2f58e8f13f4a1
2013-01-08 11:07:13 -08:00
b50f277bc7 tiffdec: correct format string
the expression using dircount will be promoted to int when tdir_t is an
unsigned short.
quiets:
warning: format specifies type 'unsigned short' but the argument has
      type 'int' [-Wformat]

Change-Id: If2e8c27454826556178b0a972aaed272d5fbfa07
2013-01-07 19:06:20 -08:00
2b9048e324 Merge "tiffdec: check error returns for width/height" 2012-12-22 06:29:23 -08:00
a1b5a9a3e0 Merge "cwebp/tiff: use the first image directory" 2012-12-21 08:37:11 -08:00
079423f5c5 tiffdec: check error returns for width/height
Change-Id: I1399a7b75aea54044f30c6a53ac11843c1e75877
2012-12-20 22:33:52 -08:00
d62824af42 Merge "cwebp/jpegdec: add JPEG metadata extraction" 2012-12-20 22:25:46 -08:00
03afaca4a2 Merge "cwebp: add PNG metadata extraction" 2012-12-20 22:20:12 -08:00
2c724968d2 cwebp/jpegdec: add JPEG metadata extraction
the values of EXIF/XMP/ICC are unused and Extended XMP for payloads >
64k is unsupported.

Change-Id: If721aa2009335ce090148b7ecd7ea8459f9b942d
2012-12-20 18:35:38 -08:00
dba64d91bb cwebp: add PNG metadata extraction
the values of XMP/EXIF/ICC are currently unused.

Change-Id: I39d78b9a179f2d36c9c8ea12776bfdf6d8d18663
2012-12-20 18:32:09 -08:00
1f075f89b0 Lossless spec corrections/rewording/clarifications
- Correct BNF for 'predictor-image' and 'color image'
- Correct some references to 'br', 'VP8LReadBits' and 'ReadStream'
- Correct value ranges in distance mapping table.
- Rewrite section 4 (some rearrangement, rewording, adding context etc).
- Similarly, rewrite section 5.

Change-Id: If487490c2553b3f7982b9fcca68d98bab5017e3c
2012-12-20 10:44:42 -08:00
2914ecfd56 cwebp/tiffdec: add TIFF metadata extraction
currently the values of XMP/ICC are unused and EXIF is ignored.

Change-Id: I1d8b73bde4db2768f117158f986aadbaaec45804
2012-12-19 18:26:05 -08:00
d82a3e3391 More corrections/clarifications in lossless spec:
- Rectify a few BNF descriptions
- Corrections in "Decoding Flow of Image Data" section:
  1. The sequence in case of "S < 256" should be green, red, blue, alpha.
  2. In case of "S >= 256 + 24", the index should be "S - (256 + 24)".
- Provide more description to clarify "Decoding Flow of Image Data" section.
- Some cosmetics: use '1's instead of '1, 2, 3...' sequence, as kramdown takes
  care of sequencing.

Change-Id: I2b76caf72f67aae813522dc1a4115f8ec8ea6db7
2012-12-17 11:40:23 -08:00
bd0025579f cwebp/tiff: use the first image directory
tiffdec does not support and warns about multi-directory images.
previously, the code would read all the directories and thus attempt to
use the last rather than the first as the message suggests.

Change-Id: I3a10c778e6e924a3df75b41c26a9c03afb761044
2012-12-15 18:49:38 -08:00
df7aa07605 Merge "Cleanup around jpegdec" 2012-12-14 19:27:49 -08:00
0f57dcc31f decoding speed-up (~1%)
- precompute filtering strength once for all at the beginning
  instead of per-macroblock
- reduce size of VP8MB struct from 8 bytes to 4.
- removed VP8StoreBlock() accordingly

Change-Id: Icf3d329473e21c464770be3d72a04c9ee4c321f2
2012-12-14 10:22:54 -08:00
bcec339b01 Lossless bitstream clarification:
Clarify what the pixels of a color transform image are.

Change-Id: I720248b5417857468d54952440cf1bae6c091042
2012-12-12 14:03:44 -08:00
6bf208748c add examples/metadata.c
relocates the static functions from metadata.h and adds MetadataCopy()
to the interface

Change-Id: I28bfa9233d3dd70dddf6b561fe0bf4be378db1ec
2012-12-11 18:10:09 -08:00
207f89c0dc Merge "configure: add libwebpdemux status to summary" 2012-12-11 02:07:35 -08:00
1bd287a6e4 Cleanup around jpegdec
* change some (*func_ptr) construct to func_ptr simply.
  * remove one memcpy
  * group #include related to decoding together

Change-Id: If751cfbd9e78be75c57fb60fc9c937900c2c8fe0
2012-12-11 11:02:39 +01:00
9145567982 Merge "cosmetics: use '== 0' in size checks" 2012-12-11 01:48:54 -08:00
d6b88b7694 cosmetics: use '== 0' in size checks
Change-Id: I8ac18e2e570e4c6a8569a3955afa11fc943bee28
2012-12-10 23:27:34 -08:00
d3dace2ff0 cosmetics: jpegdec
- squash some whitespace
- remove unnecessary pointer check

Change-Id: I06208566a5621786479956ea658434f5c4d62fcc
2012-12-10 23:26:11 -08:00
2f69af732e configure: add libwebpdemux status to summary
Change-Id: I3b11d91de6780496b72bd89f93b49350e4350203
2012-12-10 23:08:53 -08:00
1c1c5646a5 cwebp: extract tiff decoding to its own module
Change-Id: If98d0d37de34b63ac10d826150237b5f99446532
2012-12-10 22:37:04 -08:00
6a871d66a4 cwebp: extract jpeg decoding to its own module
Change-Id: I45e1f0fa7b34286dd98926e0485e5a8ab1964570
2012-12-07 20:12:46 -08:00
2ee228f9a5 cwebp: extract png decoding to its own module
Change-Id: I80dd09fe1f1c6317e9d0cdd422438bda11b43ed5
2012-12-07 20:02:41 -08:00
4679db006c Merge "cwebp: add metadata framework" 2012-12-06 14:35:20 -08:00
63aba3aef1 cwebp: add metadata framework
unused currently, but the intent is to allow each format to populate
exif/xmp/icc with cwebp then transferring it to the webp file.

Change-Id: I0514f62de52fa7f89c595ee7ef2ad7dced910a41
2012-12-06 14:29:10 -08:00
931bd516b8 lossless bitstream: block size bits correction
The color transform block size is stored as 3 bits, not 4.
Fixed the description. The code snippet is already correct.

Change-Id: I830d848b54c121cb5426ca06853a3f1184fd9a31
2012-12-05 13:38:05 -08:00
e4fc4c1c63 lossless bitstream: block size bits correction
The prediction block size is stored as 3 bits, not 4.
Fixed the description. The code snippet is already correct.

Change-Id: Iaa66a7e9817b58a2557c9a71c2231cc400b6ae4d
2012-12-05 00:01:28 -08:00
d65ec6786a fix build, move token.c to src/enc/
broken in:
  657f5c9 move token buffer to its own file (token.c)

Change-Id: I8944a0b5760979bd43008c501b55df1d22d32180
2012-12-03 11:16:08 -08:00
657f5c91b1 move token buffer to its own file (token.c)
Change-Id: Ib9791c52f48d98fad5ed3830f36894ef5ac362fa
2012-12-03 13:50:14 +01:00
c34a3758ad introduce GetLargeValue() to slim-fast GetCoeffs().
GetCoeffs is (by far) the most consuming function of the decoder.
No speed change (unfortunately), but the main loop is somehow clearer.

Change-Id: I78f1c10cadc2c8696c041f5cbda86cab92cc6598
2012-11-28 08:24:23 +01:00
d5838cd598 faster non-transposing SSE2 4x4 FTransform
1-2% faster.
uses pmaddwd instead of transpose + pmullw.
Can possibly be simplified further.

Change-Id: I420e148816c4c6ab5e2080c9b1719dbbe6762d4e
2012-11-27 08:38:24 +01:00
f76191f9db speed up GetResidualCost()
* treat the last coeff as a special case
* re-arrange the inner code to be shorter
* replace some VP8EncBands[n] by n, for n = 0 or 1

Change-Id: I71e17b014cffad7b073e787fde06260905a6953f
2012-11-26 23:50:37 +01:00
ba2aa0fdda Add support for BITS=24 case
The main advantage is that you can avoid the use of uint64_t
some times, sticking to 32bit only.
Default still is BITS=32, this is mainly "in case".

Change-Id: Id694028793117ba822c37d46ef6c52fa0afed4ac
2012-11-26 23:47:08 +01:00
2e7f6e8ef2 makefile.unix: Dependency on libraries
The binaries should have dependency on related libraries only.
For example, 'vwebp' sould not depend on libpng, libjpeg etc.

Change-Id: I517b7ae6a9092d5de891b46d0e75d07d91548e93
2012-11-21 12:12:29 -08:00
dca84219ec Merge "Separate out mux and demux code and libraries:" 2012-11-19 15:12:55 -08:00
23782f95b4 Separate out mux and demux code and libraries:
- Separate out mux.h and demux.h
- muxtypes.h: new header for data types common to mux/demux
- Move some misc read/write utilities to utils/utils.h
- Remove some duplicate methods.
- Separate out mux/demux libraries

Change-Id: If9b9569b10d55d922ad9317ef51710544315d6de
2012-11-19 11:40:18 -08:00
bd56a01f87 configure: add summary output
Change-Id: Ib5d5f470aedf4e9537c10458d0e268735e6fca83
2012-11-16 18:59:46 -08:00
90e5e3190c dwebp manual: point to webpmux, gif2webp.
Change-Id: If140e3021ee1b60d6afa355883574be07e65b10c
2012-11-16 10:25:16 -08:00
540790ca6b gif2webp.c: add a note about prerequisites
Change-Id: I25a88f13b0c38c5968b5c4a3be0955e18e990723
2012-11-15 22:31:55 -08:00
d1edf697b2 cwebp man page: meaning of '-q' for lossy/lossless
Change-Id: I00b1e6a4f35c6c191072b3c30077166e7b143f56
2012-11-15 15:57:50 -08:00
79efa1d006 Add man page for gif2webp utility
Change-Id: Ia4826134db4e97427ab27977af7cc358b26e2b86
2012-11-15 15:55:06 -08:00
2243e40c39 Merge "gif2webp build support with autoconf tools" 2012-11-15 12:14:53 -08:00
c40efca157 gif2webp build support with autoconf tools
Change-Id: I51a007e7931f05f2eb2ac062038309c2127df3fd
2012-11-15 11:04:12 -08:00
6523e2d41d WebP Container:
annotate specific sections as experimental

Change-Id: If43222cef1c4fc2a8164b5f6ca4e89033379757d
2012-11-15 11:01:41 -08:00
4da788da3f Merge "simplify the fwd transform" 2012-11-15 00:54:10 -08:00
42c3b550ba simplify the fwd transform
-> remove two shifts

Change-Id: Ibc55bca98588da30553a7870224ffd0e13d57f52
2012-11-15 09:51:35 +01:00
41a6ced92e user GLfloat instead of float
Change-Id: I1af65f9a6046835cd4d390f37ccb0e659016ba1d
2012-11-15 09:35:01 +01:00
b542611964 fix indentation
Change-Id: Ieb22b158d52b16f9782a7e747dd5edbf29099ec5
2012-11-15 09:34:34 +01:00
68f282f79c * handle offset in anim viewer 'vwebp'
* fix gif2webp to handle disposal method and odd offset correctly

+ remove -scale and -crop option from vwebp, since it'll be broken
  with offsets and fragments. Needs a revisit.
+ remove a warning in gif2web

Change-Id: If04c6d085806e32540f2f15a37244c4407b719b3
2012-11-15 09:15:04 +01:00
118cb31270 Merge "add SSE2 version of Sum of Square error for 16x16, 16x8 and 8x8 case" 2012-11-15 00:07:44 -08:00
8a7c3cc8ee Merge "Change the order of -frame argument to be more natural" 2012-11-15 00:07:28 -08:00
99e0a707da Merge "Simplify the texture evaluation Disto4x4()" 2012-11-15 00:07:11 -08:00
0f923c3ffd make the bundling work in a tmp buffer
This avoids modifying the source picture.

Change-Id: I5b472859cda17fd3236a9e0fbedbb68977e09f85
2012-11-15 09:05:25 +01:00
e5c3b3f554 Simplify the texture evaluation Disto4x4()
We don't need to use the exact forward transform,
since it's only a rough evaluation.
-> Removed some shifts and rounding constants.

Change-Id: I3fdf8b4fe9720473894155e1ad0345f4d1fd9a33
2012-11-14 07:49:31 +01:00
4860008483 Change the order of -frame argument to be more natural
Now, its: +duration+xoffset+yoffset+disposal
+disposal can be omitted and will default to +0 (NONE)
additionally, +xoffset+yoffset can be omitted and will default to +0+0

Change-Id: I62138c9f675d4fc4408305babbcd485cb32b73d3
2012-11-14 06:19:31 +01:00
35bfd4c08f add SSE2 version of Sum of Square error for 16x16, 16x8 and 8x8 case
+ replace mm_set1_ps(0) by _mm_setzero_si128()

Change-Id: I4601033c27466532373f5dabfaf349ce5e5039da
2012-11-14 06:16:49 +01:00
a7305c2ef0 Clarification for unknown chunks
clarify that writers *may* modify unknown chunks if they specifically
intend to do so.

Change-Id: I8348df2ec84648201ea781c7bfffd1f36eb3c8e5
2012-11-13 10:41:13 -08:00
4c4398e2d5 Refine WebP Container Spec wrt unknown chunks.
Change-Id: Ibe950ab7afb2a7349f61c6fb81d587fba9ff27b6
2012-11-12 14:32:44 -08:00
2ca642e02a Rectify WebPMuxGetFeatures:
It should return ALPHA_FLAG for lossless bit-stream

Change-Id: I900bd5b58bf75bc25fca1abf4ecc12aea26eac1c
2012-11-09 14:37:20 -08:00
7caab1d8f6 Some cosmetic/comment fixes.
Change-Id: Id0613f84cc53fcbeceb913c835a262451687e27b
2012-11-09 10:46:38 -08:00
60b2651a8c Merge "Write a GIF to WebP converter based on libgif." 2012-11-09 08:01:07 -08:00
c7127a4dec Merge "Add NEON version of FTransformWHT" 2012-11-09 06:54:28 -08:00
11b2721258 Write a GIF to WebP converter based on libgif.
Change-Id: Ic64bf5307996a788ec61caf59a99ab37b4b1ae96
2012-11-08 11:21:25 -08:00
e9a15a37cf ExUtilWriteFile() to write memory segment to file
Change-Id: I4a93358e55ba5527667e017e178009251f64560e
2012-11-08 11:20:01 -08:00
74356eb558 Add a simple cleanup step in mux assembly:
In particular, this removes any unnecessary FRGM/ANMF/ANIM chunks, and
indirectly leads to removal of unnecessary VP8X chunks as well.
This is especially useful for GIF to WebP conversion - it saves 56 bytes
(ANMF: 16+8 bytes, ANIM: 6+8 bytes, VP8X: 10+8 bytes) for non-animated GIFs.

Change-Id: I3b50a96ca585844c421b0fa4cd8593e52c3f95c5
2012-11-08 11:15:22 -08:00
51bb1e5de7 mux.h: correct WebPDemuxSelectFragment() prototype
This is a correction to the following change:
a00a3daf5b Use 'frgm' instead of 'tile' in
webpmux parameters

Change-Id: I8fa0bce98efdde38827fd25712017a98a6ea7388
2012-11-08 11:04:39 -08:00
22a0fd9d01 Add NEON version of FTransformWHT
Contributed by Wayne Chen (datoudatou at gmail dot com)

Change-Id: I007c21db4eeadbf82b89f0963256f965deda7d90
2012-11-08 08:28:51 -08:00
fa30c86323 Update mux code to match the spec wrt animation
- Allow a duration of 0
- Rename LOOP chunk to ANIM and add the background color field to it.
- Add a disposal method field for each animation frame.
- Modify webpmux.c binary interface to allow the input of background color
  and disposal methods. Also make '-loop' and '-bgcolor' arguments optional
  with some default values.

Change-Id: I807372a61cdb8a0d3080ae3552caf2848070bf4d
2012-11-07 11:43:06 -08:00
d9c5fbefa4 by-pass Analysis pass in case segments=1
10-15% faster encoding.

Almost same output, binary wise. The main difference is
that we can't compute uv_alpha susceptibility, means there
can be subtle differences with different -sns values.

Change-Id: Id1b1a50929bf125b6372212fee1ed75a3bed975f
2012-11-06 22:53:13 -08:00
d2ad4450ce Merge changes Ibeccffc3,Id1585b16
* changes:
  Use 'frgm' instead of 'tile' in webpmux parameters
  Design change in ANMF and FRGM chunks:
2012-11-06 22:43:43 -08:00
5c8be2515d Merge "Chunk fourCCs for XMP/EXIF" 2012-11-06 16:17:32 -08:00
a00a3daf5b Use 'frgm' instead of 'tile' in webpmux parameters
- Also, use the term 'fragments' instead of 'tiling' in code
- This makes code consistent with the spec.

Change-Id: Ibeccffc35db23bbedb88cc5e18e29e51621931f8
2012-11-06 16:09:10 -08:00
81b8a741ed Design change in ANMF and FRGM chunks:
- Make ANMF and FRGM chunks hierarchical so that they encompass all chunks of
  that frame.
- Use this in demuxer: stop parsing a frame if all image data for it isn't
  available yet. Thus, we have a frame-level incremental support; that is,
  all frames that are fully available can be parsed.
- Note: We still keep incremental support for single images - so that they can
  be decoded with incremental decoding.

Change-Id: Id1585b16b06caee1d84009c42a25d2de29fa6135
2012-11-06 16:04:33 -08:00
f903cbab9a Chunk fourCCs for XMP/EXIF
Use separate fourCCs "XMP " and "EXIF" instead of a common "META"
Also, some refactorization in webpmux.c

Change-Id: Iad3337e5c1b81e785c60670ce28b1f536dd7ee31
2012-11-06 14:53:21 -08:00
812933d6ba Tune performance of HistogramCombine
Number of pairs selected are limited between 25% of histogram
images (at start) and number of histogram images left at any iteration.
Increase the range of iter_mult.
Removed min_cluster_size as parameter for tuning HistogramCombine.

Change-Id: Ia4068cd7af4d0f63c5af9001aceda8a40b9de740
2012-11-05 16:45:39 -08:00
52ad1979d2 Animation specification in container spec
Change-Id: I3cb1d994a460d9a712998ca1045bf6bc7d953c04
2012-11-05 13:29:23 -08:00
001b930219 Image fragment specification in container spec
Change-Id: If8cad296738465df4327dfb6b44efa7e0356070e
2012-11-02 15:37:49 -07:00
391f9db9fa Ordering of description of bits in container spec
The description of bits in a byte should be from MSB to LSB

Change-Id: I50f2dfbb79b33eb434a771cca252c5d0f81fc71e
2012-11-02 15:27:37 -07:00
d57357762a Metadata specification in container spec
Change-Id: I4b76697efb160145ffef3fd9df9905544c4e8792
2012-11-02 15:14:47 -07:00
1c4609b1f8 Merge commit 'v0.2.1'
* commit 'v0.2.1':
  Update ChangeLog
  update NEWS
  bump version to 0.2.1
  libwebp: validate chunk size in ParseOptionalChunks
  cwebp (windows): fix alpha image import on XP
  autoconf/libwebp: enable dll builds for mingw
  [cd]webp: always output windows errors
  fix double to float conversion warning
  cwebp: fix jpg encodes on XP
  VP8LAllocateHistogramSet: fix overflow in size calculation
  GetHistoBits: fix integer overflow
  EncodeImageInternal: fix uninitialized free
  fix the -g/O3 discrepancy for 32bit compile
  fix the BITS=8 case
  Make *InitSSE2() functions be empty on non-SSE2 platform
  make *InitSSE2() functions be empty on non-SSE2 platform
  make VP8DspInitNEON() public

Conflicts:
	src/Makefile.am
	src/dsp/dec_neon.c

Change-Id: Iddc5152e4a6892db96c12d7c3f74adbc85fe6178
2012-11-02 12:20:19 -07:00
0ca584cbbf Merge "Color profile specification in container spec" 2012-11-01 19:20:46 -07:00
e8b41ad136 add NEON asm version for WHT inverse transform
Contributed by Wayne Chen (datoudatou at gmail dot com)

+ some header cleanup
+ remove the NEON suffix in static functions

Change-Id: I75bf5e9b54cf5e1acc53764c6f081d61690f8e3d
2012-11-01 16:31:01 -07:00
af6f0db291 Color profile specification in container spec
Change-Id: I53f849c7d93e1cdc971dda1fffd8f359f40607d3
2012-11-01 11:16:29 -07:00
a61a824b3a Merge "Add NULL check in chunk APIs" 2012-10-31 16:07:24 -07:00
0e8b7eedaa fix WebPPictureView() unassigned strides
y_stride/uv_stride/argb_stride were not set properly.

Change-Id: I001b8d46f873ca04b5c68eccd6f232061020f9ec
2012-10-31 16:01:34 -07:00
75e5f17e3b ARM/NEON: 30% encoding speed-up
(implements the backward and forward transforms in the encoder)

original patch by Wayne Chen (datoudatou at gmail dot com)

Change-Id: Ic00f3bffcdf7a924f043006728735c810ee47a57
2012-10-31 14:00:20 -07:00
02b4356875 Add NULL check in chunk APIs
Change-Id: I173ff6c9259111762580c1963ff60e34fd1e9b6b
2012-10-31 13:33:20 -07:00
a077072777 mux struct naming
members of public structs should not have a trailing underscore.

Change-Id: Ieef42e1da115bf42b0ea42159701e32bed7b9f60
2012-10-31 11:37:49 -07:00
6c66dde80f Merge "Tune Lossless encoder" 2012-10-30 18:27:14 -07:00
ab5ea217f7 Tune Lossless encoder
- Changed the dynamic range where more aggressive
  (BackwardReferencesTraceBackward) heuristic is run from quality > 10
  (instead of quality > 25).
- Limit the backward-ref Window size to 16*width & 256*width for lower
  qualities ([0, 25[ & [25, 50[) respectively, instead of 1M window.
- Evaluate the params for HashChainFindCopy outside this function call
  and pass it, instead of recomputing them for every call.

Change-Id: If9eedfc14b978e7632d7cf69c96186e2910b0554
2012-10-30 17:30:17 -07:00
74fefc8ce8 Update ChangeLog
Change-Id: I89a9c8cf6793c38e2b13d6e0557414fb05620eec
2012-10-30 16:32:36 -07:00
92f8059ce4 Rename some chunks:
TILE --> FRGM and FRM --> ANMF

Change-Id: I752f90b950413501aecb021a8f57882da0e01484
2012-10-30 15:02:15 -07:00
3bb4bbeb60 Merge "Mux API change:" 2012-10-30 14:55:39 -07:00
d0c79f0552 Mux API change:
Create common APIs for image, frame and tile.

Change-Id: I709ad752133094bd5bc89dd9c832ff79802aac68
2012-10-30 14:16:29 -07:00
abc06044e7 Merge "update NEWS" into 0.2.0 2012-10-29 20:42:00 -07:00
57cf313bba update NEWS
Change-Id: Ie225646ba11a6a1d61f5642405c37ed2d20334f8
2012-10-29 19:26:26 -07:00
25f585c4f2 bump version to 0.2.1
lib - 0.2.1
libtool - 4.1.0 (compatible release)

Change-Id: Ib6ca47f2008d5c97d818422816ac60d0d0d8cffa
2012-10-29 19:17:17 -07:00
fed7c0485a libwebp: validate chunk size in ParseOptionalChunks
the max wasn't checked leading to a rollover case, possibly exploitable.
additionally check the RIFF size early, to avoid similar issues.

pulled from chromium:
 http://codereview.chromium.org/11229048/

Change-Id: I4050b13a7e61ec023c0ef50958c45f651cf34c49
2012-10-29 14:00:33 -07:00
552cd9bce0 cwebp (windows): fix alpha image import on XP
Query the converter to ensure the format is supported; add BGR formats
as RGBA was failing for PNG on XP

Fixes issue 129

Change-Id: Ib42aaf160a6c18e767e8c7dbe93dec7c45953399
2012-10-29 14:00:28 -07:00
b14fea993a autoconf/libwebp: enable dll builds for mingw
Change-Id: Ic1ace62aad1d8de95bc370c6729ded83b7b71f0b
2012-10-29 14:00:24 -07:00
4a8fb27223 [cd]webp: always output windows errors
don't hide failures with -v.

Change-Id: I1578dbb7be67f041f0984bf6696c0c895c1600d9
2012-10-29 14:00:18 -07:00
d662158010 fix double to float conversion warning
introduced in:
 a792b91 fix the -g/O3 discrepancy for 32bit compile

Change-Id: Ic77d6170a5a91cf58ec10c68656ac61a7c0ee41d
2012-10-29 14:00:14 -07:00
72b96a6905 cwebp: fix jpg encodes on XP
correct has_alpha check; previously it was controlled by keep_alpha,
which overrode the source format check.
fixes issue #127

Change-Id: I414cfd9c5ed60b13673ccd2262ee5e4505ed6f6a
2012-10-29 14:00:10 -07:00
734f762a08 VP8LAllocateHistogramSet: fix overflow in size calculation
the multiplications done for total_size would be done with integers,
possibly overflowing, before being promoted to 64-bit for the addition

Change-Id: I32c3a6400fc2ef120c38e01a8693f4cb1727234d
2012-10-29 14:00:05 -07:00
f9cb58fbce GetHistoBits: fix integer overflow
huff_image_size was a size_t (=32 bits with 32-bit builds) which could
rollover causing an incorrectly sized allocation and a crash in lossless
encoding.
fixes issue #128

Change-Id: I0f20cee98c29b2b40b02607930b6b7a7ca56996d
2012-10-29 14:00:01 -07:00
b30add2017 EncodeImageInternal: fix uninitialized free
on allocation error refs.refs would be uninitialized and free'd, causing
a crash

Change-Id: Idb7daec7aec3e5d769d8103595c28a9d0d0b86f4
2012-10-29 13:59:57 -07:00
3de58d7730 fix the -g/O3 discrepancy for 32bit compile
in debug mode, some float operations see their intermediate
values stored in memory rather than staying in the FPU (which
is 80bit precision).

Several fixes are possible (breaking long calculations into
atomic steps for instance), but simpler of all is just about
turning the cost[] array into float* instead of double*.

The code is a tad faster, and i didn't see any major output
size difference.

Change-Id: I053e6d340850f02761687e072b0782c6734d4bf8
2012-10-29 13:59:52 -07:00
77aa7d50a4 fix the BITS=8 case
spotted by Måns Rullgård (mans at mansr dot com)

Change-Id: I4484b1f00223a0be18cbe924b24a9f5ccffb7ea2
2012-10-29 13:59:48 -07:00
e5970bda8a Make *InitSSE2() functions be empty on non-SSE2 platform
this avoids the '*.o has no symbols' warning messages

Change-Id: Ib47f9faf9073e39293acad6b2f21f21dba8c5378
2012-10-29 13:59:44 -07:00
ef5cc47ee7 make *InitSSE2() functions be empty on non-SSE2 platform
this avoids the '*.o has no symbols' warning messages

Change-Id: I96aad8637fba47fdaa5a12740e3881ed362c805b
2012-10-29 13:59:38 -07:00
c4ea259db4 make VP8DspInitNEON() public
this will avoid the "dec_neon.o has no symbol" warning

no change in binary size observed on linux.

Change-Id: Ifd83dfc6a0c61905481599b06cb5e711f55efa7d
2012-10-29 13:59:31 -07:00
8344eadfe0 Merge "libwebp: validate chunk size in ParseOptionalChunks" 2012-10-23 02:07:13 -07:00
4828bb931d Merge "cwebp (windows): fix alpha image import on XP" 2012-10-23 00:57:21 -07:00
30763333f3 libwebp: validate chunk size in ParseOptionalChunks
the max wasn't checked leading to a rollover case, possibly exploitable.
additionally check the RIFF size early, to avoid similar issues.

pulled from chromium:
 http://codereview.chromium.org/11229048/

Change-Id: Ifebc712bf3d3de0129b76ca4c57c68e062abc429
2012-10-22 21:57:59 -07:00
704818980f AccumulateLSIM: fix double -> float warnings
Change-Id: I234a5cd09b9351dbbbbc5076be35bb794d1bf890
2012-10-22 18:00:20 -07:00
eda8ee4b3b cwebp (windows): fix alpha image import on XP
Query the converter to ensure the format is supported; add BGR formats
as RGBA was failing for PNG on XP

Fixes issue 129

Change-Id: I02e0d74b3b21337bc5fffd6a5dc158b7809b9aa9
2012-10-19 18:48:47 -07:00
c6e98658d2 Merge "add EXPERIMENTAL code for YUV-JPEG colorspace" 2012-10-19 12:13:34 -07:00
f0360b4fcf add EXPERIMENTAL code for YUV-JPEG colorspace
This is mostly for experimentation!
Need to define USE_YUVj flag in the code for that.

suggested by benwreder at hotmail dot com

Change-Id: If0b8e2c1863efc08ce097de6de20f4c7efc3f7e8
2012-10-19 20:15:58 +02:00
f86e6abe1f add LSIM metric to WebPPictureDistortion()
LSIM stands for "local similarity": before matching
a compressed pixel to the source, we search around in the source
and minimise the squared error. So, this is close to PSNR calculation,
but mitigates some of its limitations (pure translation and noise for instance).

There's a new -print_lsim option to cwebp too.

Change-Id: Ia38561034c7a90e71d2ea0f55bb1de527eda245b
2012-10-19 06:48:11 -07:00
c3aa215afa Speed up HistogramCombine for lower qualities.
Make the heuristic for combining Histograms a function of compression
quality. This change will speed-up compression time for compression
quality less than 75. The compression time/density remains unchanged
for compression quality 75 and higher.

Change-Id: I94513d51078340fbc0737d459fab2cebdd2d6082
2012-10-16 15:45:36 -07:00
1765cb1ca5 Merge "autoconf/libwebp: enable dll builds for mingw" 2012-10-09 13:24:25 -07:00
a13562e800 autoconf/libwebp: enable dll builds for mingw
Change-Id: I7e0ee9f514a7102ee002c432dfb280187f06a596
2012-10-09 10:53:31 -07:00
9f469b57a9 typo: no_fancy -> no_fancy_upsampling
Change-Id: Ia0cb8c4a5b586861fb89253f59555e555a3a44db
2012-10-09 15:14:24 +02:00
1a27f2f808 Merge "fix double to float conversion warning" 2012-10-09 00:06:52 -07:00
cf1e90dec7 Merge "cwebp: fix jpg encodes on XP" 2012-10-09 00:04:19 -07:00
f2b5d19b30 [cd]webp: always output windows errors
don't hide failures with -v.

Change-Id: I46485a66f266fd9e9e8c640d1051cd22cfa40658
2012-10-08 18:36:10 -07:00
e855208c16 fix double to float conversion warning
introduced in:
 a792b91 fix the -g/O3 discrepancy for 32bit compile

Change-Id: I6a77223f237527eda4ee1d6eaa993351bd74f1d6
2012-10-08 18:27:27 -07:00
ecd66f774d cwebp: fix jpg encodes on XP
correct has_alpha check; previously it was controlled by keep_alpha,
which overrode the source format check.
fixes issue #127

Change-Id: I949be90419b03610c64900be0fd37f83b70cbe73
2012-10-08 18:26:21 -07:00
7b3eb372ad Tune lossless compression to get better gains.
Tune compression heuristics to get better gains across wide quality range.

Change-Id: Ic342d4dbcf83fe2086a34e5c184aef0714109430
2012-10-05 09:58:29 -07:00
ce8bff45bc Merge "VP8LAllocateHistogramSet: fix overflow in size calculation" 2012-10-03 14:57:15 -07:00
ab5b67a1d0 Merge "EncodeImageInternal: fix uninitialized free" 2012-10-03 14:53:35 -07:00
7fee5d1231 Merge "GetHistoBits: fix integer overflow" 2012-10-03 14:51:22 -07:00
a6ae04d455 VP8LAllocateHistogramSet: fix overflow in size calculation
the multiplications done for total_size would be done with integers,
possibly overflowing, before being promoted to 64-bit for the addition

Change-Id: Id5c127c8a497ce5de89a276c17f36b59eeb67c21
2012-10-03 12:18:00 -07:00
80237c4371 GetHistoBits: fix integer overflow
huff_image_size was a size_t (=32 bits with 32-bit builds) which could
rollover causing an incorrectly sized allocation and a crash in lossless
encoding.
fixes issue #128

Change-Id: I175c8c6132ba9792034807c5c1028dfddfeb4ea5
2012-10-03 12:17:52 -07:00
8a9972353d EncodeImageInternal: fix uninitialized free
on allocation error refs.refs would be uninitialized and free'd, causing
a crash

Change-Id: I8d77069aadc594758aaa79b2b73376c0107e57e4
2012-10-03 12:17:47 -07:00
0b9e682934 minor cosmetics
spotted in patch #34187

Change-Id: Ia706af6ef7674ec7a1d7250da08f718ed7c09e72
2012-10-03 15:22:33 +02:00
a792b913bd fix the -g/O3 discrepancy for 32bit compile
in debug mode, some float operations see their intermediate
values stored in memory rather than staying in the FPU (which
is 80bit precision).

Several fixes are possible (breaking long calculations into
atomic steps for instance), but simpler of all is just about
turning the cost[] array into float* instead of double*.

The code is a tad faster, and i didn't see any major output
size difference.

Change-Id: Icf1f833e15f8ee4ecc7f9a521d07fdc96ef711aa
2012-10-03 15:15:58 +02:00
73ba4357fe Merge "detect and merge similar segments" 2012-10-02 06:22:23 -07:00
fee6627538 detect and merge similar segments
similar = same quant and filter strength.
This save some bits in the segment map

Change-Id: I6f594474ad82bddf013278d47089e43a02e07e63
2012-10-01 21:18:03 +02:00
0c44f41585 src/webp/*.h: don't forward declare enums in C++
Change-Id: I36d3765e94d2b5529b321c186ccee1744785c5b3
fixes:
 error: ISO C++ forbids forward references to 'enum' types
since:
 28d25c8 replace 'typedef struct {} X;" by "typedef struct X X; struct X {};"
2012-09-28 21:21:41 -07:00
d7a5ac86b9 vwebp: use demux interface
fixes broken build since:
 ab3234a Create WebPMuxFrameInfo struct for Mux APIs

Change-Id: I19d472f672b9234b15425a2e55ca89a3ea35bd64
2012-09-26 23:44:59 -07:00
931e0ea1d5 Merge "replace 'typedef struct {} X;" by "typedef struct X X; struct X {};"" 2012-09-26 07:13:36 -07:00
8f216f7e60 remove cases of equal comparison for qsort()
Returning 0 (equal) can lead to undefined behaviour.
And, in our cases we'll never have equal keys (added asserts for that)

Change-Id: Ifaf202df321d3f877ad2a03de42e0d6cdd1b2388
2012-09-25 19:03:41 +02:00
28d25c8256 replace 'typedef struct {} X;" by "typedef struct X X; struct X {};"
Change-Id: I937dc8781bc87ef0c4e109d49dc1cf6f18033f12
2012-09-25 18:39:22 +02:00
2afee60a7c speed up for ARM using 8bit for boolean decoder
SBITS=8 is reported 20-30% faster on ARM (where 64bit ops
are expensive).

Also use 32bits for i32.

Change-Id: Id6a7197d805061aeb8832f20432512d0d930ebfa
2012-09-10 23:27:58 +02:00
5725cabac0 new segmentation algorithm
fixes the 'blocky sky problem' (saturation problem: when luma was flat,
chroma noise was taking over, resulting in random segment id assigned.
When just using a common uniform segment was better).

+ side clean-up and readibility/experimentability MACRO'ization
+ added '-map 7' option

Change-Id: I35982a9e43c0fecbfdd7b05e4813e8ba8c121d71
2012-09-04 23:09:15 +02:00
2cf1f81590 Merge "fix the BITS=8 case" 2012-09-03 02:36:03 -07:00
12f78aec48 fix the BITS=8 case
spotted by Måns Rullgård (mans at mansr dot com)
Change-Id: I4720dc2eeb645af894e396739be6fa11b5fe2739
2012-09-03 02:29:14 -07:00
6920c71f0a fix MSVC warnings regarding implicit uint64 to uint32 conversions
Change-Id: I284dae9222a3817bba3c5ba6be271b31b5bf660d
2012-09-01 07:21:45 -07:00
f6c096aad3 webpmux binary: Rename 'xmp' option to 'meta'
Change-Id: I00d7d2aa43ccb1e86b58e75e8677ea8ef7e1226e
2012-08-29 22:24:10 -07:00
ddfe871a51 webpmux help correction
Clarify 'SET_OPTIONS'

Change-Id: I623ea955beb2a800709412b914a257abd95266cc
2012-08-29 22:23:12 -07:00
b7c5544216 Merge "Make *InitSSE2() functions be empty on non-SSE2 platform" 2012-08-29 08:26:42 -07:00
1c04a0d438 Common APIs for chunks metadata and color profile.
Change-Id: Ie105ce913c0b56e34cc26fd7ec397103354f268a
2012-08-29 08:21:43 -07:00
2a3117a1e6 Merge "Create WebPMuxFrameInfo struct for Mux APIs" 2012-08-29 08:19:07 -07:00
5c3a7231ca Make *InitSSE2() functions be empty on non-SSE2 platform
this avoids the '*.o has no symbols' warning messages

Change-Id: I00cf527a9041a810d896bd24b993112af6276323
2012-08-28 11:02:38 -07:00
7c6e60f4bd make *InitSSE2() functions be empty on non-SSE2 platform
this avoids the '*.o has no symbols' warning messages

Change-Id: Idbaa02f5c2f7c632997a26f9507926922d191b6e
2012-08-27 23:40:47 -07:00
c7eb45764f make VP8DspInitNEON() public
this will avoid the "dec_neon.o has no symbol" warning

no change in binary size observed on linux.

Change-Id: Ia27ae2bc5a03d714afa7e46671fdcf4cb630784d
2012-08-27 00:28:13 -07:00
ab3234ae6b Create WebPMuxFrameInfo struct for Mux APIs
Change-Id: I1f3b15d679280b5347124e1d59865a3df089043b
2012-08-23 15:18:51 +05:30
e3990fd8e4 Alignment fixes
Change-Id: I99b570a6621be271abd3df1c3316cdd7286cfe83
2012-08-23 13:22:59 +05:30
e55fbd6d2c Merge branch '0.2.0'
* 0.2.0: (42 commits)
  Update ChangeLog
  dec/io.c: cosmetics
  RGBA4444: harmonize lossless/lossy alpha values
  fix RGBA4444 output w/fancy upsampling
  Alignment fix
  avoid rgb-premultiply if there's only trivial alpha values
  fix the ARGB4444 premultiply arithmetic
  Lossless decoder fix for a special transform order
  Update encoding heuristic w.r.t palette colors.
  remove unused ApplyInverseTransform()
  Update ChangeLog
  update AUTHORS
  update NEWS
  add support for ARGB -> YUVA conversion for lossless decoder
  bump version to 0.2.0
  fix alpha-plane check + add extra checks
  MODE_YUVA: set alpha to opaque if the image has none
  silence one more warning
  move some RGB->YUV functions to yuv.h
  README: sync [cd]webp help output
  ...

Change-Id: I4c4e3be2e88655d25d4dd2eae46c580d960b12ac
2012-08-17 14:33:56 -07:00
4238bc0adb Update ChangeLog
Change-Id: I598aaf69c1a45a694c36f2f3166ed9adc20ace84
2012-08-15 22:49:03 -07:00
c655380c36 dec/io.c: cosmetics
- deindent EmitAlphaRGB*
- add some missing consts

Change-Id: I65f88da295e6a0afa383fadc2ef90a40613c2d62
2012-08-15 10:27:54 -07:00
fe1958f17d RGBA4444: harmonize lossless/lossy alpha values
lossy was rounding with a bias toward opaque:
[232+, 8] -> [15, 1]
now both paths use the range:
[240+, 16] -> [15, 1]

Change-Id: I3da2063b4959b9e9f45bae09e640acc1f43470c5
2012-08-14 14:02:30 -07:00
681cb30ad2 fix RGBA4444 output w/fancy upsampling
compensates for the 1-line delay in the upscaler, outputting the correct
alpha row

Change-Id: Ia9a65bcb3cfa19e42185523cc6e706101a39d45d
2012-08-14 13:11:53 -07:00
f06c1d8f7b Merge "Alignment fix" into 0.2.0 2012-08-09 16:09:58 -07:00
f56e98fd11 Alignment fix
Change-Id: Ia5475247f03456b01571ae7531da90f74c068045
2012-08-10 02:10:32 +05:30
6fe843baeb avoid rgb-premultiply if there's only trivial alpha values
With this, MODE_rgbA can safely be used without speed penalty
even in case of pure-lossy alpha-less input.
It's also an optimization when cropping a fully-opaque region from
an image with alpha: premultiply is then skipped

Change-Id: Ibee28c75744f193dacdfccd5a2e7cd1e44604db6
2012-08-09 11:33:29 -07:00
528a11af35 fix the ARGB4444 premultiply arithmetic
* green was not descaled properly
* alpha was over-dithered, making the value '0x0f' not be a fixed point
* alpha value was not restored ok.

Change-Id: Ia4a4d75bdad41257f7c07ef76a487065ac36fede
2012-08-09 11:32:30 -07:00
a0a488554d Lossless decoder fix for a special transform order
Fix the lossless decoder for the case when it has to apply other
inverse transforms before applying Color indexing inverse transform.

The main idea is to make ColorIndexingInverse virtually in-place: we
use the fact that the argb_cache is allocated to accommodate all
*unpacked* pixels of a macro-row, not just *packed* pixels.

Change-Id: I27f11f3043f863dfd753cc2580bc5b36376800c4
2012-08-08 23:52:08 -07:00
62dd9bb242 Update encoding heuristic w.r.t palette colors.
Added a threshold of MAX_COLORS_FOR_GRAPH for color-palettes, above
which the graph hint is ignored.

Change-Id: Ia5d7f45e52731b6eaf2806999d6be82861744fd3
2012-08-08 18:57:52 -07:00
6f4272b090 remove unused ApplyInverseTransform()
transforms are only allowed for is_level0

Change-Id: Iec8ce8bdbe024aae6cae2688e2934ab8f445000c
2012-08-07 22:41:25 -07:00
93bf0faafa Update ChangeLog
Change-Id: I5ff337065b8a6f8952dc77c3f9c7798267ee6727
2012-08-03 16:21:12 -07:00
5934fc59db update AUTHORS
Change-Id: I205422ac3be5e363adfc84dcf84f6d5d84b9a40f
2012-08-03 16:15:38 -07:00
014a711d96 update NEWS
changes since v0.1.99

Change-Id: Iaab1545516ef8df9f9dd6b4bc9cbf07539cb454f
2012-08-03 16:13:29 -07:00
43b0d6107a add support for ARGB -> YUVA conversion for lossless decoder
This was returning an (hard-to-explain) error before.
(through WebPDecodeYUV() for instance).

+ rationalize the incremental API:
-> add WebPINewYUVA
-> deprecated WebPINewYUV
-> add WebPIDecGetYUVA
-> deprecated WebPIDecGetYUV

+ some NULL cosmetics

Change-Id: I39a6bd6018a34294d898b29f6c40e2cf76f1037e
2012-08-03 15:41:01 -07:00
33705ca093 bump version to 0.2.0
Change-Id: I01cb50b9c4c8e9245aede3947481cbbd27d6a19d
2012-08-03 15:41:01 -07:00
c40d7ef125 fix alpha-plane check + add extra checks
Change-Id: I9d8c9743f9d4f3d394544773ed2d0c31a9acf24d
2012-08-03 14:44:35 -07:00
a06f802325 MODE_YUVA: set alpha to opaque if the image has none
this change avoids returning uninitialized alpha values when decoding
lossy with alpha to YUVA

Change-Id: I1e02459ac28b36f1f2b422063d057a5faba2f8f2
2012-08-03 12:04:44 -07:00
52a87dd7ff Merge "silence one more warning" into 0.2.0 2012-08-02 17:53:04 -07:00
3b02309347 silence one more warning
inadvertently added in last warning roundup

Change-Id: I38e6bcfb18c133f2dc2b38cec81e12d2ff556011
2012-08-02 17:50:12 -07:00
f94b04f045 move some RGB->YUV functions to yuv.h
will be needed later

Change-Id: I6b9e460db2d398b9fecd5d3c1bbdb3f2f3d4f5db
2012-08-02 17:23:02 -07:00
4b71ba035a README: sync [cd]webp help output
Change-Id: Ic54e0f3e5e2e667adb369321e5849890d3b96e42
dwebp: -pam, -alpha
2012-08-02 16:11:02 -07:00
c9ae57f596 man/dwebp.1: add links to output file format details
Change-Id: I30e3e52e428c9e68ba2ec263024a1edc56ad6741
2012-08-02 15:10:31 -07:00
292ec5cc7d quiet a few 'uninitialized' warnings
spurious in this case, but addresses e.g.,
... potentially uninitialized local variable 'weighted_average' used

Change-Id: Ib99998bf49e4af7a82ee66f13fb850ca5b17dc71
2012-08-02 14:03:30 -07:00
4af3f6c4d3 fix indentation
Change-Id: Ib00b3cdc21ac336a56390f1e71c169e7fd4767a6
2012-08-02 11:55:55 -07:00
9b261bf521 remove the last NOT_HAVE_LOG2 instances
Change-Id: I193ecf82316cd1d5d7ddeebebf8fc98afccf0ede
2012-08-02 06:42:41 -07:00
323dc4d9b9 remove use of log2(). Use VP8LFastLog2() instead.
Order-by-cost mostly unchanged (up to a scaling constant 1/log(2))
(except for few minor diff in < 2% of cases)

+ remove unused field cost_mode->cache_bits_

Change-Id: I714f8ab12f49a23f5d499a64c741382c9b489a3e
2012-08-02 00:08:58 -07:00
8c515d54ea Merge "harness some malloc/calloc to use WebPSafeMalloc and WebPSafeCalloc" into 0.2.0 2012-08-01 18:16:46 -07:00
d4b4bb0248 Merge changes I46090628,I1a41b2ce into 0.2.0
* changes:
  check VP8LBitWriterInit return
  lossless: fix crash on user abort
2012-08-01 13:19:32 -07:00
bff34ac1ca harness some malloc/calloc to use WebPSafeMalloc and WebPSafeCalloc
quite a large security sweep.

Change-Id: If150dfbb46e6e9b56210473a109c8ad6ccd0cea4
2012-08-01 12:06:04 -07:00
a3c063c714 Merge "extra size check for security" into 0.2.0 2012-08-01 12:00:30 -07:00
5e7963000a Merge "WebPEncode: clear stats at the start of encode" into 0.2.0 2012-08-01 12:00:09 -07:00
f1edf62fae Merge "rationalize use of color-cache" into 0.2.0 2012-08-01 11:55:36 -07:00
c19333173a extra size check for security
no speed diff observed by removing the test before calling BitWriterResize().

+ remove some unnecessary memset() in VP8LBitWriter
+ fix mixed code/variable-decl in BIG_ENDIAN mode

Change-Id: I36be61f83d10a43e4682b680c2dae0e494da4218
2012-08-01 00:37:24 -07:00
906be65744 rationalize use of color-cache
* ~1-4% faster
* if it's not used, don't use it
* remove the special handling of cache_bits = 0
* remove some tests in the loops

Change-Id: I19d87c3ca731052ff532ea8b2d8e89816507b75f
2012-08-01 00:32:12 -07:00
dd1c3873fe Add image-hint for low-color images.
For low-color images, it may be better to not use color-palettes.
Users should treat this as one another hint (as with Photo &
Picture) and another parameter for tuning the compression density.
The optimum compression can still be obtained by running (outer loop)
compression with all possible tunable parameters.

Change-Id: Icb1a4face2a84774e16e801aee4a8ae97e232e8a
2012-07-31 23:11:19 -07:00
4eb7aa64da Merge "WebPCheckMalloc() and WebPCheckCalloc():" into 0.2.0 2012-07-31 18:37:14 -07:00
80cc7303ab WebPCheckMalloc() and WebPCheckCalloc():
safe size-checking versions of malloc() and calloc()

Change-Id: Iffa3138c48b9b254b3d7eaad913e1f852d9dafba
2012-07-31 16:56:39 -07:00
183cba83a7 check VP8LBitWriterInit return
Change-Id: I460906281598f5792bd75a25b14b449c8daaff8c
2012-07-31 12:11:40 -07:00
cbfa9eecf4 lossless: fix crash on user abort
avoid free on uninitialized bit writer buffer

Change-Id: I1a41b2cea421bf5a2ea0af33c6e84018cb997caf
2012-07-31 11:59:54 -07:00
256afefa50 cwebp: exit immediately on version mismatch
{Picture,Config}Init don't do allocations and attempting to free any of
their contents on version mismatch will likely cause a crash

Change-Id: I2a5aece235f9680fb406aec4799adceea7f62cfc
2012-07-27 19:58:58 -07:00
475d87d767 WebPEncode: clear stats at the start of encode
also relocate user_data from WebPAuxStats to the WebPPicture struct to
make clearing easier while placing it closer to the progress hook with
which it's used.
prior to this change some spurious lossless data could be reported in
the lossy (sans alpha) encoding case. additionally user_data could be
lost during lossless encoding.

Change-Id: I929fae3dfde4d445ff81bbaad51445ea586dd80b
2012-07-27 19:57:18 -07:00
a7cc729126 fix type and conversion warnings
avoids warning messages on MSVC mainly

Change-Id: I80f281d5263a54c6a224bb095175497cf2f4ce1e
2012-07-25 14:18:21 -07:00
7d853d79dc add stats for lossless
* Extend AuxStats with new fields
  it's slightly ABI-incompatible, but i guess it's ok for 0.1.99+
  I expect to add more stats later, possibly (predictor stats, etc.)
* Have cwebp report the features used by lossless
  compression (either for alpha or full lossless coding)
* Print the PSNR for alpha (useful in case of -alpha_q)
* clean-up alpha.c signatures
+ misc cleanup (added const '* const ptr', etc.)

Change-Id: I157a21581f1793cb0c6cc0882e7b0a2dde68a970
2012-07-24 16:17:13 -07:00
d39177b74c make QuantizeLevels() store the sum of squared error
(instead of MSE).
Useful for directly storing the alpha-PSNR (in another patch)

Change-Id: I4072864f9c53eb4f38366e8025a2816eb14f504e
2012-07-24 15:06:18 -07:00
5955cf5e89 replace x*155/100 by x*101581>>16
Don't expect a visible speed diff. it's just cool.
(and, that's one less TODO in the code).

Change-Id: Iaeb2f1c930debb51501e170ee806f2f945fb1a8d
2012-07-24 15:06:00 -07:00
7d732f905b make QuantizeLevels() store the sum of squared error
(instead of MSE).
Useful for directly storing the alpha-PSNR (in another patch)

Change-Id: I4072864f9c53eb4f38366e8025a2816eb14f504e
2012-07-23 14:26:56 -07:00
e45a446ad5 replace x*155/100 by x*101581>>16
Don't expect a visible speed diff. it's just cool.
(and, that's one less TODO in the code).

Change-Id: Iaeb2f1c930debb51501e170ee806f2f945fb1a8d
2012-07-23 14:23:33 -07:00
159b75d31a cwebp output size consistency:
In case of lossless too, it should report full file size.
Fixes this issue: http://code.google.com/p/webp/issues/detail?id=126

Change-Id: I96e2bf09e6c9470a0267f5eea911d9b40d1addb3
2012-07-23 12:47:24 +05:30
cbee59eba4 Merge commit 'v0.1.99'
* commit 'v0.1.99': (39 commits)
  Update ChangeLog
  add extra precision about default values and behaviour
  header/doc clean up
  Makefile.vc: fix webpmux.exe *-dynamic builds
  remove INAM, ICOP, ... chunks from the test webp file.
  harmonize authors as "Name (mail@address)"
  makefile.unix: provide examples/webpmux target
  update NEWS
  README: cosmetics
  man/cwebp.1: wording, change the date
  add a very crude progress report for lossless
  rename 'use_argb_input' to 'use_argb'
  add some padding bytes areas for later use
  fixing the findings by Frederic Kayser to the bitstream spec
  add missing ABI compatibility checks
  Doc: container spec text tweaks
  add ABI compatibility check
  mux.h: remove '* const' from function parameters
  encode.h: remove '* const' from function parameters
  decode.h: remove '* const' from function parameters
  ...

Conflicts:
	src/mux/muxinternal.c

Change-Id: I635d095c451742e878088464fe6232637a331511
2012-07-21 12:20:19 -07:00
1889e9b6cc dwebp: report -alpha option
remove from WEBP_EXPERIMENTAL_FEATURES block; alpha is no longer
experimental.

Change-Id: I57df006ecac8122a987e52084813dc84ca7bcfd6
2012-07-20 19:42:56 -07:00
3bc3f7c0ee Merge "dwebp: add PAM output support" into 0.2.0 2012-07-20 19:09:45 -07:00
d919ed06eb dwebp: add PAM output support
retains the alpha channel rather than stripping it as with PPM.

display from ImageMagick can render the files

Change-Id: I4f3a5d332937e0aeaf4e3fbd214fdae3b5382fb8
2012-07-20 19:06:01 -07:00
85e215d36f README/manpages/configure: update website link
code.google was moved to developers.google

Change-Id: I072cab38ccb6f45c3d1d6e533d1626420cdbba56
2012-07-20 16:25:04 -07:00
c3a207b9f4 Update ChangeLog
Change-Id: I7e8192f4c5fd90354669c492235b1348debdc839
2012-07-19 18:19:33 -07:00
d1fd78263f Merge "add extra precision about default values and behaviour" into 0.2.0 2012-07-19 18:15:45 -07:00
efc826e04a add extra precision about default values and behaviour
Change-Id: I445f4d3b20a53d32819fe361f74443e0a0c8a632
2012-07-19 18:08:42 -07:00
9f29635d95 header/doc clean up
Put emphasis on RGBA decoding instead of RGB/BGR
Clarify doc at some rough spots
Misc typo fix and cosmetics

Change-Id: Ic5fcfcc5bf4d612c5de23b0a5499f1fadde55bfe
2012-07-19 18:05:03 -07:00
ff9fd1bac6 Makefile.vc: fix webpmux.exe *-dynamic builds
the libwebpmux objects depend on the generated webp_dll.[hc] files as
well

Change-Id: I26177b56f415d69e4bc34b24d32c70a13c6c053c
2012-07-19 17:55:50 -07:00
8aacc7b056 remove INAM, ICOP, ... chunks from the test webp file.
Change-Id: Ia396d932b8b1af85717f693251c76985abc86395
2012-07-19 17:34:04 -07:00
2fc1301577 harmonize authors as "Name (mail@address)"
Change-Id: I85bfae61a37de75a5ed945a906002de2ef75149f
2012-07-19 16:09:47 -07:00
4a9f37b742 Merge "update NEWS" into 0.2.0 2012-07-19 14:44:06 -07:00
7415ae1386 makefile.unix: provide examples/webpmux target
this target is experimental so must be explicitly set

missing since:
e41a759 build: remove libwebpmux from default targets/config

Change-Id: I128d9e6a06ba3e7102ae3175dc3db52c6f4b1439
2012-07-19 14:39:26 -07:00
ce82cedc4b update NEWS
mention TIFF support, cwebp's alpha encoding disposition

Change-Id: I0340590f43e1617c6fb3fc2e98a609dbf4a880ce
2012-07-19 12:59:39 -07:00
641e28e8dc Merge "man/cwebp.1: wording, change the date" into 0.2.0 2012-07-19 12:58:13 -07:00
c37c23e594 README: cosmetics
- update swig function references
- remove references to decode_vp8.h (no longer installed)
- add lossless references
- some grammar/spelling changes

Change-Id: Icebfbcf6f638762f42d844b6bd3c0129c64d9340
2012-07-19 12:38:46 -07:00
3976dcd59f man/cwebp.1: wording, change the date
options were added since the last date refresh

Change-Id: I3899ebd429ba0260a28ce02bb973e1ee015c6e6e
2012-07-19 12:20:01 -07:00
3e5bbe1c2e Merge "rename 'use_argb_input' to 'use_argb'" into 0.2.0 2012-07-18 23:26:42 -07:00
ce90847a40 Merge "add some padding bytes areas for later use" into 0.2.0 2012-07-18 23:26:18 -07:00
2390dabcb6 Merge "fixing the findings by Frederic Kayser to the bitstream spec" into 0.2.0 2012-07-18 23:19:34 -07:00
0275159143 add a very crude progress report for lossless
better than nothing. Removed the warning in cwebp.c
(and silenced the warning in quiet mode too)

Change-Id: I85bbeaf77e0f60ead798886043dc053e6b44def5
2012-07-18 22:54:50 -07:00
a4b9b1c604 Remove some unused enum values.
- WEBP_MUX_INVALID_PARAMETER: was used only at one place, and that too
should actually be an assert().
- WEBP_MUX_ERROR: was never used.

Change-Id: I8883cb4dfae7a7918507501f21fced0c04dda36a
2012-07-19 11:23:37 +05:30
dd1081763c rename 'use_argb_input' to 'use_argb'
long name, and there's not really an 'output' equivalent

Change-Id: I9133ff734ae8d6572cb2f607211361f011fc0bc1
2012-07-18 22:47:16 -07:00
90516ae8f5 add some padding bytes areas for later use
so we can add few fields without breaking ABI

+ re-order fields
+ refresh the doc

Change-Id: Id60ec33934f6346e35c95fcdb4abbe1bc7b50acb
2012-07-18 22:47:13 -07:00
d03b250369 fixing the findings by Frederic Kayser to the bitstream spec
Change-Id: I4bcc428412dd4c21675d90159771e2e0b338ecf3
2012-07-18 22:47:11 -07:00
ce156afccf add missing ABI compatibility checks
original change:
f7f16a2 add ABI compatibility check

Change-Id: I7cd6508f8d8e0d957a3d62ad52a117876fa5ec29
2012-07-18 22:24:33 -07:00
9d45416aa7 Merge "Doc: container spec text tweaks" into 0.2.0 2012-07-18 21:49:24 -07:00
4e2e0a8cac Doc: container spec text tweaks
Change-Id: I8e29f1c814b0c8f6aa268562d8653989caaf281d
modified:   doc/webp-container-spec.txt
2012-07-18 16:38:50 -07:00
f7f16a2976 add ABI compatibility check
minor revision shouldn't matter, we only check major revision number.
Bumped all version numbers so that incompatibility starts *now*

Change-Id: Id06c20f03039845ae4cfb3fd121807b931d67ee4
2012-07-18 11:53:25 -07:00
2a77557002 Merge "swig: add WebPEncodeLossless* wrappers" into 0.2.0 2012-07-17 17:30:17 -07:00
a3ec6225d5 mux.h: remove '* const' from function parameters
makes the public interface consistent and more readable

Change-Id: I33f1d1c4ee752e353e4c10636a4df4e44d7cd03f
2012-07-17 17:21:54 -07:00
31426ebaec encode.h: remove '* const' from function parameters
makes the public interface consistent and more readable

Change-Id: Ib93614e901e0af44bb64782357cfd9e724e050be
2012-07-17 16:26:54 -07:00
9838e5d5ff decode.h: remove '* const' from function parameters
makes the public interface consistent and more readable

Change-Id: I067eb5ecc1094216ef6aecc65f636f69873de8f9
2012-07-17 15:48:00 -07:00
4972302d24 swig: add WebPEncodeLossless* wrappers
Change-Id: If373a5d2953ec53b856900666422fb2b4f9939a4
2012-07-17 14:41:51 -07:00
9ff00cae72 bump encoder/decoder versions
those returned by WebPGet(Encoder|Decoder)Version()

Change-Id: I7584d04060ae7ca552f8f3aaf9df294d310a5be6
2012-07-17 13:43:39 -07:00
c2416c9b61 add lossless quick encoding functions to the public API
New functions:
   WebPEncodeLosslessRGB()
   WebPEncodeLosslessBGR()
   WebPEncodeLosslessRGBA()
   WebPEncodeLosslessBGRA()

Change-Id: Id56da7569eee80c57de8f1f053fb87b217d33a4b
2012-07-17 12:02:53 -07:00
4c1f5d6435 Merge "NEWS: mention decode_vp8.h is no longer installed" into 0.2.0 2012-07-17 11:20:55 -07:00
6cb2277d0f NEWS: mention decode_vp8.h is no longer installed
Change-Id: Id1075b4a917c83552446fb62dada8868dbdb21ef
2012-07-17 11:19:42 -07:00
d5e5ad6356 move decode_vp8.h from webp/ to dec/
the functions contained in it are now private

Change-Id: Ief6c81b32ae3f6d97052edac625716e5b909e66e
2012-07-16 22:12:59 -07:00
8d3b04a25d Merge "header clean-up" into 0.2.0 2012-07-16 19:21:49 -07:00
02201c35a0 Merge "remove one malloc() by making color_cache non dynamic" into 0.2.0 2012-07-16 19:21:05 -07:00
d708ec1452 Merge "move MIN/MAX_HISTO_BITS to format_constants.h" into 0.2.0 2012-07-16 19:19:32 -07:00
ab2da3e9fd Merge "add a malloc() check" into 0.2.0 2012-07-16 19:18:28 -07:00
2d571bd89f add a malloc() check
mostly a sanity measure to be future-proof

Change-Id: I55a81345819b2a8e939c98f0da883dc5c0cc16a2
2012-07-16 19:15:00 -07:00
7f0c178e46 remove one malloc() by making color_cache non dynamic
Change-Id: I7c71a056f79a79bfacfe64a263f1eb8476c05456
2012-07-16 19:13:58 -07:00
6569cd7c88 Merge "VP8LFillBitWindow: use 64-bit path for msvc x64 builds" into 0.2.0 2012-07-16 19:13:30 -07:00
23d34f3142 header clean-up
remove unused VP8LHistogramRemove function
make HistogramEstimateBitsHeader static

Change-Id: I0dc6a6f4c41d3c5f55a8153cd7d710c9f84582a7
2012-07-16 19:13:01 -07:00
2a3ab6f925 move MIN/MAX_HISTO_BITS to format_constants.h
(under the name MAX_HUFFMAN_BITS, since the specs read:
	int huffman_bits = ReadBits(3) + 2;
)

Change-Id: Ifc66576bbd8e48518d3d78a3f515f851cf1883dc
2012-07-16 19:11:54 -07:00
985d3da6c4 Merge "shuffle variables in HashChainFindCopy" into 0.2.0 2012-07-16 19:11:00 -07:00
cdf885c67c shuffle variables in HashChainFindCopy
might lead to observable speed-up on some compiler/arch

Change-Id: I6c89ec9cd4f490e7e22b790785f80097a47d27b5
2012-07-16 19:08:59 -07:00
c3b014db28 Android.mk: add missing lossless files
Change-Id: I5d97e22392ed3847e97f3b31c928d3828fa6732a
2012-07-16 18:43:07 -07:00
8c1cc6b5dc makefile.unix dist: explicitly name installed includes
avoids mux.h, format_constants.h

Change-Id: I6c8458dd1ce7faa23fbf1e3df84a8dfc4a884a3e
2012-07-16 16:32:15 -07:00
7f4647eecb Merge "clarify the colorspace naming and byte ordering of decoded samples" into 0.2.0 2012-07-16 12:16:17 -07:00
cbf69724d2 clarify the colorspace naming and byte ordering of decoded samples
Change-Id: If5ac331bd1e45e7c959b5fa60248268ae2bbe861
2012-07-16 12:09:51 -07:00
857650c8fc Mux: Add WebPDataInit() and remove WebPImageInfo
Change-Id: If661f7d198e284a103a53a451e9f74805119fcf9
2012-07-16 11:12:05 +05:30
ff771e7705 don't install webp/decode_vp8.h
the VP8 decode functions do not need to be public; only
GetInfo/CheckSignature need to be marked extern as they're used by
libwebpmux.

Change-Id: Id9ab4d6166b0271cf5d04563c6dac1fcc84adbdc
2012-07-14 21:23:03 -07:00
596dff784d VP8LFillBitWindow: use 64-bit path for msvc x64 builds
Change-Id: I14a3865f4091dd048e02abc99aa4e7f1e325e12a
2012-07-14 13:20:26 -07:00
3ca7ce9805 Merge "doc: remove non-finalized chunk references" into 0.2.0 2012-07-14 10:58:52 -07:00
1efaa5a369 Merge "bump versions" into 0.2.0 2012-07-14 10:57:58 -07:00
51fa13e170 Merge "README: update cwebp help output" into 0.2.0 2012-07-14 09:29:19 -07:00
12f9aede7e README: update cwebp help output
Change-Id: Ifc2fafca8131e53a894056e37bb22d25fedfa150
2012-07-13 14:55:39 -07:00
f0b5defb0a bump versions
lib - 0.1.99
libtool - 3.0.0 (interface changes)

Change-Id: Id52f8b8df5b941b15af6cb54b1cc05daf322179f
2012-07-13 14:07:51 -07:00
4c42a61b9a update AUTHORS
Change-Id: Ibf5b8c6aa101e6dd6cbcb69485ae582364387d80
2012-07-13 13:55:31 -07:00
6431a1ce3d doc: remove non-finalized chunk references
tiles, animation, etc.

Change-Id: Ie83135be576f516fe475c7be21171f9d12a17ce4
2012-07-13 12:33:49 -07:00
8130c4cc64 Merge "build: remove libwebpmux from default targets/config" 2012-07-13 11:33:52 -07:00
23b44438dd Merge "configure: broaden test for libpng-config" 2012-07-13 11:13:26 -07:00
85bff2cdbe Merge "doc: correct lossless prefix coding table & code" 2012-07-13 11:12:14 -07:00
05108f6ea0 Merge "More spec/code matching in mux:" 2012-07-12 23:53:58 -07:00
6808e69db8 More spec/code matching in mux:
- Match offsets, duration, width/height for frames/tiles and enforce
some constraints.
- Note that this also means using 'int's instead of 'uint32_t's for
16-bit and 24-bit fields.

Change-Id: If0b229ad9fce296372d961104aa36731a3b1304b
2012-07-13 11:47:24 +05:30
bd2b46f5f2 Merge "doc/webp-container-spec: light cosmetics" 2012-07-12 21:04:27 -07:00
20ead3290f doc/webp-container-spec: light cosmetics
- provide anchor links to the bitstream chunks referenced in the
  extended format section
- remove some unnecessary parenthetical notation and add some
  consistency to various chunk element definitions

Change-Id: Ifd946fee81b36e4e555399555a2a58c853fdc3b7
2012-07-12 19:19:39 -07:00
1d40a8bce8 configure: add pthread detection
adds a --disable-threading option to prevent the check.
uses AX_PTHREAD from:
git://git.savannah.gnu.org/autoconf-archive.git
100644 blob d90de34d14    ax_pthread.m4

Change-Id: Icf3ad1ebcf052748bc341706effcc9ba02a259e4
2012-07-12 16:27:29 -07:00
b5e9067a28 fix some int <-> size_t mix for buffer sizes
could have led to some negative overflow on 32bit arch
(if it was not for the "total_size == (size_t)total_size" test)

Change-Id: I7640340b605b9c674d30dd58a1e2144707299683
2012-07-12 07:23:01 -07:00
e41a759615 build: remove libwebpmux from default targets/config
the extended file format is still under development and related
libs/binaries are not fit for release

configure:
--enable/disable-libwebpmux; default is disabled.

makefile.unix:
src/mux/libwebpmux.a and examples/webpmux must be explicitly specified

Makefile.vc:
$(DIRLIB)\libwebpmux.lib and $(DIRBIN)\webpmux.exe must be explicitly
specified

Change-Id: I8246746b256010dd2a2e4de58291222d7eaf0457
2012-07-11 14:25:41 -07:00
0fc2baae5c configure: broaden test for libpng-config
some versions of cygwin's libpng-devel only install libpngXX-config,
e.g., libpng12-config, but do not create libpng-config. the library also
has a version number.

Change-Id: I35332b7011e2dbabb95b599f810523a729d6097e
2012-07-11 14:21:50 -07:00
45b8272c31 Merge "restore authorship to lossless bitstream doc" 2012-07-11 13:56:10 -07:00
06ba05909e restore authorship to lossless bitstream doc
lost in port from pdf

Change-Id: I17bad348577be9818c036e557a0beba63ffcc689
2012-07-11 13:46:00 -07:00
44a09a3ccd add missing description of the alpha filtering methods
Change-Id: Id7bdf5e30121ce5d610b7fa00f64bcd2d7bed2bf
2012-07-10 19:50:30 -07:00
63db87dd2a Merge "vwebp: add checkboard background for alpha display" 2012-07-10 12:38:16 -07:00
a73b8978d1 vwebp: add checkboard background for alpha display
Change-Id: Iefb02f38c0479e61334844d9110cd1b735f0395d
2012-07-10 12:02:03 -07:00
939158ce4f Merge "vwebp: fix info display" 2012-07-10 07:37:28 -07:00
b35c07d9a7 vwebp: fix info display
change alpha intensity to 1 from 0; broken since alpha blending was enabled.

Change-Id: Ic8bb73b62e602ae56e08e9d5a77fdc6aa76b54c5
2012-07-09 22:47:10 -07:00
48b39eb17a fix underflow for very short bitstreams
+ hardened the asserts

Change-Id: Ie798ef2f9d848c131f6f84a35ea28ef254822d1e
2012-07-09 16:47:34 -07:00
7e622984bb cosmetics: param alignment, manpage wording
after eb6f9b8, c0e8859

Change-Id: I79bcea77d65eb6d1abf1156796996f3b9909b62b
2012-07-07 10:37:26 -07:00
1bd7dd5097 Merge changes I7b0afb0d,I7ecc9708
* changes:
  Get rid of image_info_ from WebPChunk struct.
  WebP Container Spec:
2012-07-04 16:32:29 -07:00
ac69e63eeb Merge "Updated cwebp man's help for Alpha & Lossless." 2012-07-04 16:30:03 -07:00
c0e8859d81 Get rid of image_info_ from WebPChunk struct.
The image_info_ was used only in GetImageCanvasWidthHeight(). So, now
we infer it from data there.
This removal fixes a bug: earlier, 'image_info' wasn't initialized in
the WebPMuxCreate() flow, and so the canvas width/height were being
calculated to be zero.

Also, a related refactoring: Combine CreateImageInfo() and
CreateDataFromImageInfo() into a single function CreateFrameTileData().

Change-Id: I7b0afb0d36dc6e13b9d6a1135fb027aa4e03716c
2012-07-04 18:49:56 +05:30
135ca69eb7 WebP Container Spec:
Clarify that a file must contain at least one frame.

Change-Id: I7ecc97084498adc108275585d0c7d0aaa9f5c6ed
2012-07-04 17:28:17 +05:30
eb6f9b8a72 Updated cwebp man's help for Alpha & Lossless.
Change-Id: Iaa129685fdbd95c3b408c92c77532b321bc2637f
2012-07-04 12:51:56 +05:30
0fa844fb8f cosmetic fixes on assert and 'const' where applicable
Change-Id: Iede15b8464be453e7d12929513ed82183921265c
2012-07-03 05:50:36 -07:00
7f22bd2596 check limit of width * height is 32 bits
Update the RIFF-specs file too

Change-Id: I113a7e25da2f7a19c1344c1dc5d496127cfe2596
2012-07-03 05:42:13 -07:00
16c46e83ac autoconf/make: cosmetics: break long lines
Change-Id: If08350a27cdfc4371dcb28ecb9d88d05eceaf977
2012-07-02 21:48:18 -07:00
ab22a07afc configure: add helper macro to define --with-*
replaces repeated --with-{jpeg,png,tiff}{include,lib}dir defines

Change-Id: Ic0eb8622dfc94184ab74f8302112c36547a34664
2012-07-02 21:26:48 -07:00
c17699b343 configure: add libtiff test
Change-Id: Ia5828797bae9c993a3d00ddd5e0089d3b828e975
2012-07-02 18:01:49 -07:00
0e09732c5e Merge "cwebp: fix crash with yuv input + lossless" 2012-07-02 14:40:00 -07:00
88a510ff53 Merge "fix big-endian VP8LWriteBits" 2012-07-02 14:38:32 -07:00
da99e3bfcd Merge "Makefile.vc: split mux into separate lib" 2012-07-02 14:36:17 -07:00
7bda392b50 cwebp: fix crash with yuv input + lossless
Change-Id: Ia27c925f532a4243369288e954abdc063b9f94f9
2012-07-02 14:33:25 -07:00
f56a369ab0 fix big-endian VP8LWriteBits
bits would be lost if n_bits was > 17

Change-Id: Id315d075075338a08e10c04faa91cab347a53591
2012-07-02 14:30:41 -07:00
54169d6cd7 Merge "cwebp: name InputFileFormat members consistently" 2012-07-02 13:19:27 -07:00
e2feefa9b8 Makefile.vc: split mux into separate lib
similar to other builds, reusing some variable naming from
makefile.unix.
also change the main output file names to libwebp{,mux}.{lib,dll} with
the import lib retaining the _dll suffix.

Change-Id: I6bbc4fb39ab37957f153e9f31954387b24094581
2012-07-02 12:37:57 -07:00
27caa5aa34 Merge "cwebp: add basic TIFF support" 2012-07-02 11:39:21 -07:00
d8921dd4e6 cwebp: name InputFileFormat members consistently
append an '_'. TIFF introduced TIFF_ to avoid a name clash.

Change-Id: Iebe484d43aeb8e1912cd5bd10d36e1c5e66a4b42
2012-07-02 11:24:23 -07:00
6f76d246ba cwebp: add basic TIFF support
Change-Id: I29f354e1ef9cf8f23002cf2e15814a53a94b4ed5
2012-07-02 11:22:52 -07:00
4691407bb3 Merge changes If39ab7f5,I3658b5ae
* changes:
  WebPMuxCreate() error handling:
  Fix a memleak in WebPMuxCreate()
2012-07-02 01:46:17 -07:00
cca7c7b81b Fixed nit: 10 -> 10.f
Change-Id: I0cdb096525460b27f3adcb9f802f6dc193d5f590
2012-07-02 11:29:01 +05:30
5d09a244b7 WebPMuxCreate() error handling:
Directly return NULL if no allocation is done yet.

Change-Id: If39ab7f5a55833263d3372fa0a5d9b0a600cb9ed
2012-07-02 11:20:09 +05:30
777341c3d0 Fix a memleak in WebPMuxCreate()
Change-Id: I3658b5ae487082aef28989eb8abc274c207fef0f
2012-07-02 10:19:21 +05:30
61c9d161d5 doc: correct lossless prefix coding table & code
extra bit counts and literal distance return value

Change-Id: I290e3ee8900469503a323f87e9dbb8ca5cb4afc7
2012-07-01 14:10:32 -07:00
4c3975792b Merge "mark VP8{,L}{GetInfo,CheckSignature} as WEBP_EXTERN" 2012-06-29 10:31:26 -07:00
e4e36cc6c6 Merge "Mux: Allow only some frames/tiles to have alpha." 2012-06-29 05:17:26 -07:00
ad2aad3c21 Merge "WebP Decoding error handling:" 2012-06-29 05:15:55 -07:00
97649c8f6b Mux: Allow only some frames/tiles to have alpha.
And related const fixes.

Change-Id: I79f6f1b9f8c6faac8cc4ef24b58edff6d90de045
2012-06-29 17:17:19 +05:30
f864be3b2c Lower the quality settings for Alpha encoding.
Evaluated the impact of this change over 1000 image corpus.
The compression density is up (on average) by 1.2% and encoding time has
gone down considerably from 716 ms (per file) to 146 ms (per file)
(4.9X improvement in encoding time).

Change-Id: Ida562cc0bfe18c9d6f5f00873c95f8396b480eab
2012-06-29 16:19:42 +05:30
3ba81bbe8b WebP Decoding error handling:
- Don't allow any extended chunks (except ALPH) without RIFF & VP8X
chunks.
- Also, don't allow VP8X without RIFF.

Change-Id: I1beba43e617ec637901aeeb93f2f484ec086a75d
2012-06-29 14:32:21 +05:30
fcc69923b9 add automatic YUVA/ARGB conversion during WebPEncode()
Adds new methods WebPPictureARGBToYUVA() and WebPPictureYUVAToARGB()
Depending on the value of picture->use_argb_input,
the main call WebPEncode() will convert appropriately.
Note that both conversions are lossy, so it's recommended to:
* use YUVA input for lossy compression (picture->use_argb_input=0)
* use ARGB input for lossless compression (picture->use_argb_input=1)

Change-Id: I8269d607723ee8a1136b9f4999f7ff4e657bbb04
2012-06-28 00:34:23 -07:00
802e012a18 fix compilation in non-FANCY_UPSAMPLING mode
Change-Id: Id0b1fad3a4888b6e9563a227412b2e6a656d9a2a
2012-06-28 00:26:35 -07:00
e012dfd90f make width/height coding match the spec
* width/height in VP8X chunk is 24bit now
* Added some more constants #defines

Change-Id: I2f8ca7f965a247bccd341dd079ed2abf549c39d7
2012-06-28 00:20:28 -07:00
228d96a538 mark VP8{,L}{GetInfo,CheckSignature} as WEBP_EXTERN
these functions are used by libwebpmux

Change-Id: Ifcb79e685f3a6b53007c0dc5f220737daba97d47
2012-06-27 16:07:33 -07:00
637a314f97 remove the now unused *KeepA variants
Change-Id: I65217f3075e30bc9a7f38a49d09f01c9d7271d6a
2012-06-27 10:00:48 -07:00
d11f6fcc82 webpmux returns error strings rather than numbers
Change-Id: Ifc8d8aaf0f6c03ecb1508ec7fbc34c918bf69c61
2012-06-27 16:55:57 +05:30
fcec059322 makefile.unix: cwebp: fix OSX link
this is more a workaround than a fix. this change forces the tables
from yuv.h into the data section rather than generating them as common
blocks. prior to this the linkage would fail with e.g.,

Undefined symbols:
...
  "_VP8kClip4Bits", referenced from:
      _Yuv444ToRgba4444 in libwebp.a(libwebpdsp_la-upsampling.o)

broken since:
 48f8275 add colorspace for premultiplied alpha

Change-Id: I69c36758c31cd3a4b3ea5c412674d1a47b45447e
2012-06-26 18:09:55 -07:00
6b811f1b06 Merge "doc: remove lossless pdf" 2012-06-22 15:43:20 -07:00
c963482124 doc: remove lossless pdf
superseded by webp-lossless-bitstream-spec.txt

Change-Id: I5f233d4c3c2fa048a180db950ad4319ffdb9bced
2012-06-22 15:25:03 -07:00
b9ae4f0d88 cosmetics after mux changes b74ed6e, b494ad5
Change-Id: I8f693b1ba2537de89bda1dfbcf3b95abd17e420a
2012-06-22 14:30:01 -07:00
b494ad5096 Mux: only allow adding frame/tiles at the end.
Change-Id: I5d685628da8c8ac85144cee2e5808b30ec79fef9
2012-06-22 11:18:18 -07:00
2c341b0eed Merge "Added image characteristic hint for the codec." 2012-06-22 02:54:51 -07:00
d373076a53 Added image characteristic hint for the codec.
This image type hint is used by codec to apply appropriate set of
transform filters to the image.

Change-Id: Ibb24e47ba14c40fa7f9f2c50ae86e03f2b29e9a6
2012-06-22 14:03:46 +05:30
2ed2adb5ba Merge "msvc: add intrinsic based BitsLog2Floor" 2012-06-22 00:13:47 -07:00
e595e7c552 Merge "add demux.c to the makefiles" 2012-06-21 23:44:44 -07:00
da47b5bda7 Merge "demux: add {Next,Prev}Chunk" 2012-06-21 23:43:03 -07:00
e5f467420d add demux.c to the makefiles
Change-Id: If98c0ea859c845261218196df35e905589f09e76
2012-06-21 23:21:41 -07:00
4708393c3b demux: add {Next,Prev}Chunk
replaces WebPDemuxSetChunk(). makes this consistent with the Frame
interface.

Change-Id: Ia2b1b98cc290f35b41fd14ee35a2a17cecac7ba8
2012-06-21 23:18:39 -07:00
e8a0a821d2 demux: quiet msvc warnings
min_size is safe to be a uint32_t so avoid the size_t -> uint32_t
conversion

Change-Id: Ib53fe58d313b55dfcf3bee35d0cad48f210d07bf
2012-06-21 23:09:38 -07:00
7f8472a610 Update the WebP Container Spec.
- Add details about the VP8L chunk support.
- Also add new example bitsteams containing VP8L chunk.
- Add back a section describing the VP8 chunk.
- Restrict some fields to 16 or 24 bits instead of 32 bits.
- Fields whose values are always positive are stored 1-based
instead of 0-based.
- Unknown chunks can only occur at certain places in the file.
- Remove the restriction for some fields to be divisible by 32 or 16.
  Instead they are restricted to be even.
- Add a restriction for (canvas_width * canvas_height) product.
- Add 3 bits for rotation & symmetry in VP8X flags.
- Add some new example layouts.
- Add/clarify some nitty-gritties throughout the doc.
- Use the terms frame/tile more consistently and logically.
- Update related TODOs.

Change-Id: I611c1f58ecc3ee87546ca31bad1609376fad251e
2012-06-21 16:04:58 -07:00
31b68fe639 cleanup WebPPicture struct and API
* add a real proper pointer for holding memory chunk pointer
  (instead of using y and argb fields)
* polish the doc with details
* add a WebPPictureView() that extract a view from a picture
  without any copy (kind of a fast-crop).
* properly snap the top-left corner for Crop/View. Previously,
  the luma position was not snapped, and was off compared to the chroma.

Change-Id: I8a3620c7f5fc6f7d1f8dd89d9da167c91e237439
2012-06-21 00:30:43 -07:00
9144a18643 add overflow check before calling malloc()
It's preferable to be over-strict and paranoid here.

Change-Id: Ia928b279b753fa8f836d17decb17a35e6dc441b3
2012-06-20 23:58:43 -07:00
81720c9139 consistency cosmetics
Change-Id: Ie8e372ddcdd6e48527478f70bf716953ed18292a
2012-06-20 23:56:11 -07:00
2ebe8394f8 Merge "Add kramdown version information to README" 2012-06-20 16:02:03 -07:00
7144308402 enc/vp8l.c: fix build
broken since:
233a589 take picture->argb_stride into account for lossless coding

Change-Id: I9ecbbf65f3048be3077d28c3a20dfc0e1afa10be
2012-06-20 14:44:39 -07:00
b7ac19fec9 Add kramdown version information to README
Example kramdown command line to apply syntax highlighting requires
kramdown latest. Command is slightly different for earlier versions.

modified:   doc/README

Change-Id: Icda1197436b5c5ed936ceff53c1dc51aa4ce409b
2012-06-20 14:17:36 -07:00
efdcb6670c Merge "Edit for consistency, usage and grammar." 2012-06-20 14:01:13 -07:00
08220102d1 Enable alpha in vvwebp
Change-Id: I9499b6d4ea64b7eab18cb377f0bb09b6b494c534
2012-06-20 11:20:48 -07:00
8de9a0847b Merge "Mux API change:" 2012-06-20 11:11:49 -07:00
b74ed6e766 Mux API change:
'Set' and 'Get' methods for images take/return a bitstream as input,
instead of separate 'image' and 'alpha' arguments.

Also,
- Make WebPDataCopy() a public API
- Use WebPData for storing data in WebPChunk.
- Fix a potential memleak.

Change-Id: I4bf5ee6b39971384cb124b5b43921c27e9aabf3e
2012-06-20 11:00:42 -07:00
233a589ea9 take picture->argb_stride into account for lossless coding
analysis phase was assuming flat layout...

Change-Id: I96681f6d76aa3faabc51dd2ee3dffbe77ff90d36
2012-06-20 10:13:04 -07:00
04e33f17de Edit for consistency, usage and grammar.
Substantial edit, though less than 100% thorough.  This
makes changes that are clearly safe, but avoids others
where my domain knowledge is incomplete and accuracy
might be compromised.

modified:   doc/webp-lossless-bitstream-spec.txt

Change-Id: I89361a2e1157b8d2e44a8b4f4603f65833f0c1e6
2012-06-20 10:08:53 -07:00
a575b4bc15 Merge "cosmetics: add missing const" 2012-06-19 22:34:28 -07:00
8d99b0f4bd Merge "cosmetics: remove unimplemented function proto" 2012-06-19 22:33:54 -07:00
69d022176d cosmetics: add missing const
Change-Id: I0c0e89bbe826961b02a40ada5a6f89e02abee378
2012-06-19 22:28:34 -07:00
5b08318b57 cosmetics: remove unimplemented function proto
Change-Id: I580fcc756d161cebbabf753ee68c09d189628d7f
2012-06-19 22:27:56 -07:00
b7fb0ed567 Log warning for unsupported options for lossless.
Change-Id: I30d4e775959c7a4a8f5b649c8c90a4edb8cced47
2012-06-20 10:51:50 +05:30
e1f769fe1c msvc: add intrinsic based BitsLog2Floor
Change-Id: Ic0c7d2f03e300c6699e130916a759403e672f9d8
2012-06-19 16:14:54 -07:00
8a69c7d8af Bug-fix: Clamp backward dist to 1.
Check for valid bounds on the 'dist' in backward reference case.
Clamp it to 1 in case of zero and negative values.

Change-Id: I78e956d4595955efa02b1f9628b475093f6ee001
2012-06-19 16:44:03 +05:30
b5b6ac979f Merge "Bring the special writer 'WebPMemoryWriter' to public API" 2012-06-18 16:22:17 -07:00
a6a1909fff Merge "Fix floating point exception with cwebp -progress" 2012-06-18 16:11:53 -07:00
f2cee06708 Fix floating point exception with cwebp -progress
Adds a test of enc->mb_h_ to VP8IteratorProgress() to avoid a division
by zero. Fixes issue #121.

Original patch from even rouault (even dot rouault at gmail dot com).

Change-Id: Ie5fcc1821860c0a9366d5aa11f3aded4f5b98ed7
2012-06-18 15:43:28 -07:00
91b7a8c754 Bring the special writer 'WebPMemoryWriter' to public API
=> WebPMemoryWriter, WebPMemoryWriterInit(), WebPMemoryWrite()

Change-Id: I142fb22b0290ece7a6f6d74f00964a2e9e58ec9b
2012-06-18 15:42:56 -07:00
310e297205 support resize and crop for RGBA input
Change-Id: I19eac3fb4f8ecb973ff5872ac3a921f8947054bf
2012-06-18 15:20:46 -07:00
a89835d33a Merge changes Ice662960,Ie8d7aa90,I2d996d5e,I01c04772
* changes:
  Manually number "chapters," as chapter numbers are used in the narrative.
  Re-wrap at <= 72 columns
  Apply inline emphasis and monospacing, per gdoc / PDF
  Incorporate gdoc changes through 2012-06-08
2012-06-18 14:19:58 -07:00
ce614c0caf Merge "dec/vp8: avoid setting decoder status twice" 2012-06-18 14:12:21 -07:00
900285dac3 dec/vp8: avoid setting decoder status twice
Has the potential of returning confusing USER_ABORT for bitstream errors
in some cases.

Change-Id: I358fdb0b36549179df6dc2a95c09a872bd35aa24
2012-06-18 14:10:01 -07:00
8227adc878 Merge changes I6f02b0d0,I5cbc9c0a,I9dd9d4ed,Id684d2a1
* changes:
  Removed CodeRay syntax declarations ...
  Provide for code-block syntax highlighting.
  Replace high ASCII artifacts (curly quotes, etc.).
  Lossless WebP doc largely ported to markdown text.
2012-06-18 13:55:21 -07:00
dcda59c12d Merge "demux: rename SetTile to SelectTile" 2012-06-18 13:50:45 -07:00
622ef12ea5 demux: rename SetTile to SelectTile
Change-Id: I52b0b30578aeb77b71069f355c6b00901b948634
2012-06-18 13:49:41 -07:00
81ebd37505 Merge "demux: add {Next,Prev}Frame" 2012-06-18 13:41:42 -07:00
02dd37a2a3 demux: add {Next,Prev}Frame
Replaces WebPDemuxSetFrame().

Change-Id: I38cef0ebeabb5c2f164322502abe1780f7a65e06
2012-06-18 13:37:16 -07:00
4b79fa5923 Merge "Limit the maximum size of huffman Image to 16MB." 2012-06-17 00:20:26 -07:00
9aa34b3438 Manually number "chapters," as chapter numbers are used in the narrative.
modified:   doc/webp-lossless-bitstream-spec.txt

Change-Id: Ice662960ff988a6ff577a8ca5a594e14ba69d4de
2012-06-15 14:54:19 -07:00
2a4c6c29a0 Re-wrap at <= 72 columns
modified:   doc/webp-lossless-bitstream-spec.txt

Change-Id: Ie8d7aa907dc20d941b74455f8657d4e1b4e23bbb
2012-06-15 14:54:13 -07:00
a45adc1918 Apply inline emphasis and monospacing, per gdoc / PDF
modified:   doc/webp-lossless-bitstream-spec.txt

Change-Id: I2d996d5e80967641e22997d4f6e7173b39df0978
2012-06-15 14:54:06 -07:00
91011206ad Incorporate gdoc changes through 2012-06-08
modified:   doc/webp-lossless-bitstream-spec.txt

Change-Id: I01c04772bff7e3d7d6f0b526949cd846b5a97c8d
2012-06-15 14:53:55 -07:00
7a18248716 Removed CodeRay syntax declarations ...
... as they became unnecessary when upstream (kramdown)
implemented LQ feature request:
17625c8082

Also updated (and simplified) syntax-highlighting instructions.

modified:   doc/README
modified:   doc/webp-lossless-bitstream-spec.txt
Change-Id: I6f02b0d0a69a4d1d96cb0f771936cbe9e2e6bbec
2012-06-15 14:53:39 -07:00
b3ec18c556 Provide for code-block syntax highlighting.
modified:   doc/README
modified:   doc/webp-lossless-bitstream-spec.txt

Change-Id: I5cbc9c0a4fbbcc049a4d792e1fac367d28acf4a6
2012-06-15 14:53:29 -07:00
709d770241 Replace high ASCII artifacts (curly quotes, etc.).
modified:   doc/webp-lossless-bitstream-spec.txt
Change-Id: I9dd9d4ed05c8f93d4cafadf8c99cc21c300a9299
2012-06-15 14:53:16 -07:00
930e8abbda Lossless WebP doc largely ported to markdown text.
Word-level formatting (italics, bold) remains to be done,
but awaits final author edits, to avoid rework.

modified:   doc/template.html
new file:   doc/webp-lossless-bitstream-spec.txt

Change-Id: Id684d2a10d02e197d660a960540fe83f87d317f2
2012-06-15 14:52:57 -07:00
18cae37b91 msvc: silence some build warnings
these are related to the removal of USE_LOSSLESS_ENCODER

Change-Id: Ib0ca5bc2766c351130507bc2e657a034c8455b34
2012-06-13 13:51:50 -07:00
b3923084b9 Limit the maximum size of huffman Image to 16MB.
This limit corresponds to default histo_bits=3 for images upto sizes 400x400.
Any image higher than this dimension will bump up the histo_bits to 4 internally.

Change-Id: Ic8ba3dcd50e9c588cbbc4a0457289086498ff4ee
2012-06-13 13:27:43 +05:30
f180df2afd Merge "libwebp/demux: add Frame/Chunk iteration" 2012-06-13 00:29:29 -07:00
2bbe1c9aa0 Merge "Enable lossless encoder code" 2012-06-13 00:28:42 -07:00
d0601b0107 Merge changes I1d97a633,I81c59093
* changes:
  libwebp/demux: add WebPDemuxGetI
  libwebp/demux: add extended format parsing
2012-06-13 00:28:25 -07:00
78f3e34504 Enable lossless encoder code
Remove USE_LOSSLESS_ENCODER compile flag
Update Makefile.am and makefile.unix

Change-Id: If7080c4d8f37994c7c784730c5e547bb0a851455
2012-06-13 00:26:58 -07:00
d974a9cc15 Merge "libwebp/demux: add simple format parsing" 2012-06-13 00:03:37 -07:00
26bf223280 Merge "libwebp: add WebPDemux stub functions" 2012-06-12 23:57:18 -07:00
2f66668882 Merge "modify WebPParseHeaders to allow reuse by GetFeatures" 2012-06-12 23:51:55 -07:00
b402b1fbb9 libwebp/demux: add Frame/Chunk iteration
Change-Id: I2da68611b375de48391adcf446df31a93450c7d8
2012-06-12 23:45:11 -07:00
ad9ada3b9f libwebp/demux: add WebPDemuxGetI
Enables queries for format flag, canvas width/height.

Change-Id: I1d97a633712141e42dfc86c95492eb6da5cefa01
2012-06-12 23:45:10 -07:00
2f2d4d5889 libwebp/demux: add extended format parsing
Extends parser to support 'VP8X' and its components

Change-Id: I81c59093b02c7ad27810a7b0473129ea06f99952
2012-06-12 23:45:08 -07:00
962dcef6a8 libwebp/demux: add simple format parsing
Adds image parsing / validation framework for 'VP8 '/'VP8L' files

Change-Id: I8b0a5d1f20d86ab137c881a01dba3275ea191aa4
2012-06-12 23:45:06 -07:00
f8f94081be libwebp: add WebPDemux stub functions
beginning of a separate interface to demux webp files.

Change-Id: If8bf9c43defe5f6c8678afd03541f7cd8261c99a
2012-06-12 23:45:02 -07:00
fb47bb5cf4 Merge "NumNamedElements() should take an enum param." 2012-06-11 00:23:39 -07:00
7c6898051e Fix asserts in Palette and BackwardReference code.
Fix inequality assertion on number of palette colors.
Fix inequality assertion test in BackwardReferencesHashChainFollowChosenPath.

Change-Id: Ie3242f1bbeaf96db91b839b6732ccce2634cebf3
2012-06-11 12:27:59 +05:30
fbdcb7ea38 NumNamedElements() should take an enum param.
- Move TAG_ID to webp/mux.h
- Rename it to WebPChunkId
- Rename IDs to WEBP_CHUNK_<tag>
- Remove "name" param from ChunkInfo struct and related changes.
- Rename WebPMuxNumNamedElements to WebPMuxNumChunks().
- WebPMuxNumChunks() takes WebPChunkId as param.

Change-Id: Ic6546e4a9ab823b556cdbc600faa137076546a2b
2012-06-11 12:26:13 +05:30
fb4943bdf9 modify WebPParseHeaders to allow reuse by GetFeatures
moves the implementation to ParseHeadersInternal. this also allows
decoding to start at a VP8X sub-chunk, e.g. 'ALPH'.

Change-Id: I06791f87d90f888de32746ecb02705e4b0ff227a
2012-06-08 14:55:14 -07:00
3697b5ceb2 write an ad-hoc EncodeImageInternal variant
Used when we don't code a Huffman Image.
-> Simplify the code quite some because we don't have to
deal with special cases of histo bits

Change-Id: I0c3f46cbf3b501e021c093e07253e7404c01ff4f
2012-06-08 11:52:31 -07:00
eaee9e79f7 Bug-Fix: Decode small (less than 32 bytes) images.
ParseVP8X was checking for presence of extra 20 bytes (after RIFF header).
This check should not be executed for non-mux (non-VP8X) images.

Change-Id: I3fc89fa098ac0a53102e7bbf6c291269817c8e47
2012-06-08 14:30:56 +05:30
0bceae488e Merge "cwebp: fix alpha reporting in stats output" 2012-06-07 21:27:02 -07:00
0424b1ef3b Rebase default encoding settings.
Updated histo_bits to 3 from 4 and changed the quality threshold for inner loop for HashChainFindCopy.
Impact: 0.5%-0.8% better bpp with 15%-20% hit on encoding throughput
at default encoding settings.

Change-Id: I316ef88403148b1e19036fa0817d944eb0301255
2012-06-08 09:18:15 +05:30
c71ff9e359 cwebp: fix alpha reporting in stats output
Since
 437999f introduce a generic WebPPictureHasTransparency() function
lossy encodes will not encode alpha if the alpha channel is completely
opaque.

Change-Id: I1826669c3932483650d7f8ce806cfebd4e5225fc
2012-06-07 17:32:29 -07:00
e2ffe446bd Merge "Stop indefinite recursion for Huffman Image." 2012-06-07 10:52:26 -07:00
70eb2bd687 Stop indefinite recursion for Huffman Image.
Ensure that the lossless bit-stream doesn't allow for such cases and
safe-gaurd decoder against indefinite recursion.

Change-Id: Ia6d7f519291de8739f79a977a5800982872aae71
2012-06-07 17:27:19 +05:30
f3bab8eb27 Update vwebp
... with updated mux API calls.

Change-Id: I0f8a36eeffaeb041964ec4f582e369d48bba4978
2012-06-07 17:20:26 +05:30
6d5c797cee Remove support for partial files in Mux.
Change-Id: Ie084f308c79a3cfaf2ea13e800397debc2643470
2012-06-07 13:46:42 +05:30
f1df5587d9 WebPMuxAssemble() returns WebPData*.
Also add an API 'WebPDataFree()'

Change-Id: I00dc4c67fd78a541a18aaf0e65b8ef62d9769803
2012-06-07 11:05:57 +05:30
814a063925 Rename 'Add' APIs to 'Set'.
Change-Id: I10a836a5bc3c9207b6f7fa423bb64bc9bcac055b
2012-06-05 20:37:51 +05:30
bbb0218fa5 Update Mux psuedo-code examples.
Change-Id: I9df4d509286c9b892272181646403c0c7893db70
2012-06-05 20:29:42 +05:30
4fc4a47f6e Use WebPData in MUX set APIs
Change-Id: Ibdede3c1cd02c6aeef333718592da313f10f6408
2012-06-05 14:21:46 +05:30
c67bc979dd Merge "add WebPPictureImportRGBX() and WebPPictureImportBGRX()" 2012-06-05 00:28:04 -07:00
27519bc2b6 add WebPPictureImportRGBX() and WebPPictureImportBGRX()
When importing BGRA or RGBA data for encoding, provide variants of
the WEBPImportPicture API for RGBX and BRGX data meaning the alpha
channel should be ignored.

Author: noel@chromium.org
from Chromium patch: https://chromiumcodereview.appspot.com/10496016/

Change-Id: I15fcaa4160c69a2b5549394204b6e6d7a1c5d333
2012-06-05 00:26:17 -07:00
f80cd27e28 factorize code in Import()
Change-Id: I6a4e77715c3a5be5238c81e029bfb6479d36de05
2012-06-04 23:27:01 -07:00
9b71502669 histogram: add log2 wrapper
Change-Id: I5e68efaf5f763a42ace1af83f4b7887e0ddfd099
2012-06-04 23:14:41 -07:00
8c34378ff3 Merge "fix some implicit type conversion warnings" 2012-06-04 22:46:33 -07:00
42f6df9da3 fix some implicit type conversion warnings
Change-Id: I0653d10410c0d46f91fedad4c4dffa9c1de402cb
2012-06-04 22:33:32 -07:00
250c16e3d5 Merge "doc: update lossless pdf" 2012-06-04 22:30:41 -07:00
9d9daba43d Merge "add a PDF of the lossless spec" 2012-06-04 22:30:19 -07:00
8fbb91884e prefer webp/types.h over stdint.h
stdint.h is part of C99 and is notably lacking under MSVC

Change-Id: Iff60dcb8bdcc7f948dc35fb0b5d47478520b570f
2012-06-04 18:34:24 -07:00
0ca170c2dd doc: update lossless pdf
Change-Id: I8c6d0e6fc21196f6dd239b21eda2097ba4ce2bba
2012-06-04 16:53:16 -07:00
0862ac6e7e add a PDF of the lossless spec
(cherry picked from commit db9967748781d73832b3875db1dfcbefb180f7c9)

Change-Id: I5909abc48d9b4c4415f81a019681968f06d6a3d7
2012-06-04 16:51:39 -07:00
437999fb77 introduce a generic WebPPictureHasTransparency() function
VP8-lossy will now avoid writing an ALPH chunk if the
alpha values are trivial.

+ changed DumpPicture() accordingly in cwebp
+ prevented the -d option to be active with lossless
 (DumpPicture wouldn't work).

Change-Id: I34fdb108a2b6207e93fa6cd00b1d2509a8e1dc4b
2012-06-04 16:17:55 -07:00
d2b6c6c03b cosmetic fixes after Idaba281a
Change-Id: I275a3dee5696fe1a3e2db0976f8241f2044be512
2012-06-04 13:19:28 -07:00
b4e6645c61 Merge "add colorspace for premultiplied alpha" 2012-06-04 07:56:37 -07:00
48f827574e add colorspace for premultiplied alpha
The new modes are
       MODE_rgbA
       MODE_bgrA
       MODE_Argb
       MODE_rgbA_4444
It's binary incompatible, since the enums changed.

While at it, i removed the now unneeded KeepAlpha methods.
-> Saved ~12k of code!

* made explicit mention that alpha_plane is persistent,
so we have access to the full alpha plane data at all time.
Incremental decoding of alpha was planned for, but not
implemented. So better not dragged this constaint for now
and make the code easier until we revisit that.

Change-Id: Idaba281a6ca819965ca062d1c23329f36d90c7ff
2012-06-04 07:50:41 -07:00
069f903a08 Change in lossless bit-stream.
Change the lossless signature to 0x2f
Add 1 bit indicator for 'droppable (or trivial) alpha)'.
Add 3 bit lossless version (for future extension like yuv support).
Change the sub-resolution information to 3 bits implying range [2 .. 9]

Change-Id: Ic7b8c069240bbcd326cf5d5d4cd2dde8667851e2
2012-06-04 12:47:01 +05:30
5f7bb3f53a Merge "WebPReportProgress: use non-encoder specific params" 2012-05-31 13:02:30 -07:00
f18281ffa0 WebPReportProgress: use non-encoder specific params
Take picture and percent value storage location instead of VP8Encoder.
This will allow reuse by the lossless encoder.

Change-Id: Ic49dbc800cc3e2df60d20f4ebac277f68ed6031b
2012-05-31 11:28:48 -07:00
9ef3228301 Add support for raw lossless bitstream in decoder.
Previously, it used to assume any raw bitstream is a VP8 one.

Also,
- Factor out VP8CheckSignature() & VP8LCheckSignature().
- Use a local var for *data_ptr in ParseVP8Header() for
readability.

Change-Id: I0fa8aa177dad7865e00c8898f7e7ce76a9db19d5
2012-05-31 14:03:17 +05:30
7cbee29afa Fix bug: InitIo reseting fancy_upsampling flag.
frame's InitIo should not reset fancy_upsampling flag.
This flag (fancy_upsampling) is set via CustomSetup -> WebPIoInitFromOptions
and frame's InitIo() is resetting it to 0.

Change-Id: I64b54cdfba43799c0a5aa8e384575af5d6331674
2012-05-30 14:46:22 +05:30
880fd98ca1 vwebp: fix exit w/freeglut
GLUT_ACTION_CONTINUE_EXECUTION is required to allow glutMainLoop to
return.

Change-Id: I8eb7e657a52d6923858959b7b03447a7ddb53ca0
2012-05-25 15:06:21 -07:00
1875d926e7 trap two unchecked error conditions
CostModelBuild() and TrackBackwards() returns weren't checked

+ code clean-up
+ de-inline VP8LBackwardRefs non-critical methods
+ shuffle the .h around to group things together
+ extract some constants as #define's
+ fixed the "if (!(cc_init = ...)) {...}" constructs
+ removed some unneeded VP8L prefixes

Change-Id: Ic634cb87bc6b2033242d3e8e8731fab4c134f327
2012-05-25 02:52:44 -07:00
87b4a908a5 no need to have mux.h as noinst clause in enc/
Change-Id: I93c65838f33d01170fc63340650edeeee753786f
2012-05-24 15:05:19 -07:00
88f41ec6ec doc: fix bit alignment in VP8X chunk
Change-Id: I7eaa7be48213642e3eceaaac95ad00952e085330
2012-05-24 12:33:48 -07:00
52f5a4eff0 Merge "fix bug with lossy-alpha output stride" 2012-05-24 08:56:44 -07:00
3bde22d768 fix bug with lossy-alpha output stride
dec->width_ != final_width in case of Bundle transform!

thanks to Pepijn for spotting the problem

Change-Id: I08b451a32097dcbf23b73deabc8cc6a2d59f0119
2012-05-24 08:54:02 -07:00
42d61b6def update the spec for the lossy-alpha compression methods.
No further experiments are to be expected, so this is quite the
final format so far, pending supplemental feedbacks.

Change-Id: I2a3de025c90b7bb5fdd8792b2b2ccdc2e3753f56
2012-05-24 07:22:52 -07:00
e75dc80516 Move some more defines to format_constants.h
Also remove some duplicate const/defines.

Change-Id: I0ec48866b874f546022d72e938fb65669b0b3211
2012-05-24 17:46:01 +05:30
c13f663261 Move consts to internal header format_constants.h
Change-Id: Ic6180c16d0b4245680738992925e4608c593fbe8
2012-05-24 15:02:02 +05:30
7f2dfc92dc use a bit-set transforms_seen_ instead of looping
may be useful later for instance to bypass some code
if we know we don't use the Bundle+ColorMap transform.

Change-Id: I9dc70d18165b2363ad9ede763684ef3d8eba5903
2012-05-24 02:04:23 -07:00
18da1f53fc modulate alpha-compression effort according to config.method
we vary linearly lossless-method between 0 and 6,
and lossless-quality between 50 and 100, so that encoding
speed can go from 'quite fast' to 'rather slow'.
Impact on size is moderate, but visible.

Change-Id: I0b7917e7170eb50258afb1a4e248028cd9e9207d
2012-05-24 01:54:12 -07:00
f5f2fff657 Merge "Alpha flag fix for lossless." 2012-05-24 01:11:07 -07:00
c975c44ea5 Alpha flag fix for lossless.
- Make sure alpha flag is set in case of a lossless file with VP8X chunk.
  The semantic of ALPHA_FLAG changes with this: it means the images
  contain alpha (rather than ALPH chunk in particular).
- Update the mux container spec to add 1-line description of alpha
  flag.
- Rename "HasLosslessImages()" to "MuxHasLosslessImages()", and other
  similar function renames.
- Rename FeatureFlags to WebPFeatureFlags
- Elaborated a comment for a special case.
- A misc comment fix.

Change-Id: If212ccf4338c125b4c71c10bf281a51b3ba7ff45
2012-05-24 11:35:12 +05:30
4f067fb254 Merge "Android: only build dec_neon with NEON support" 2012-05-23 22:26:03 -07:00
255c66b48f Android: only build dec_neon with NEON support
Defining LOCAL_ARM_NEON = true can result in neon instructions being
used in portions unprotected by the cpu check.
This changes defines a WEBP_USE_NEON/WEBP_ANDROID_NEON pair similar to
the SSE2 code and MSVC.

Change-Id: Ifac010b06e42c73d5aca529baa2198c6796674bd
2012-05-23 22:21:10 -07:00
8f9117a9f0 cosmetics: signature fixes
Change-Id: Id0e1026d43c0a6928dd740c88117df638bfb6db6
2012-05-23 12:45:05 -07:00
39bf5d6497 use header-less lossless bitstream for alpha channel
This saves ~26 bytes of headers.
* introduce new VP8LDecodeAlphaImageStream() for decoding
* use VP8LEncodeStream() for encoding
* refactor code a bit

still TODO: make the alpha-quality/enc-method user-configurable

Change-Id: I23e599bebe335cfb5868e746e076c3358ef12e71
2012-05-23 08:01:44 -07:00
75d7f3b222 Merge "make input data be 'const' for VP8LInverseTransform()" 2012-05-23 07:54:12 -07:00
9a721c6d24 make input data be 'const' for VP8LInverseTransform()
Change-Id: I5b5b1e29bca6c42704df141b21632a0d0fcb07cf
2012-05-23 07:21:53 -07:00
9fc64edc21 Disallow re-use of same transformation.
Limit the overall number of transformations to 4 and disallow any
duplicate transform for decoding an image.

Change-Id: Ic4b0ecd553db96702e117fd073617237d95e45c0
2012-05-23 17:04:57 +05:30
98ec717f1e use a function pointer for ProcessRows()
this allows later customization of data output method.
No perf diff observed, even if ProcessRows is no longer inlined.

Change-Id: I6933a3612a9cf6c108cf2776dfde0ae80c6c07c0
2012-05-23 02:00:14 -07:00
f7ae5e370a cosmetics: join line
Change-Id: Ib27ed202fff439b94431360c8b0654d88962fb9a
2012-05-23 01:56:29 -07:00
140b89a323 factor out buffer alloc in AllocateARGBBuffers()
+ small opportunistic fixes:
  * allow NULL decoded_data to be passed to DecodeStream
    and clarity (with assert()) when to do so
  * AllocateAndInitRescaler() was already setting error status,
    as it should. No need to do it at caller's site

Change-Id: I30867e596564a7f459a0d1ddbf6f5d312414b7fd
2012-05-23 01:53:57 -07:00
a107dfa806 Rectify WebPParseOptionalChunks().
Now it stops at either VP8/VP8L chunk.

Change-Id: Iadac4fa47396b61b9b720b8b7b19138c89df24cc
2012-05-23 13:59:52 +05:30
237eab6764 Add two more color-spaces for lossless decoding.
Added color-spaces (RGBA_4444 and RGB_565), required for Android device
to lossless decoding.

Change-Id: I229832edd4deca59e066f463e7454f77457c5bcd
2012-05-23 12:10:13 +05:30
27f417ab66 fix orthographic typo
Change-Id: I4f62e9c125ef3bc1ab75871e6725551f1c89f5e8
2012-05-22 13:20:57 -07:00
489ec335a1 add VP8LEncodeStream() to compress lossless image stream
* RIFF header is omitted
* rename NewVP8LEncoder and DeleteVP8Encoder
* change the signature to take a "const WebPPicture*"
  (it was non-const just because we were setting some error potentially)
* made the pic_ field const in VP8LEncoder too.
* trap the bitwriter::error_ too
* simplify some signatures to take WebPPicture* instead
  of unneeded VP8LEncoder*

VP8LEncodeStream() will be called directly to compress alpha channel
header-less.

Change-Id: Ibceef63d2b3fbc412f0dffc38dc05c2dee6b6bbf
2012-05-22 03:15:58 -07:00
fa8bc3dbca make WebPEncodingSetError() take a const picture
This is a border-case situation: the picture is not const, because
we're change its error status. But taking it non-const forces
the caller to carry a non-const picture all around the code just
in case (0.00001% of the time?) something bad happen.
This pretty much the same as making all objects non-const because
we'll eventually call delete or free() on them, which is quite a
non-const operation. Well... Better allow constness enforcement for
the remaining 99.9999% of the code.

Change-Id: I9b93892a189a50feaec1a3a518ebf488eb6ff22f
2012-05-22 02:51:38 -07:00
638528cd1e bitstream update for lossy alpha compression
now, we only use 2 bits for the filtering method, and 2 bits
for the compression method.
There's two additional bits which are INFORMATIVE, to specify
whether the source has been pre-processed (level reduction)
during compression. This can be used at decompression time
for some post-processing (see DequantizeLevels()).

New relevant spec excerpt:

     0                   1                   2                   3
     0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    |                      ChunkHeader('ALPH')                      |
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    |Rsv| P | F | C |     Alpha Bitstream...                        |
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

Compression method (C): 2 bits

: The compression method used:

  * `0`: No compression.
  * `1`: Backward reference counts encoded with arithmetic encoder.

Filtering method (F): 2 bits

: The filtering method used:

  * `0`: None.
  * `1`: Horizontal filter.
  * `2`: Vertical filter.
  * `3`: Gradient filter.

Pre-processing (P): 2 bits

: These INFORMATIVE bits are used to signal the pre-processing that has
been performed during compression. The decoder can use this information to
e.g. dither the values or smooth the gradients prior to display.

  * `0`: no pre-processing
  * `1`: level reduction

Decoders are not required to use this information in any specified way.

Reserved (Rsv): 2 bits

: SHOULD be `0`.

Alpha bitstream: _Chunk Size_ - `1` bytes

: Encoded alpha bitstream.

This optional chunk contains encoded alpha data for a single tile.
Either **ALL or NONE** of the tiles must contain this chunk.

The alpha channel data is losslessly stored as raw data (when
compression method is '0') or compressed using the lossless format
(when the compression method is '1').

Change-Id: Ied8f5fb922707a953e6a2b601c69c73e552dda6b
2012-05-22 02:36:22 -07:00
d73e63a726 add DequantizeLevels() placeholder
will be called by alpha post-processing, although doing nothing for now.
Gradient smoothing would be nice-to-have here. Patch welcome!

Change-Id: I534cde866bdc75da22d0f0a6d1373c90e21366f3
2012-05-22 02:28:19 -07:00
ec122e0986 remove arch-dependent rand()
let's use our own simple pseudo-random number generator

Change-Id: I7b4a190cdf4d338b1fae5ef3622ebd82c6e19274
2012-05-22 00:17:04 -07:00
d40e7653db fix alignment
Change-Id: Ieb36de1bcf8c624024f8a3d5a238a2b508d4bb51
2012-05-21 14:31:16 -07:00
1dd6a8b65e Merge "remove tcoder, switch alpha-plane compression to lossless" 2012-05-21 06:38:45 -07:00
3e863dda61 remove tcoder, switch alpha-plane compression to lossless
* Method #1 is now calling the lossless encoder on the alpha plane.
Format is not final, it's just a first draft. We need ad-hoc functions.
* removed now useless utils/alpha.*
* added utils/quant_levels.h instead
* removed the TCoder code altogether

Change-Id: I636840b6129a43171b74860e0a0fc5bb1bcffc6a
2012-05-21 06:24:48 -07:00
8d77dc29e1 Add support for lossless in mux:
- Separate out 'CHUNK_INDEX' from 'TAG_ID' (this is to help with the
  situation where two different tags - "VP8 " and "VP8L" can have the
  same TAG_ID -> IMAGE_ID).
- Some internal methods now take 'CHUNK_INDEX' param instea of 'TAG_ID'
  as appropriate.
- Add kChunks[] entry for lossless.
- Rename WebPMuxImage.vp8_ --> WebPMuxImage.img_
- SetImage() and AddFrame/Tile() infer whether the bitstream is a
  lossless one based on LOSSLESS_MAGIC_BYTE. The correct tag is stored
  based on this.

Also, handle the case when GetVP8Info/GetVP8LInfo() fails.

Change-Id: I6b3bc9555cedb791b43f743b5a7770958864bb05
2012-05-21 13:54:18 +05:30
831bd13168 Make tile size a function of encoding method.
Higher method implies more encoding effort (CPU) achieved with
smaller tile sizes (lower histo_bits).

Change-Id: Ic39c8d882c87835f74fde41172afb002ac3fd1c3
2012-05-18 12:16:39 +05:30
778c52284b Merge "remove some variable shadowing" 2012-05-17 14:03:10 -07:00
817c9dce61 Few more HuffmanTreeToken conversions.
Change-Id: I932b5368d279f83c462c7d916978dab3e81d7709
2012-05-16 12:15:52 +05:30
37a77a6bf4 remove some variable shadowing
Change-Id: I4348253ec6b50639095b22c4745dc26da0904466
2012-05-15 14:04:24 -07:00
89c07c9660 Merge "normalize example header includes" 2012-05-15 13:50:27 -07:00
4aff411fe0 Merge "add example_util.[hc]" 2012-05-15 13:49:21 -07:00
00b29e282f normalize example header includes
headers from examples/ aren't installed so prefix with './' to be
explicit.

Change-Id: Ie6c1544a026a9859b7fc0cf238b21e031ef0013f
2012-05-15 13:48:11 -07:00
061263a787 add example_util.[hc]
moves ReadFile to a common location

Change-Id: Ia81230671f16d7d4d218b9954a5be55577a85413
2012-05-15 13:42:57 -07:00
c6882c49e3 merge all tree processing into a single VP8LProcessTree()
-> 0.1% size improvement because we're calling OptimizeForRLE()
systematically now.

Change-Id: I03bd712175728e0d46323f375134cae5a241db4b
2012-05-14 05:49:02 -07:00
9c7a3cf5e7 fix VP8LHistogramNumCodes to handle the case palette_code_bits == 0
-> lot of simplifications ensue and we should be able to get rid of
 ClearHuffmanTreeIfOnlyOneSymbol() too, in a subsequent patch.

Change-Id: Ic4c51d05e4b1970e37f94ffd85fae6a02e4a6422
2012-05-14 01:23:58 -07:00
b5551d2e1d Merge "Added HuffmanTreeCode Struct for tree codes." 2012-05-14 01:23:08 -07:00
8b85d01c45 Added HuffmanTreeCode Struct for tree codes.
To represent tree codes (depth and bits array).

Change-Id: I87650886384dd10d95b16ab808dfd3bb573172bc
2012-05-14 13:50:35 +05:30
093f76d831 Merge "Allocate single memory in GetHuffBitLengthsAndCodes." 2012-05-14 01:15:46 -07:00
41d8049451 Allocate single memory in GetHuffBitLengthsAndCodes.
Allocate big chunk of memory in GetHuffBitLengthsAndCodes, instead of allocating in a loop.
Also fixed the potential memleak.

Change-Id: Idc23ffa306f76100217304444191a8d2fef9c44a
2012-05-14 13:41:59 +05:30
1b04f6d234 Correct size in VP8L header.
The size written in VP8L header should be without padding.
(Also clarified this code using consts).

Change-Id: Ic6583d760c0f52ef61924ab0330c65c668a12fdc
2012-05-14 12:49:16 +05:30
2924a5aee6 Makefile.vc: split object lists based on directory
Change-Id: I4e189193817f26117e6459da078e2a72c9f3ef5f
2012-05-11 18:29:33 -07:00
c8f24165b7 Merge "add assert(tokens)" 2012-05-11 01:46:45 -07:00
432399472f add assert(tokens)
Change-Id: I952a5cd15ff0a80cff349293e6403357cbc7bd8d
2012-05-11 01:45:06 -07:00
9f547450e0 Catch an error in DecodeImageData().
When we are at end-of-stream, but haven't decoded all pixels, we should
return an error.
Also remove an obsolete TODO.

Change-Id: I3fb1646136e706da536d537a54d1fa487a890630
2012-05-11 14:10:01 +05:30
ac8e5e42d1 minor typo and style fix
Change-Id: If4927beb7a8f3c96379eee1fedc687a5046a6951
2012-05-11 01:17:31 -07:00
9f566d1d36 clean-up around Huffman-encode
* refine doc
* use LUT for bit-reversal
* added assert
* Introduce HuffmanTreeToken instead of separate code/extra_bits arrays

Change-Id: I0fe0b50b55eb43a4be9f730b1abe40632a6fa7f0
2012-05-10 09:11:47 -07:00
c579a71012 Introduce CHUNK_SIZE_BYTES in muxi.h.
Plus a style fix.

Change-Id: Id94df6c91a96598cb022c813e0981f542aebe982
2012-05-10 13:16:18 +05:30
14757f8ae2 Make sure huffman trees always have valid symbols
- Symbols added to the tree are valid inside HuffmanTreeBuildExplicit().
- In HuffmanTreeBuildImplicit(), make sure 'root_symbol' is
valid in case of a single symbol tree.

Change-Id: I7de5de71ff28f41e2d6228b29ed8dd4a20813e99
2012-05-10 11:40:18 +05:30
4105061840 makefile.unix: add support for building vwebp
standalone from the normal examples due to the additional OpenGL
dependencies.
$ make -f makefile.unix examples/vwebp

Change-Id: I7e3f0b5e0328230cb32acdd1e2a011cbbb80e55d
2012-05-09 15:47:00 -07:00
48b37721fc Merge "fixed signed/unsigned comparison warning" 2012-05-09 14:10:32 -07:00
57f696daef Merge "EncodeImageInternal: fix potential leak" 2012-05-09 13:58:55 -07:00
d972cdf2dd EncodeImageInternal: fix potential leak
if histogram_image_size is reduced in when writing the histogram_image
the bit arrays would leak any remaining elements. store their element
count separately.

Change-Id: I710142a11ebd4325faec7bd65c2d2572aae19307
2012-05-09 13:49:10 -07:00
5cd12c3df2 fixed signed/unsigned comparison warning
present in an assert in backward_references.h

Change-Id: Id9a528896689e51d784ad64fdc1ca052e97fe7a2
2012-05-09 13:45:26 -07:00
cdca30d0b5 Merge "cosmetics: shorten long line" 2012-05-09 13:45:12 -07:00
e025fb5546 cosmetics: shorten long line
Change-Id: I78bb19cf593730e74734e08d3d6de08a29bd9cbc
2012-05-09 13:42:31 -07:00
22671ed6a3 Merge "enc/vp8l: fix double free on error" 2012-05-09 13:36:38 -07:00
e1b9b05258 Merge "cosmetics: VP8LCreateHuffmanTree: fix indent" 2012-05-09 13:23:24 -07:00
a8e725f800 enc/vp8l: fix double free on error
GetHuffBitLengthsAndCodes and the caller would both free
bit_lengths/bit_codes

Change-Id: I1b62ff727c82567f11c39a847f74fe765b5f527c
2012-05-09 12:56:07 -07:00
27541fbdc0 cosmetics: VP8LCreateHuffmanTree: fix indent
Change-Id: I025fada400366f8937208e1f9b8df483cd53a942
2012-05-09 12:11:22 -07:00
1d38b258b8 cwebp/windows: use MAKE_REFGUID where appropriate
Change-Id: If595c75a833d37df86c16bf926da5f032015c68e
2012-05-09 11:52:01 -07:00
817ef6e9af Merge "cwebp: fix WIC/Microsoft SDK compatibility issue" 2012-05-09 11:50:05 -07:00
902d3e3b5f cwebp: fix WIC/Microsoft SDK compatibility issue
Fixes issue #115.
Define local copies of GUID_WICPixelFormat24bppRGB &
GUID_WICPixelFormat32bppRGBA (and GUID_WICPixelFormat32bppBGRA for
symmetry) to avoid link issues when building against older versions of
the SDK.

Change-Id: I2a26be1b7fe6d970feb3211cf0059e5898e3028d
2012-05-09 11:47:15 -07:00
89d803c423 Merge "Fix a crash due to wrong pointer-integer arithmetic." 2012-05-09 02:22:01 -07:00
cb1bd741f9 Merge "Fix a crash in lossless decoder." 2012-05-09 02:21:13 -07:00
de2fe20290 Merge "Some cleanup in VP8LCreateHuffmanTree() (and related functions CompareHuffmanTrees() and SetBitDepths()): - Move 'tree_size' initialization and malloc for 'tree + tree_pool' outside the loop. - Some renames/tweaks for readability." 2012-05-09 02:15:42 -07:00
ce69177a41 Fix a crash due to wrong pointer-integer arithmetic.
[Basically, the condition "src - dist < data" can be wrongly evaluated
to be false if "src < dist" due to underflow. Instead, "src - data <
dist" is the correct condition, as "src > data" is always true and so
there would never be an underflow].

Change-Id: Ic9f64bfe76a9acae97abc1fb7c1f4868e81f1eb8
2012-05-09 14:40:06 +05:30
e40a3684f5 Fix a crash in lossless decoder.
This was due to incorrect update of 'ok'.

Change-Id: I91edfb5682527e8bc7eaa10e635c0261edb016b6
2012-05-09 14:35:11 +05:30
3927ff3abc remove unneeded error condition for WebPMuxNumNamedElements()
+ fix error message

Change-Id: If283ff6609ee0c5dff81a9c1c3f194faa729161c
2012-05-09 01:57:15 -07:00
2c140e113c Some cleanup in VP8LCreateHuffmanTree() (and related functions
CompareHuffmanTrees() and SetBitDepths()):
- Move 'tree_size' initialization and malloc for 'tree + tree_pool'
  outside the loop.
- Some renames/tweaks for readability.

Change-Id: I5cb3cc942afac6e9f51a0b97c57ee897677a48a2
2012-05-09 14:26:01 +05:30
861a5b7bc9 add support for animation
it's using glutTimerFunc() for trigger next frame's decoding

Reminder: how to build and use manually (integration in makefile.unix coming soon)

Unix:
cd libwebp
make -f makefile.unix
cd examples
cc -o vwebp vwebp.c -framework GLUT -framework OpenGL -I../src/ ../src/libwebp.a ../src/mux/libwebpmux.a

Mac + xcode:
cd libwebp
make -f makefile.unix
cd examples
cc -o vwebp vwebp.c -lglut -lGL -lpthread -lm -I../src/ ../src/libwebp.a ../src/mux/libwebpmux.a

Change-Id: Id49e87c26628c2b58ec221f6030cbd2e46a807b4
2012-05-09 01:23:39 -07:00
eb5c16cc18 Merge "Set correct encode size in encoder's stats." 2012-05-09 00:37:25 -07:00
4abe04a204 fix the return value and handle missing input file case.
Change-Id: I42a64fcf7587ff3a487115808e2cfa51cec0031d
2012-05-09 00:34:30 -07:00
2fafb85579 Set correct encode size in encoder's stats.
The current implementation doesn't take care one byte
signature and associated one byte padding (for odd sized chunk).

Change-Id: I35b81d0644818cdba38189aa48c75db5f92e68f4
2012-05-09 12:33:58 +05:30
e7167a2b95 Provide one entry point for backward references.
The new method VP8LGetBackwardReferences hides internal
heuristics used for choosing RLE or LZ77 based refs.
- Tuned VP8LHashChainFindCopy for better compression at higher Q.
- Refactored code.
- Removed the unused method VP8LVerifyBackwardReferences.

Change-Id: Ibb7bb072bab5a49a001577a20d88226f52e6c663
2012-05-09 12:13:06 +05:30
c4ccab6463 Print relevant lossless encoding stats in cwebp.
Change-Id: Ib8dfab498b1a05e49734bba2d3e72810343e8b0a
2012-05-09 11:31:41 +05:30
e3302cfd73 GetHuffBitLengthsAndCodes: reduce level of indirection
arrays can be passed directly as only their members are being modified.
this also reduces the allocation for bit_codes[] by taking the
sizeof(type)=2 rather than sizeof(ptr)=4/8 in one case.

Change-Id: Idad20cead58c218b58d90b71699374fefd01cad9
2012-05-08 11:48:55 -07:00
b5f2a9ed49 enc/vp8l: fix uninitialized variable warning
histogram_image_size could be unset if the code branches to the 'Error'
label.

Change-Id: I690b20f86372f19a47d159c2bec8fbf49553f0d5
2012-05-08 11:45:04 -07:00
7885f8b25d makefile.unix: add lossless encoder files
comment out 'EXTRA_FLAGS += -DUSE_LOSSLESS_ENCODER' to disable

Change-Id: I75ead699c95644e319e7cbbf2a167d98e826fb7c
2012-05-08 11:25:28 -07:00
1261a4c888 Merge "cosmetics" 2012-05-07 17:54:43 -07:00
3926b5be3b Merge "dsp/cpu.c: Android: fix crash on non-neon arm builds" 2012-05-07 17:53:03 -07:00
834f937f3c dsp/cpu.c: Android: fix crash on non-neon arm builds
add proper cpu-detection for Android targets

Fixes issue #118 (and is a better solution for #117).

based on patch by pepijn vaneeckhoudt

Change-Id: I6b00ea6d51ca658ccf6a3d55b87b99c01c6805be
2012-05-07 17:52:15 -07:00
126e160672 cosmetics
vp8.[hc]:fix '*' placement in pointer types
vp8l.c: remove trailing ',' from enum
decode.h: fix stray WebPINew()

Change-Id: Id6749a14a12ed0a090649f28ef4267fda45a37a8
2012-05-07 17:47:51 -07:00
e38602d2ad Merge branch 'lossless_encoder'
* lossless_encoder: (46 commits)
  split StoreHuffmanCode() into smaller functions
  more consolidation: introduce VP8LHistogramSet
  big code clean-up and refactoring and optimization
  Some cosmetics in histogram.c
  Approximate FastLog between value range [256, 8192]
  Forgot to update out_bit_costs to symbol_bit_costs at one instance.
  Evaluate output cluster's bit_costs once in HistogramRefine.
  Simple Huffman code changes.
  Lossless decoder: remove an unneeded param in ReadHuffmanCodeLengths().
  Reducing emerging palette size from 11 to 9 bits.
  Move GetHistImageSymbols to histogram.c
  Improve predict vs no-predict heuristic.
  code-moving and clean-up
  reduce memory usage by allocating only one histo
  Restrict histo_bits to ensure histo_image size is under 32MB
  further simplification for the meta-Huffman coding
  A quick pass of cleanup in backward reference code
  Make transform bits a function of encode method (-m).
  introduce -lossless option, protected by USE_LOSSLESS_ENCODER
  Run TraceBackwards for higher qualities.
  ...

Conflicts:
	src/enc/webpenc.c

Change-Id: I9a5d98cba0889ea91d10699466939cc283da345a
2012-05-07 14:27:17 -07:00
e8d3d6a018 split StoreHuffmanCode() into smaller functions
Change-Id: Iaa715f4997505eebabee1e92e964a5d7ee6f3e7d
2012-05-07 14:25:32 -07:00
d0d88990d8 more consolidation: introduce VP8LHistogramSet
VP8LHistogramSet is container for pointers to histograms that
we can shuffle around. Allocation is one big chunk of memory.
Downside is that we don't de-allocate memory on-the-go during
HistogramRefine().

+ renamed HistogramRefine() into HistogramRemap(), so we don't
confuse with "HistogramCombine"
+ made VP8LHistogramClear() static.

Change-Id: Idf1a748a871c3b942cca5c8050072ccd82c7511d
2012-05-07 14:25:30 -07:00
1a210ef1a9 big code clean-up and refactoring and optimization
* de-inline some function
* make VP8LBackwardRefs be more like a vectorwith max capacity
* add bit_cost_ field to VP8LHistogram
* general code simplifications
* remove some memmov() from HistogramRefine
* simplify HistogramDistance()
...

Change-Id: I16904d9fa2380e1cf4a3fdddf56ed1fcadfa25dc
2012-05-07 14:25:29 -07:00
41b5c8ff71 Some cosmetics in histogram.c
Change-Id: I5d5872a793759fad593dba88c3f593f72b328b0c
2012-05-07 14:25:28 -07:00
ada6ff77df Approximate FastLog between value range [256, 8192]
Profiled data: Profiled few images and found that in the function VP8LFastLog,
90% of time table lookup is performed, while rest of time (10%) call to log
function is made. Typical lookup accounts for 10 CPU instructions and call to
log 200 instruction counts. The weighted average comes out to be 30
instructions per call. For mid qualities (25-75), this function (VP8LFastLog)
accounts for 30-50% of total CPU cycles (via call path: VP8LCOlorSpaceTransform
-> PredictionCostCrossColor -> ShannonEntropy). After this change, the log is
called less that 1% of time, with average instructions being 15 per call.
Measured the performance over 1000 files for various qualities and found
overall compression speedup between 10-15% (in quality range [0, 75]). The
compression density loss is around 0.5% (though at some qualities, compression
is little better as well).

Change-Id: I247bc6a8d4351819c871f19d65455dc23aea8650
2012-05-07 14:25:26 -07:00
ec123ca3f6 Forgot to update out_bit_costs to symbol_bit_costs at one instance.
Change-Id: Iaf952c0cb6e3fe35257d2503a16a437c6f2eb3aa
2012-05-07 14:25:25 -07:00
cf33ccd160 Evaluate output cluster's bit_costs once in HistogramRefine.
Avoid bit_costs evaluated every time in function HistogramDistance. Also moved
VP8LInitBackwardRefs and VP8LClearBackwardRefs to backward_references.h

Change-Id: Id507f164d0fc64480aebc4a3ea3e6950ed377a60
2012-05-07 14:25:23 -07:00
781c01f421 Simple Huffman code changes.
No empty trees are codified with the simple Huffman code. The simple Huffman
code is simplified to be either a 1-bit code or 8-bit code for symbols.

Change-Id: I3e2813027b5a643862729339303d80197c497aff
2012-05-07 14:25:21 -07:00
a2849bc502 Lossless decoder: remove an unneeded param in ReadHuffmanCodeLengths().
Change-Id: I279452fdf38b680737d5ba6e868a219281bc8962
2012-05-07 14:25:20 -07:00
b39e7487a7 Reducing emerging palette size from 11 to 9 bits.
This is required to reduce memory used to construct histo_image.

Change-Id: I491a06e10a3e3f3d8a00ecec286394378283ffea
2012-05-07 14:25:19 -07:00
bfc73db4a8 Move GetHistImageSymbols to histogram.c
Planning to revisit memory allocation scheme at several instanaces (next CL).

Change-Id: Id7b9f4854e9577e10b53d5b1d8595b7d862e6e01
2012-05-07 14:25:18 -07:00
889a578681 Improve predict vs no-predict heuristic.
This improves compression density. For example, at quality 95 on 1000 PNGs:
bpp(before) = 2.447 and bpp(after) = 2.412

Change-Id: I19c343ba05cca48a6940293721066502a5c3d693
2012-05-07 14:25:16 -07:00
01f50663dc code-moving and clean-up
* removed use_lz77_ field, and added cache_bits_ one.
* use more BackwardRefs params
* move code around to organize more logically
* reduce memory use on histo
...

Change-Id: I833217a1b950189cf486704049e3fe28382ce335
2012-05-07 14:25:14 -07:00
31035f3b49 reduce memory usage by allocating only one histo
instead of lz77+rle

* introduce VP8LBackwardRefs structure and simplify the code by not passing
  around {PixOrCopy/int} pairs.

More functions should be turned into using this struct (TODO(later)).

Change-Id: I69c5c9fa61dddd61a2abc2824d70b8606a1c55b6
2012-05-07 14:25:12 -07:00
fbb501b8ee Restrict histo_bits to ensure histo_image size is under 32MB
Change-Id: I75ccb65d56ee060b649de714287e71611a92c8e9
2012-05-07 14:25:10 -07:00
8415ddf3be further simplification for the meta-Huffman coding
* don't transmit the number of Huffman tree group explicitly
* move color-cache information before the meta-Huffman block

* also add a check that color_cache_bits is in [1..11] range, as per spec.

Change-Id: I81d7711068653b509cdbc1151d93e229c4254580
2012-05-07 14:25:07 -07:00
e491729905 A quick pass of cleanup in backward reference code
const correctness, renaming, cosmetics etc.

Change-Id: I432befbb22f0eafd9a613f5f632398b6ef03c0f6
2012-05-07 14:25:05 -07:00
83332b3c16 Make transform bits a function of encode method (-m).
Change-Id: Idc392f7cba6e160ea068eacd7f82be4ebc971eaa
2012-05-07 14:25:03 -07:00
72920caa61 introduce -lossless option, protected by USE_LOSSLESS_ENCODER
Change-Id: Ic5707082fefd964b9bcab0c9f9aa276992c22b06
2012-05-07 14:25:02 -07:00
c6ac4dfbb4 Run TraceBackwards for higher qualities.
Also reduce the iteration count in function VP8LHashChain_FindCopy.

Change-Id: I73e3811e142e81314515587fd655ab3bfa74d099
2012-05-07 14:25:00 -07:00
412222c88c Make histo_bits and transform_bits function of quality.
Change-Id: Ic34e40853604811abc63a38e09d6a01961649efc
2012-05-07 14:24:58 -07:00
149b5098a9 Update lossless encoder strategy:
Don't use any other transform when using palette.

Change-Id: I488ac546869677f1b6e4eed80e973569c757e997
2012-05-07 14:24:56 -07:00
0e6fa06595 cache_bits passed to EncodeImageInternal()
should be 0 when not using color cache.

Change-Id: Id15c9b6bfbeb7c69a0189fa4c411df2763f9dead
2012-05-07 14:24:54 -07:00
e38b40a996 Factorize code for clearing HtreeGroup.
Change-Id: I29de6dab7383b8cf071eec155e01340d5fdadee5
2012-05-07 14:24:53 -07:00
6f4a16ea00 Removing the indirection of meta-huffman tables.
Now, the indexing refers directly to 5 huffman codes that must be encoded
separately.

Change-Id: I92e10ccf8ca464aa7259867d5fae2869343e3b3c
2012-05-07 14:24:51 -07:00
3d33ecd12b Some renaming/comments related to palette in lossless encoder.
Change-Id: Iaab32912f4c31e809d7a49fd748099d8c0c3e7d9
2012-05-07 14:24:49 -07:00
4d02d5863f Lossless encoder: correction in Palette storage
(Essentially, there was no need of a separate 'argb_palette' array. And
argb_palette[0] was never being set).

Change-Id: Id0a8c7e063d3af41e39fc9b8661611b51ccc55cd
2012-05-07 14:24:47 -07:00
4a6362357a fix a memleak in EncodeImageInternal()
Change-Id: I55cd013211f192188b54c694ef0837af0c01b53c
2012-05-07 14:24:45 -07:00
0993a611cd Full and final fix for prediction transform
use (tile_size + 1) rows of scratch area.

Change-Id: I06d612fff1794fc045ba76275e94e7210802c332
2012-05-07 14:24:43 -07:00
afd2102f43 Fix cross-color transform in lossless encoder
make elements of "Multiplier" struct unsigned, so that any negative values are
automatically converted to "mod 256" values.

Change-Id: Iab4f9bacc50dcd94a557944727d9338dbb0982f7
2012-05-07 14:24:41 -07:00
b96d8740c9 Need to write a '0' bit at the end of transforms.
Also convert an 'if' to 'assert'.

Change-Id: Ia1129ad9ddb027c27b4f4fc1da4bbaf53a0a8f76
2012-05-07 14:24:39 -07:00
54dad7e553 Color cache size should be counted as 0 when cache bits = 0
Change-Id: I1d05e0561a92aebaf62162fe11ffc4b12496d698
2012-05-07 14:24:37 -07:00
4f0c5caf67 Fix prediction transform in lossless encoder.
(Keep one tile as a scratch buffer).

Change-Id: If112ada29bfd0bdc81b82e849a566b30dd331d2f
2012-05-07 14:24:35 -07:00
36dabdadf8 Fix memory leak in method EncodeImageInternal for histogram_image.
Change-Id: Ia1cfb96d9e6c120630732e2b5f39688376d1d208
2012-05-07 14:24:33 -07:00
352a4f49ab Get rid of PackLiteralBitLengths()
[and in turn a malloc]. Also, a few related const fixes.

Change-Id: I229519b1c34d41c78d9ad2403f1e25feab3c9d93
2012-05-07 14:24:31 -07:00
d673b6b9a0 Change the predictor function to pass left pixel
instead of pointer to the source.

Change-Id: Ia2c8e17c3140709a825c2f85a88c5e31bd6e462f
2012-05-07 14:24:29 -07:00
b2f99465a7 Fix CopyTileWithPrediction()
so that it uses original values of left, top etc for prediction rather than the
predicted values of the same. Also, do some renaming in the same to make it
more readable.

Change-Id: I2fe94e35a6700bd437f5c601e2af12323bf32445
2012-05-07 14:24:27 -07:00
84547f540c Add EncodeImageInternal() method.
Most of changes in enc/vp8l.c is cherry-picked from src/lossless/encode.c

Change-Id: I27938cb2590eccbfe1db0a454343e856bd483e75
2012-05-07 14:24:25 -07:00
6b38378acb Guard the lossless encoder (in flux) under a flag
Change-Id: I6dd8fd17089c199001c06b1afde14233dc3e3234
2012-05-07 14:24:23 -07:00
09f7532cce Fix few nits (const qualifiers)
Change-Id: I527e82af49956b695ab18625d34e143854067421
2012-05-07 14:24:21 -07:00
648be3939f Added implementation for various lossless functions
- VP8LEncAnalyze, EvalAndApplySubtractGreen, ApplyPredictFilter,
  ApplyCrossColorFilter
- Added palette handling and transform buffer management in VP8LEncodeImage()
- Add Transforms (subtract Green, Predict, cross_color) to dsp/lossless.c.

These are more-or-less copied from src/lossless code.

After this Change, will implement the EncodeImageInternal() method.

Change-Id: Idf71f803c24b3b5ae3b5079b15e019721784611d
2012-05-07 14:24:19 -07:00
32714ce3be Add VP8L prefix to backward ref & histogram methods.
Change-Id: I8c14fb219a1d7830d3244aa780c91c9964867330
2012-05-07 14:24:17 -07:00
fcba7be2d3 Fixed header file tag (WEBP_UTILS_HUFFMAN_ENCODE_H_)
Change-Id: I7ccd00361b1b0347639b05ee494e8e701c95cfe3
2012-05-07 14:24:16 -07:00
bc7037465d Add backward_ref, histogram & huffman encode modules from lossless.
Change-Id: Iac056d27972956782defa182caa3ea400cdb77f8
2012-05-07 14:24:14 -07:00
fdccaaddcf Fixing nits
- Const Handling of picture object, removed bitwriter from encoder.

Change-Id: Id943854de09324de81cca615ada960390c4b8152
2012-05-07 14:24:12 -07:00
227110c4c3 libwebp interface changes for lossless encoding.
Change-Id: I703a1a18347acf78378cb23fddc6e5ca6dc6a0bb
2012-05-07 14:24:09 -07:00
50679acf25 minor style fixes
Change-Id: I78a6fa19a799c41d6536631f547279692b658c4d
2012-05-04 19:01:11 -07:00
b38dfccf8d remove unneeded reference to NUM_LITERAL_CODES
Change-Id: I3e98acce3a69fa45054ffcf77644fcbbc04bd366
2012-05-04 19:01:09 -07:00
8979675bdf harmonize header description
Change-Id: Ie0256794e663b58557e7234f08af3d516071001e
2012-05-04 19:01:06 -07:00
c04eb7be9d tcoder.c: define NOT_HAVE_LOG2 for MSVC builds
no version of msvc currently implements log2(). unconditionally define
NOT_HAVE_LOG2 in this case to simplify building libwebp sources in other
projects.

Change-Id: Ia9d985b1125553c5a8271d7e539bc1b4f898d749
2012-05-03 16:59:13 -07:00
9a214fa112 Merge "VP8[L]GetInfo: check input pointers" 2012-05-02 16:07:47 -07:00
5c5be8ba69 VP8[L]GetInfo: check input pointers
validate data before using & width/height before assigning.

Change-Id: I0872e80fcbfea295d7c633b0d4cb7809e1d1883b
2012-05-02 16:05:02 -07:00
0c188feca1 Merge changes I431acdfe,I713659b7
* changes:
  mux: drop 'chunk' from ChunkInfo member names
  muxi.h: remove some unused defines
2012-05-02 16:03:06 -07:00
b3515c6215 mux: drop 'chunk' from ChunkInfo member names
fixes naming style (members should be lowercase, not camelcase).

Change-Id: I431acdfe3cc3740d9effe9df80a94ca284a072b6
2012-05-01 17:47:18 -07:00
aea7923ca2 muxi.h: remove some unused defines
Change-Id: I713659b7ed83bafedd94a0b16379decea293a2f0
2012-05-01 17:47:11 -07:00
0142249285 update NEWS file for next release
Change-Id: I93ba2432fb99334dd17bd1a9da3a39c19e495484
2012-05-01 17:34:14 -07:00
29e3f7ec75 Merge "dec: remove deprecated WebPINew()" 2012-05-01 11:26:31 -07:00
4718e44988 Merge "muxedit: a few more size_t changes" 2012-04-28 03:04:08 -07:00
82654f961d Merge "muxedit: remove a few redundant NULL checks" 2012-04-28 02:50:27 -07:00
02f27fbd3b dec: remove deprecated WebPINew()
Change-Id: I22ad1d297333f5ebc84456d142426a4e0e9a044b
2012-04-27 19:47:35 -07:00
ccddb3fc6f muxedit: remove a few redundant NULL checks
Change-Id: I8285a7694d40b0f5c986dbfe40703251682eaafc
2012-04-27 19:06:03 -07:00
a6cdf7107a muxedit: a few more size_t changes
Change-Id: I18266dc572426cb3daace6e0ad8f2ae21687a151
2012-04-27 18:53:08 -07:00
a384689292 Merge "mux: remove unused LIST_ID" 2012-04-27 03:03:34 -07:00
11ae46ae91 alpha.c: quiet some size_t -> int conversion warnings
Change-Id: I52026a9271bde4028f00df2d752e100c61fd3fe3
2012-04-26 18:47:08 -07:00
dee466926b mux: remove unused LIST_ID
The 'LIST' fourcc is not a well known value in the context of webp.

Change-Id: I6a571f5f3acd6463cf3cad7c5d5ffa89d0597fb6
2012-04-25 18:18:25 -07:00
03f1f49321 mux: add version checked entry points
Change-Id: I3bf5b25b17c06ec092f8ad1c14eea411aa9471c1
2012-04-25 17:27:16 -07:00
6a0abdaa3a Merge "doc: tile/alpha corrections" 2012-04-24 23:57:05 -07:00
c8139fbe5d Merge "few cosmetics" 2012-04-24 23:47:06 -07:00
683387374b Merge "lossless: remove some size_t -> int conversions" 2012-04-24 23:41:26 -07:00
5249e94a22 doc: tile/alpha corrections
- the tile chunk size does not include the alpha or vp8 chunks that
  follow
- remove 'experimental' note from alpha section
- drop an unused term from the terminology section

Change-Id: I46f0fd610bbce579446e19339c3458dddfb595f7
2012-04-24 17:43:06 -07:00
d96e722b0c huffman: quiet int64 -> int conversion warning
children_ is bounded by max_nodes_ and protected with IsFull checks

Change-Id: Iac1eb03c5030568140352174c1265a938fc28d97
2012-04-24 16:17:36 -07:00
532020f24a lossless: remove some size_t -> int conversions
Sizes are given as ints in the documentation and used as such elsewhere.

Change-Id: I51ecd9e501cf9b4e3948aa0e947d2c9b5c85a30f
2012-04-24 16:00:00 -07:00
23be6edfd4 few cosmetics
Change-Id: I85b44d811ecc7c551b75e74e64115e74645836b6
2012-04-24 11:53:10 -07:00
1349edade1 Merge "configure: AC_ARG_* use AS_HELP_STRING" 2012-04-24 10:54:39 -07:00
bfbcc60a18 configure: AC_ARG_* use AS_HELP_STRING
properly formats --help output

Change-Id: I18fad9039400df8415ef192a41c0295019c52775
2012-04-24 10:48:17 -07:00
1427ca8eae Merge "Makefile.am: header file maintenance" 2012-04-24 10:41:59 -07:00
087332e394 Merge "remove unused parameter 'round' from CalcProba()" 2012-04-24 06:41:54 -07:00
9630e16854 remove unused parameter 'round' from CalcProba()
Change-Id: I0d89c34565decb28776aee7500ebd261fc43caf7
2012-04-24 06:40:19 -07:00
92092eaa45 Merge "bit_reader.h: correct include" 2012-04-24 04:19:24 -07:00
a87fc3f609 Merge "mux: ensure # images = # tiles" 2012-04-24 04:18:35 -07:00
53af99b18f Merge "mux: use size_t consistently" 2012-04-24 04:09:44 -07:00
39a57dae22 Makefile.am: header file maintenance
src/dec/Makefile.am: add missing reference to vp8li.h
src/{dec,dsp,enc}/Makefile.am: move some headers to noinst_

Change-Id: I0e2bc69980bd8175d99ad0ab63f537ef9e425b77
2012-04-23 18:53:48 -07:00
1bd0bd0d4d bit_reader.h: correct include
use webp/types.h rather than webp/decode_vp8.h

Change-Id: I9c6da04b92ff00d6dac47ce3eb0bcb2d6a96712d
2012-04-23 17:04:22 -07:00
326a3c6bdc mux: ensure # images = # tiles
when a file contains tiles an image outside of a tile is not allowed.

Change-Id: I5d16759abc9aa9bb299103b2cd7d694fc9c89697
2012-04-23 16:44:37 -07:00
95667b8d86 mux: use size_t consistently
remove mixed use of uint32_t

Change-Id: I57f701a0d9fce255c4dd83c01e523079976ef5b5
2012-04-23 11:00:20 -07:00
231ec1fb6d Removing the indirection of meta-huffman tables.
Now, the indexing refers directly to 5 huffman codes  that must be encoded separately.

Change-Id: I4deeb04de1997e6d20c376046d2053ec7ee918de
2012-04-23 08:36:14 -07:00
15ebcbaaf4 check return pointer from MuxImageGetListFromId
previously, it could crash with nth=1 on a raw vp8 bitstream, e.g.

Change-Id: Ice555d95b984ba71017fc56314d0c2c1b5bdf599
2012-04-23 08:22:58 -07:00
b0d6c4a722 Merge "configure: remove test for zlib.h" 2012-04-21 15:34:41 -07:00
8cccac50ae Merge "dsp/lossless: silence some build warnings" 2012-04-21 15:32:45 -07:00
b08819a624 dsp/lossless: silence some build warnings
src/dsp/lossless.c: In function 'VP8LInverseTransform':
src/dsp/lossless.c:312:23: warning: 'packed_pixels' may be used
uninitialized in this function [-Wuninitialized]
src/dsp/lossless.c:304:16: note: 'packed_pixels' was declared here
src/dsp/lossless.c:258:34: warning: 'm.red_to_blue_' may be used
uninitialized in this function [-Wuninitialized]
src/dsp/lossless.c:275:17: note: 'm.red_to_blue_' was declared here
src/dsp/lossless.c:257:34: warning: 'm.green_to_blue_' may be used
uninitialized in this function [-Wuninitialized]
src/dsp/lossless.c:275:17: note: 'm.green_to_blue_' was declared here
src/dsp/lossless.c:255:33: warning: 'm.green_to_red_' may be used
uninitialized in this function [-Wuninitialized]
src/dsp/lossless.c:275:17: note: 'm.green_to_red_' was declared here

patch by pepijn vaneeckhoudt

Change-Id: Iffa4764487a75479df45e772169325cd9ee60d94
2012-04-20 12:35:35 -07:00
7ae225218d Android.mk: SSE2 & NEON updates
patch by pepijn vaneeckhoudt
- Android.mk should include dec/enc/upsampling sse2 variants. This
  provides sse2 optimizations when compiling for Android/x86
- LOCAL_ARM_NEON should be set to true when compiling for armeabi-v7a.
  Otherwise __ARM_NEON__ is not defined and all neon code is removed by
  the preprocessor.

Change-Id: I54f3505757fc5d2d63cca4b64d61be34a0b34eb8
2012-04-20 12:07:03 -07:00
0a49e3f3da Merge "makefile.unix add missing header files" 2012-04-20 00:34:35 -07:00
2e75a9a1ba Merge "decode.h: use size_t consistently" 2012-04-19 22:49:47 -07:00
fa13035e97 configure: remove test for zlib.h
hasn't been needed since:
  9523f2a Add Alpha Encode support from WebPEncode.

Change-Id: Ia784ac434ec6fd43aade8875a91e2ad9f0fa9c30
2012-04-19 16:54:59 -07:00
d3adc81db2 makefile.unix add missing header files
Change-Id: I440ea805fd14884242bab2577e8286088616e5c7
2012-04-19 16:13:26 -07:00
262fe01be2 Merge "makefile.unix & Android.mk: cosmetics" 2012-04-19 16:03:08 -07:00
4cce137ebf Merge "enc_sse2 add missing stdlib.h include" 2012-04-19 15:51:53 -07:00
80256b8567 enc_sse2 add missing stdlib.h include
lost in fbd82b5; most platforms were getting it indirectly through
emmintrin.h.

Change-Id: I310f8bc8e82d63cfbde74c34cd21b72514a16a01
2012-04-19 15:47:58 -07:00
9b3d1f3a1b decode.h: use size_t consistently
replaces mixed use of int/uint32_t for buffer sizes
further changes the API/ABI.

Change-Id: I91d70fd82ee3e1ac34b884b8ead9a114a9b1015a
2012-04-19 14:31:31 -07:00
64083d3c89 Merge "Makefile.am: cosmetics" 2012-04-19 13:51:33 -07:00
dceb8b4d9a Merge changes If1331d3c,I86fe3847
* changes:
  types.h: centralize use of stddef.h
  vp8io: use size_t for buffer size
2012-04-14 13:01:14 -07:00
0e33d7bf42 Merge "webp/decode.h: fix prototypes" 2012-04-13 10:46:14 -07:00
fac0f12e1b rename BitReader to VP8LBitReader
Change-Id: I192b76422e131a94fb58c2c4a5520a5dba807126
2012-04-13 01:56:31 -07:00
fbd82b5a39 types.h: centralize use of stddef.h
for size_t / NULL

Change-Id: If1331d3cf44296ed0ba9e838eae2f5b1bcaeb61b
2012-04-12 17:14:58 -07:00
2154835f73 Makefile.am: cosmetics
- use common file organization across subdir makefiles
- append lib/source/header list variables and sort

Change-Id: I0653e1c73a4552b0c43d21f321b22b4972d6e87b
2012-04-12 15:53:06 -07:00
1c92bd37f3 vp8io: use size_t for buffer size
changes the decoder ABI

Change-Id: I86fe384739b985bf63bcd9badbbbf4411e1eecae
2012-04-12 15:19:53 -07:00
90ead710dc fix some more uint32_t -> size_t typing
Change-Id: Ibbe85ff4a700b17126a65e9ca5a3fa8cbf00b8a6
2012-04-12 13:06:54 -07:00
cbe705c78a webp/decode.h: fix prototypes
fell out of sync with:
  6860c2e fix some uint32_t -> size_t typing

Change-Id: I897fcd61f6a9767fb6accc5899d8e7763c9f4de8
2012-04-12 12:52:17 -07:00
3f8ec1c21f makefile.unix & Android.mk: cosmetics
split object/source list to single line & sort
remove unnecessary tabs

Change-Id: I1db03555f9578e128c746853084438da2b9186eb
2012-04-12 12:29:57 -07:00
217ec7f4d0 Remove tabs in configure.ac
Change-Id: Ia6cd668523881ca6777a723bfe3460f38d064934
2012-04-12 00:13:06 -07:00
b3d35fc130 Merge "Android.mk & Makefile.vc: add new files" 2012-04-11 15:48:30 -07:00
0df04b9e19 Android.mk & Makefile.vc: add new files
from the lossless additions, fixes the build.

Change-Id: I3243c48f21cfb4e2244614bb5ab12ff94dd684e5
2012-04-11 15:47:04 -07:00
e4f20c5bd5 Merge "automake: replace 'silent-rules' w/AM_SILENT_RULES" 2012-04-11 15:45:55 -07:00
8d254a0927 cosmetics
long line, remove out of date TODO

Change-Id: Ic8a40c9d731178af85645b3e24c1cbd807d7d58b
2012-04-11 15:44:48 -07:00
6860c2ea9d fix some uint32_t -> size_t typing
Change-Id: I078243802a67498dfcd3d15b5f1bebf4b6b3b1bb
2012-04-11 04:27:45 -07:00
4af1858a10 Fix a crash due to max symbol in a tree >= alphabet size
(cherry picked from commit 15253f91567ce7a2a4a3de8d70e54ba4b0641af3)

Change-Id: I4fbeaea4c712dae3bef078aef9d302b44bc39ffb
2012-04-10 23:07:13 -07:00
6f01b830e2 split the VP8 and VP8L decoding properly
* each with their own decoder instances.
* Refactor the incremental buffer-update code a lot.
* remove br_offset_ for VP8LDecoder along the way
* make VP8GetHeaders() be used only for VP8, not VP8L bitstream
* remove VP8LInitDecoder()
* rename VP8LBitReaderResize() to VP8LBitReaderSetBuffer()
(cherry picked from commit 5529a2e6d47212a721ca4ab003215f97bd88ebb4)

Change-Id: I58f0b8abe1ef31c8b0e1a6175d2d86b863793ead
2012-04-10 23:06:58 -07:00
f2623dbe58 enable lossless decoder
import changes from experimental 5529a2e^
and enable build in autoconf and makefile.unix; windows will be treated
separately.

Change-Id: Ie2e177a99db63190b4cd647b3edee3b4e13719e9
2012-04-10 23:06:36 -07:00
b96efd7d50 add dec/vp8i.h changes from experimental
Pulled from 5529a2e^.

Change-Id: I51fe7a9c3acf1be4c43af834fd525ab3be5d7e65
2012-04-10 23:05:57 -07:00
19f6398ed7 add dec/vp8l{i.h,.c} from experimental
Pulled from 5529a2e^.
The history of this and related files is a bit entangled so rather
trying to split the changes and introduce some noise in master's history
we'll start with a fresh snapshot.
The file progression is still available in the experimental branch.

Change-Id: I490a49cb0084d556a29d7c5257c986ea695ce60c
2012-04-10 23:05:14 -07:00
c4ae53c8b3 add utils/bit_reader.[hc] changes from experimental
Pulled from the parent of the current version (5529a2e^).
The history of this and related files is a bit entangled so rather
trying to split the changes and introduce some noise in master's history
we'll start with a fresh snapshot.
The file progression is still available in the experimental branch.

Change-Id: I6dae97fc381cd6c1d1640c4c565b2084a41ec955
2012-04-10 17:48:49 -07:00
514d008921 add dsp/lossless.[hc] from experimental
Pulled from the current HEAD (218c32e).
The history of this and related files is a bit entangled so rather
trying to split the changes and introduce some noise in master's history
we'll start with a fresh snapshot.
The file progression is still available in the experimental branch.

Change-Id: I40538799dbf999abb9408ac83f55b897d8e22498
2012-04-10 17:37:44 -07:00
9c67291d67 add utils/huffman.[hc] from experimental
Pulled from the current HEAD (218c32e).
The history of this and related files is a bit entangled so rather
trying to split the changes and introduce some noise in master's history
we'll start with a fresh snapshot.
The file progression is still available in the experimental branch.

Change-Id: Ie57be21bf50ad83808c72aeb5fc706d9954d01d8
2012-04-10 17:31:54 -07:00
337914a036 add utils/color_cache.[hc] from experimental
Pulled from the current HEAD (218c32e).
The history of this and related files is a bit entangled so rather
trying to split the changes and introduce some noise in master's history
we'll start with a fresh snapshot.
The file progression is still available in the experimental branch.

Change-Id: Id879be453a94d9f44ec8d47747823ca7297ae008
2012-04-10 17:23:38 -07:00
b3bf8fe7a1 the read-overflow code-path wasn't reporting as an error
(since 'ok' was '1' by default)
(cherry picked from commit fe5eb4ffae74ff493e92fb5cd9a7a1625a113a7b)
2012-03-30 18:58:30 -07:00
1db888ba40 take colorspace into account when cropping
(cherry picked from commit 4e33653b52637c74ae30adde7990265d1d43994b)

Conflicts:

	src/dec/vp8l.c
2012-03-30 12:48:24 -07:00
61c2d51fd7 move the rescaling code into its own file and make enc/ and dec/ use it.
(cherry picked from commit 8e92d9e380a89b7443a2e2c3d16ce5a222e8c1e8)

Conflicts:

	Android.mk
	makefile.unix
	src/dec/vp8l.c
	src/utils/Makefile.am
2012-03-30 12:16:25 -07:00
efc2016a31 Make rescaler methods generic
to be used in rescaling of lossless bitstreams.
(cherry picked from commit 2e12a3045498b6faf13b93bc25391e8226119f0a)
2012-03-30 11:57:07 -07:00
3eacee8158 Move rescaler methods out of io.c.
(cherry picked from commit b5e9db1824f6efbe0bfb87e94b8d6e88a7973ef7)
2012-03-30 11:56:51 -07:00
a69b893dda automake: replace 'silent-rules' w/AM_SILENT_RULES
silent-rules is a new option with automake-1.11; older versions will
fatally exit with it. Using AM_SILENT_RULES will only result in a
warning at least through automake-1.9.

Change-Id: Ieae6a09780efd85f08f0c6442172634a1ce5ff33
2012-03-28 22:46:12 -07:00
6f7bf645b4 issue 111: fix little-endian problem in bit-reader
patch by naideflan

Change-Id: I874dbd5588d5cd2559c54ca9ad5582fa3a589b1b
2012-03-27 05:55:20 -07:00
ed278e2279 Removed unnecessary lookup
The lookup value is the same as the index.  The index in this
case is either a 0 or 1.

Change-Id: I0432dfcbea9e7bb20bca7574e25fb1fd8a51c8e9
2012-03-26 11:44:04 -04:00
cd8c3ba78f fix some warnings: down-cast and possibly-uninitialized variable
Change-Id: I5baf59bbcd5dcff69316b0601483ff5abe8e1454
2012-03-16 20:20:33 -07:00
0a7102ba60 ~1% improvement of alpha compression
by packing the symbol map more efficiently.

This is mainly useful in making it harder to generate invalid bitstream:
before this change, one could code the same symbol twice. Now, it's
impossible, since we code the position using empty symbol slots, instead
of total position.

* Fix the HasOnlyLeftChild() naming while at it.

Change-Id: I63c56c80a4f04a86ac83eded1e3306329815b6c9
2012-02-24 19:59:40 -08:00
3bc1b14191 Merge "Reformat container doc" 2012-02-24 19:30:40 -08:00
dc17abdcb6 mux: cosmetics
add a few missing consts and remove an unnecessary cast

Change-Id: I396571090ce379bbc7a173cbc90714a6b7b52a2a
2012-02-23 13:21:43 -08:00
cb5810dfbe Merge "WebPMuxGetImage: allow image param to be NULL" 2012-02-22 21:58:48 -08:00
506a4af2fa mux: cosmetics
group like parameters together in prototypes, comments, move variable
declarations closer to first use.

Change-Id: Idd6bd87d0366d783fed83f4dd21bd7968cbe6948
2012-02-22 16:14:32 -08:00
135e8b1942 WebPMuxGetImage: allow image param to be NULL
but not both alpha & image

Change-Id: I6822a740de7577eedcbe7529382aa2c020d1e8e4
2012-02-22 16:09:06 -08:00
de556b6866 Merge "README.mux: reword some descriptions" 2012-02-22 15:02:50 -08:00
0ee2aeb904 Makefile.vc: use batch mode rules
speeds up the build

Change-Id: I2471fb6b42bb5d51f8dd1634f65d5f8114355a22
2012-02-22 11:36:28 -08:00
d9acddc010 msvc: move {i,p}db creation to object directory
avoids cluttering the source tree.

Change-Id: I2885b36dd7152e294536584fa5cfe3ae8b04c7fa
2012-02-22 11:19:16 -08:00
237c9aa727 Merge "expose WebPFree function for DLL builds" 2012-02-22 10:55:52 -08:00
b3e4054f14 silence msvc debug build warning
_byteswap_ulong is defined in stdlib.h, release builds seem to pull it
in through a different path.

Change-Id: I510d2624150f89a4a77734bf3dc5b4db60a4ba95
2012-02-21 13:57:48 -08:00
45feb55dec expose WebPFree function for DLL builds
This allows managed code (e.g., C#) to free buffers returned by the API
instead of relying on free().
Based on suggestion from Steven (grokys at googlemail dot com).
Fixes issue #109.

Change-Id: I94826a77f6f4cb6e331c454f994c964e2e448cae
2012-02-21 13:48:06 -08:00
11316d84b4 README.mux: reword some descriptions
Change-Id: I334caaa908c9a50baf8e35125dd0062d764f2949
2012-02-17 14:39:31 -08:00
4be52f4a65 factorize WebPMuxValidate
move count extraction, count and feature flag validation to
ValidateChunk.

Change-Id: I4bd81bbc8a5a48e1263d11992ab3f285c45417b8
2012-02-15 11:54:10 -08:00
14f6b9f606 mux: light cleanup
- const / move declarations closer to first use
- remove unnecessary ()s
- don't return int unnecessarily with internal Init/Release
- compact some lines

Change-Id: If7ab505e417221debc356f21f075506939110a84
2012-02-14 13:51:41 -08:00
5e96a5dbef add more param checks to WebPPictureDistortion()
and use the proper alpha flag too.

Change-Id: I664c6c9dbcc747495bf20b3da95d00e1120b5baf
2012-02-10 02:52:48 -08:00
8abaf82083 Merge "silence some type size related warnings" 2012-02-09 19:21:39 -08:00
1601a39b09 silence some type size related warnings
size_t/ptrdiff_t -> uint32_t

Change-Id: Ic4d889b9239752311b9ed906c83076829d850874
2012-02-09 13:00:09 -08:00
f3abe520ac Merge "idec: simplify buffer size calculation" 2012-02-09 01:25:00 -08:00
a9c5cd4c97 idec: simplify buffer size calculation
Change-Id: Id0e20c44704ef9b0e14dcf5e71a05cea488fd95a
2012-02-08 14:29:25 -08:00
7b06bd7fcb Merge "configure/automake: add silent-rules option" 2012-02-08 14:04:12 -08:00
e9a7d145e7 Reformat container doc
- split the doc into sections for simple and extended format and move
  example layouts to the end.
- use ASCII tables to describe chunk formats
- attempt to consistently use MUST/SHOULD, etc.
- remove bold from most terms, but add them to definition lists which
  allow for the styling to be changed.

Change-Id: I93c1cd33bde9ccf0b265b202ec4182ce98fd6b48
2012-02-08 11:32:42 -08:00
d4e5c7f327 configure/automake: add silent-rules option
Enables --(enable|disable)-silent-rules and make V=[01] to control
compile output. Default is verbose as before.

Change-Id: Id9a65977ac8c719f4d9e3efe386750e520689b76
2012-02-07 18:08:08 -08:00
5081db78be configure/automake: no -version-info for convenience libs
Silences:
libtool: link: warning: `-version-info/-version-number' is ignored for
convenience libraries

Change-Id: I5705383b58f529fb06c2bf0932976b5a202446b6
2012-02-07 18:06:20 -08:00
85b6ff6897 Merge "idec: fix WebPIUpdate failure" 2012-01-31 23:39:02 -08:00
7bb6a9ccd6 idec: fix internal state corruption
A call to Append/Update would index the parts_ array w/-1 as num_parts_
had yet to be set by DecodePartition0. This would cause corruption
within the VP8Decoder member.

Fixes issue #106.

Change-Id: Ib9f2811594ff19e948a66fda862a4e0a384bb9aa
2012-01-31 17:10:29 -08:00
89cd1bb85b idec: fix WebPIUpdate failure
If the first call to WebPIUpdate contained all of partition 0, but not
enough to decode a macroblock the test for max macro block size could
fail (4096 bytes) due to a memory buffer offset not being updated.
This change offsets the buffer in the same manner as Append().

Fixes issue #105.

Change-Id: I90ca3d0dde92eedc076933b8349d2d297f2469e8
2012-01-31 16:55:10 -08:00
01b6380656 4-5% faster decoding, optimized byte loads in arithmetic decoder.
Bits are loaded 32bits at a time (and often aligned).
Rather 64bit-friendly

Change-Id: If7f67dbe5e37696efbeb6d579d9d8482350b79ee
2012-01-31 02:07:15 -08:00
631117ea5e Merge "cosmetics & warnings" 2012-01-30 22:04:11 -08:00
a0b2736d79 cosmetics & warnings
- remove some unused functions
- move global arrays from data to read only section
- explicitly cast malloc returns; not specifically necessary, but helps
  show intent
- miscellaneous formatting

Change-Id: Ib15fe5b37fe6c29c369ad928bdc3a7290cd13c84
2012-01-30 17:19:53 -08:00
f73947f41d use 32bit for storing dequant coeffs, instead of 16b.
is a tad faster

Change-Id: Ibef8f3b4f3f04a9a647098e5946f616e211a61cd
2012-01-29 17:38:37 -08:00
b9600308e8 Merge "store prediction mode array as uint8_t[16], not int[16]." 2012-01-27 07:16:50 -08:00
7b67881a23 store prediction mode array as uint8_t[16], not int[16].
This allow faster copy and gives a little bit of speed-up

Change-Id: I5f478229766098630b53b8a4982442fe29290ee6
2012-01-27 03:17:41 -08:00
cab8d4dc22 Merge "NEON TransformOne" 2012-01-26 11:38:16 -08:00
ba503fdac6 NEON TransformOne
As with the loop filter, implementing this with intrinsics is difficult
because we require subscript access for reading and writing 32 bits at a
time.

Approximately 5% decode speed improvement. This could be increased by
exposing TransformOne and rewriting TransformTwo to only handle dual
IDCTs.

Change-Id: Idd409264ab5d154a537107a1d54b419a48f7c1a8
2012-01-26 11:37:32 -08:00
9f740e3b1a Merge "gcc warning fix: remove the 'const' qualifier." 2012-01-25 15:53:10 -08:00
f76d3587e5 gcc warning fix: remove the 'const' qualifier.
Change-Id: I47b8f147f54072cb9b62669efd78c7b958aa5c08
2012-01-25 15:50:24 -08:00
e78478d62c Merge "webpmux: make more use of WebPData" 2012-01-25 13:06:49 -08:00
f85bba3dae Merge "manpages: add BUGS section" 2012-01-25 12:43:16 -08:00
48a43bbfae Merge "makefile.unix: variable cosmetics" 2012-01-25 12:42:09 -08:00
c274dc9679 makefile.unix: variable cosmetics
use CPPFLAGS to hold include paths, makes overriding CC a bit more
intuitive.

Change-Id: I6ecfc1957cae423dd150ebf37b878f1da6bbcef3
2012-01-25 10:46:28 -08:00
1f7b8595ae re-organize the error-handling in the main loop a bit
Change-Id: Id74298131df9c33a86b989e15c11ffb6d04960d8
2012-01-25 08:34:58 -08:00
1336fa719d Only recompute level_cost_[] when needed
Add a dirty_ flag to keep track of updated probabilities and the need to
recompute the level costs.
This only makes a difference for "-m 2" method which was sub-optimal.
But it's overall cleaner to have this flag.

Change-Id: I21c71201e1d07a923d97a3adf2fbbd7d67d35433
2012-01-25 07:52:34 -08:00
771ee449b0 manpages: add BUGS section
reorder sections to better match 'man man-pages'

Change-Id: I6cc3cd7f74b6cc6848c407cb1f042207c82f847e
2012-01-24 17:40:42 -08:00
0f7820e65c webpmux: make more use of WebPData
Add WebPDataCopy and use it in ReadImage which now returns WebPData*s.
Update ReadData prototype variables used with it to avoid unnecessary
const casting back and forth from void*.

Change-Id: I3f83db6729306eab0db9027b68706c8a7005ec10
2012-01-24 17:18:45 -08:00
974aaff360 examples: logging updates
- send errors to stderr
- send help to stdout
- add image size to webpmux -info output and send to stdout
- correct webpmux exit values

Change-Id: Ifd8e8493aab33a82765f7b7903cef345d96da9ae
2012-01-24 16:55:38 -08:00
6c14aaddc4 Merge "better token buffer code" 2012-01-23 18:55:11 -08:00
f40542508c better token buffer code
(still not finished, but compiles and works ok)

Change-Id: I7002bf8017e31e7af34a53126072b625d23e2589
2012-01-23 18:54:24 -08:00
18d959fa9a Merge "mux: add WebPData type" 2012-01-23 18:00:21 -08:00
eec4b87718 mux: add WebPData type
slightly simplifies Get process

Change-Id: I9db365da29038e02a032494e0ef3d8a0d7515210
2012-01-23 17:51:01 -08:00
0de3096b3a use 16bit counters for recording proba counts
This proved being ok, even for large pictures, provided one
takes care of overflow. When an overflow is bound to occur, the
counters are renormalized.
Overall, shaves ~12k of memory.

Change-Id: I2ba21a407964fe1a34c352371cba15166e0c4548
2012-01-23 17:50:58 -08:00
7f23678da0 fix for LevelCost + little speed-up
the p0 proba was incorrectly accumulated. Merging its contribution into
the LevelCost[] was creating more problems than anything (esp. with trellis)
so let's just not.

Change-Id: I4c07bfee471085df901228d97b20a4d9606ba44e
2012-01-23 09:21:17 -08:00
7107d54483 further speed-up/cleanup of RecordCoeffs() and GetResidualCost()
(note: Incorporated the cost of bin #1 into the LevelCost[])

Change-Id: I6408b2a822efdb97ad6a3a21d380bc7b0da9c715
2012-01-23 07:01:37 -08:00
fd22104022 Introduce Token buffer (unused for now)
Later, will be useful to collect stats and code bitstream in one single pass

Change-Id: Icf866473958b5eff879e219dbb1d7e350f2268ba
2012-01-23 05:57:12 -08:00
5fa148f47c Merge "speed-up GetResidualCost()" 2012-01-23 02:50:58 -08:00
28a9d9b41a speed-up GetResidualCost()
+ misc cosmetics and code polishing

Change-Id: I5830cd2f268d64c072b1cbccc0a4674833875055
2012-01-23 02:36:38 -08:00
11e7dadd96 Merge "misc cosmetics" 2012-01-22 23:52:29 -08:00
378086bd0a misc cosmetics
Change-Id: Iafc73f9fece13b5ca900a8b9c1039268872a181b
2012-01-22 23:20:53 -08:00
d61479f95b add -print_psnr and -print_ssim options to cwebp.
These will report the 7x7-averaged PSNR or SSIM, using the
new internal function WebPPictureDistortion().
This is for information only. These flags have no encoding impact.

+misc opportunistic cosmetics

Change-Id: I64c0a7eca679134d39062e438886274b22bb643f
2012-01-20 07:37:29 -08:00
2e3e8b2ef5 add a WebPCleanupTransparentArea() method
to 'clean up' the fully-transparent area and make it more compressible
new cwebp flags: -alpha_cleanup (off by default, since gain is not 100% guaranteed)

Change-Id: I74d77e1915eee146584cd61c9c1132a41db922eb
2012-01-18 14:01:24 -08:00
552c121715 Merge "mux: plug some memory leaks on error" 2012-01-18 13:46:38 -08:00
a2a81f7d61 Merge "fix Mach-O shared library build" 2012-01-18 13:16:12 -08:00
b3482c4300 Merge "fix gcc-4.0 apple 32-bit build" 2012-01-18 13:15:23 -08:00
e4e3ec19ad fix gcc-4.0 apple 32-bit build
gcc-4.0 defines __PIC__ but not __pic__. This leaves the test for
__pic__ should the inverse case exist.
Fixes issue #103; build failing with:
"error: can't find a register in class 'BREG' while reloading 'asm'"

Change-Id: Ia767a733de6ce0294146f9477ff9c46f0ebe13b0
2012-01-18 13:12:45 -08:00
b0d2fecf25 mux: plug some memory leaks on error
Make sure chunk->data and wpi are not leaked by
MuxAddFrameTileInternal() in case of MEMORY_ERROR in ChunkSetNth().

Change-Id: Ie20e84b92f4bdcb7c3b94520f36b20dd2e730545
2012-01-17 18:40:25 -08:00
f0d2c7a76f pass of cosmetics
Change-Id: Id031221b7499e8cfc460c873d0f8124c9bef3aa3
2012-01-17 18:32:27 -08:00
b309a6f901 fix Mach-O shared library build
Add extern to kChunks[] in muxi.h.
Fixes:
ld: duplicate symbol _kChunks in .libs/muxinternal.o and .libs/muxedit.o

Change-Id: Ibeb060f7fdec5fe904097a2443f0cda2f7ede884
2012-01-17 16:51:19 -08:00
241ddd38e2 doc: delete mux container pdf
The source is now webp-container-spec.txt.

Change-Id: I43debf616b7eec774b5e1586c286974c7332fb48
2012-01-17 12:54:51 -08:00
8b1ba272d2 doc: update VP8 decode guide link
The draft is now RFC6386.

Change-Id: Ief019357af5a5de9c6290cafd34db09d984f58aa
2012-01-17 12:52:27 -08:00
7e4371c5b3 WebPMuxCreate: fix unchecked malloc
Change-Id: Ic824cdfbede4abe8e5106904dd17d564bb1b32d4
2012-01-15 11:18:23 -08:00
eb425586e1 Merge "have makefile.unix clean up src/webp/*~ too" 2012-01-13 14:27:46 -08:00
a85c363186 Merge "correct EncodeAlpha documentation" 2012-01-13 14:27:03 -08:00
a33842fdb0 Merge "Update webp container spec with alpha filter options." 2012-01-13 14:25:39 -08:00
8d6490dae6 Incremental support for some of the mux APIs.
This CL adds incremental support for WebPMuxCreate() and
WebPMuxGetFeatures()

Change-Id: I312122f5e817d58366e18ae238cb9e2a493811fb
2012-01-13 14:47:53 +05:30
b8375abd08 have makefile.unix clean up src/webp/*~ too
Change-Id: Ida17b92346055b197fe6ccb60a9ac223ddd46f90
2012-01-12 18:49:29 -08:00
b5855fc78d correct EncodeAlpha documentation
The paeth filter was removed in 8ca2076

Change-Id: I743502147da4e0b5506e49382311b8f592973d41
2012-01-12 18:37:45 -08:00
dba37fea0e Update webp container spec with alpha filter options.
Change-Id: I032f350c8c698aeb139f7dd148f01a0a3b012b6d
2012-01-12 18:25:00 -08:00
2e74ec8b5f fix compile under MINGW
there was a type conflict around INT32 (in libjpeg).

Patch by nipmarsh
Issue 102: http://code.google.com/p/webp/issues/detail?id=102

Change-Id: I6425b6b9b9861bcaa8bb1adc8a78541e44031a6e
2012-01-12 04:53:30 -08:00
716d1d7f87 fix suboptimal MAX_LEN cut-off limit
MAX_LEN -> max_len
This was sub-optimal at the end of the picture, when there's
less than MAX_LEN bytes left to match.

Change-Id: I5ebe1fca4e7c112dcd34748a082d1c97f95eb099
2012-01-10 07:41:11 -08:00
57cab7b891 Harmonize the alpha-filter predictions at boundary
often reduces compressed size by ~10's of bytes
+ refactored / sped-up the prediction code (gradient: ~30% faster)

Change-Id: I26bd983655dad4f85d5c5ddc20a1980f384c4dd6
2012-01-10 03:21:13 -08:00
3a9895340f Merge "Fix bug for Alpha in RGBA_4444 color-mode." 2012-01-09 02:59:59 -08:00
8ca2076de1 Introduce a 'fast' alpha mode
.. where only 2 filtering modes are potentially
tried, instead of all of them. This is fast than the exhaustive 'best'
mode, and not much worse.

Options for cwebp are:
 -alpha_filter none
 -alpha_filter fast      (<- default)
 -alpha_filter best      (<- slow)

Change-Id: I8cb90ee11b8f981811e013ea4ad5bf72ba3ea7d4
2012-01-09 02:37:44 -08:00
221a06bb16 Fix bug for Alpha in RGBA_4444 color-mode.
Fix bug for Alpha data in RGBA_4444 color-mode.
The Alpha data is required to be clipped [0, 15] while
converting from 8 bits to 4 bits.

Change-Id: I80705d575c35121beb9633a05ec8823435c79586
2012-01-09 14:07:30 +05:30
ad1e163a0d cosmetics: normalize copyright headers
Change-Id: I5e2462b101e0447a4f15a1455c07131bc97a52dd
2012-01-06 14:49:06 -08:00
c77424d7eb cosmetics: light include cleanup
remove some unused includes

Change-Id: I07fabf707e8eac7f204757e68dab1057fd21aef1
2012-01-06 14:38:34 -08:00
9d0e17c9a9 fix msvc build breakage after 252028a
replace inline with WEBP_INLINE; inline is reserved for c++ code
w/visual studio

Change-Id: Ib06c6a12fd786701740d8b260d9aa310ee81fddf
2012-01-05 18:26:40 -08:00
7c4c177c39 Some readability fixes for mux library
Add a #define for UNDEFINED_CHUNK_SIZE and remove a misleading comment.

Change-Id: I5c56a12f1245e647f913c35c6a34d2e5d658415e
2012-01-05 17:53:51 +05:30
d8a47e66f7 Merge "Add predictive filtering option for Alpha." 2012-01-05 00:33:32 -08:00
252028aaac Add predictive filtering option for Alpha.
Add predictive filtering option for Alpha plane.
Valid range for filter option is [0, 5] corresponding to prediction
methods none, horizontal, vertical, gradient & paeth filter.
The prediction method 5 will try all the prediction methods (0 to 4)
and pick the prediction method that gives best compression.

Change-Id: I9244d4a9c5017501a9696c7cec5045f04c16d49b
2012-01-05 13:55:35 +05:30
9b69be1cdc Merge "Simplify mux library code" 2012-01-05 00:15:48 -08:00
a056170eca Simplify mux library code
Refactor mux code into Read APIs, Set/Delete APIs and internal
objects/utils.

Change-Id: Ia4ce32ec18cf0c1c75de9084fbb28840d46892b4
2012-01-05 12:23:08 +05:30
992187a380 improve log2 test
- add check for native log2 to configure
- use a common define (NOT_HAVE_LOG2) to enable use of local library
  version for non-autoconf platforms without their own version,
  currently msvc and android

This uses a negative (NOT_HAVE_) to simplify the ifdef

Change-Id: Id0610eed507f8bb9c5da338918112853d5c8127a
2012-01-04 18:49:37 -08:00
e852f83205 update Android.mk file list
Change-Id: Idffc497931c85582725e65f1d7b7384bcee0fdd5
2011-12-26 02:39:56 -08:00
a90cb2be6e reduce number of copies and mallocs in alpha plane enc/dec
Change-Id: Ice48d2dd403c18870567ee6e1b210b1eb3d5b44f
2011-12-23 01:21:53 -08:00
b1662b0530 fix some more type conversion warnings w/MSVC
API & memory related warnings will be dealt with separately

Change-Id: I8a7893baa4d5035c963fb3c16e0bb4eee742e968
2011-12-21 16:07:16 -08:00
223d8c60aa fix some uint64_t -> int conversion warnings with MSC
Change-Id: I5dc314c9d1a3cbda095be3c90886983500104867
2011-12-21 14:43:52 -08:00
c1a0437b87 Merge "simplify checks for enabling SSE2 code" 2011-12-20 17:42:59 -08:00
f06817aaea simplify checks for enabling SSE2 code
also fixes build issues under vs11 which has a native arm compiler for
windows 8 targets

Change-Id: Id76c2deae9fc9de147d13ad0d34edffcb5a726c4
2011-12-20 17:41:55 -08:00
948d4fe94f silence a msvc build warning
implicit double -> float conversion; avoiding sqrtf (c99) for
compatibility

Change-Id: If9b367dde237fc5173c1445cc60b16aa6ad2821c
2011-12-19 23:04:01 -08:00
911795490e vwebp: msvc build tweaks
snprintf -> _snprintf / remove double->float warnings

Change-Id: I5dcdc394cf7e2d37205beaf83ed0f80a18ec06ab
2011-12-16 19:30:33 -08:00
7937b409e7 simple WebP viewer, based on OpenGL
Quite handy and simple (for now).
It's not yet incorporated within the build system (autotools or
makefile.unix), because it gets complicated with OpenGL. TODO(later).

For now, there's some ready-to-use command line for compiling on Linux
or Mac in the header of vwebp.c

Later, this tool will be supplemented with support for animation,
tiling, zooming, etc.

Change-Id: I292972cea4862536afbe8c9ec444c590d152f086
2011-12-13 14:02:04 -08:00
6aac1df17b add a bunch of missing 'extern "C"'
Change-Id: I8c0ada049ce9fa7ef14164b90d58e999cdabba53
2011-12-13 10:51:32 -08:00
421eb99db3 Merge "Remove assigned-but-not-used variable "br"" 2011-12-08 10:41:18 -08:00
91e27f4573 better fitting names for upsampling functions
Change-Id: I816e81586c9e1a74ebc5516598dbd4ae0ddf48d8
2011-12-08 06:42:53 -08:00
a5d7ed5c4b Remove assigned-but-not-used variable "br"
Fixes gcc 4.6.x -Wunused-but-set-variable compiler warning:

	libtool: compile:  gcc -DHAVE_CONFIG_H -I. -I../.. -Wextra -Wall -Wunused-but-set-variable -MT libwebpdecode_la-idec.lo -MD -MP -MF .deps/libwebpdecode_la-idec.Tpo -c idec.c  -fPIC -DPIC -o .libs/libwebpdecode_la-idec.o
	idec.c: In function 'DecodeRemaining':
	idec.c:371:17: warning: variable 'br' set but not used [-Wunused-but-set-variable]

Change-Id: Ib037be9634b5b802ba9f1e2ef156a8fdf9630752
2011-12-08 15:42:01 +01:00
f62d2c9497 remove unused 'has_alpha' from VP8GetInfo() signature
alpha information is not to be found at RIFF chunks level, not
in the VP8 bitstream (that was a tmp hack)

Change-Id: Idd1629c696b03c26f6f30650d7216f627f1761df
2011-12-08 06:41:40 -08:00
08e865822a trap alpha-decoding error
Improves robustness to bad bitstream.

Change-Id: I87ca03ccd12d4d690904b35f8dfc2a20a28fb47b
2011-12-08 06:34:00 -08:00
b361eca1c5 add cut-off to arith coder probability update.
This speeds things up for long message, while not damaging
the stats too much for usual-sized cases

Change-Id: I3f45e28b771d701e2e1da11eb800de18c4ed12fc
2011-12-08 06:27:11 -08:00
8666a93aae Some bug-fixes for images with alpha.
- Fix the off-by-one diff when cropping with simple-filter.
- Fix a bug in incremental decoding in case of alpha.
- In VP8FinishRow(), do not decode alpha when y_start > y_end.
- Correct output of alpha channel for MODE_ARGB.
- Correct output of alpha channel for MODE_RGBA_4444.

Change-Id: I785763a2a704b973cc742ad93ffbb53699d1fc0a
2011-12-07 15:12:50 +05:30
273a12a013 fix off-by-1 diff in case cropping and simple filtering
Change-Id: I6dea172d0cf129f9986b8a3e1eea85fa97a70402
2011-12-05 08:37:55 -08:00
2f741d1e13 webpmux: ReadImage: fix ptr free in error case
allocate to temporaries and deal with output pointers in one place to
reduce casting.

Change-Id: Ib12d866440184315536f35a15eb5adeba7879ae7
2011-12-02 17:58:20 -08:00
721f3f48e7 fix alpha decode
- remove left-over WEBP_EXPERIMENTAL_FEATURES #ifdef

Change-Id: I2b91ccd2e2b3ebea63d5f698f90206feec30a4db
2011-12-02 11:00:27 -08:00
60942c8cea fix the has_alpha_ order
Change-Id: I26211732584f6181bf763497818b45515e394c21
2011-12-02 10:26:42 -08:00
30971c9e95 Implement progress report (and user abort)
New cwebp flag is -progress

Change-Id: Ied872cca13f512036860783bbee1bdbccad72768
2011-12-01 14:19:40 -08:00
eda520a92e cosmetics after 9523f2a
spelling, indent and other style conformance

Change-Id: Iad720c0d85f2147676e302439d57628712d3b109
2011-12-01 13:05:31 -08:00
38bd5bb524 Merge "Better alpha support in webpmux binary" 2011-12-01 06:01:33 -08:00
ccbaebfe30 Merge "Updated the includes to relative paths." 2011-12-01 04:20:46 -08:00
d71fbdcca3 fix small typo in error message array
Change-Id: If34537e53cc56b5f5daa15afaefb1f49d11602f5
2011-12-01 03:34:22 -08:00
cdf97aa265 Better alpha support in webpmux binary
- Support for adding/getting frames/tiles with alpha in webpmux
- For "-info" option in webpmux binary, add alpha related info

Change-Id: Iccd2fd35ab8453dabd74779f12f2844ab76d0538
2011-12-01 16:15:57 +05:30
885f25bc83 Updated the includes to relative paths.
Change-Id: I0ea1a59dd0f6cb1df9f41e048e0c5a13e7fb8335
2011-12-01 15:30:41 +05:30
a0ec9aace9 Update WebP encoder (cwebp) to support Alpha.
Updated cwebp (Webp Encoder) binary to support Alpha encoding.
Modified man page and WebP container spec appropriately.

Change-Id: I52f6a5cb3e870c386591e9a7776293fa6a8fb04b
2011-12-01 15:13:17 +05:30
667b769aee Fixed the include for types.h within mux.h
Made the include (for types.h) to relative path w.r.t mux.h

Change-Id: Ifb2a36557d7c8b63490738a2cc48e03993d24639
2011-12-01 13:47:32 +05:30
9523f2a5de Add Alpha Encode support from WebPEncode.
Extend WebP Encode functionality to encode Alpha data and produce
bit-stream (RIFF+VP8X+ALPH+VP8) corresponding to WebP-Alpha.

Change-Id: I983b4cd97be94a86a8e6d03b3b9c728db851bf48
2011-12-01 12:15:58 +05:30
16612ddd30 Merge "Add Alpha Decode support from WebPDecode." 2011-11-30 22:02:03 -08:00
d117a94046 Add Alpha Decode support from WebPDecode.
Extend WebP decode functionality to extract Alpha data (support ALPH
chunk) and decode the Alpha plane using Alpha (utils/alpha) core-lib.

Change-Id: I6f0ee1b189c13caba3c1dd9b681383bfd00aa212
2011-12-01 11:24:50 +05:30
67228734dc cosmetics after e1947a9
indent / spelling / line length & a couple missing consts

Change-Id: Id282cb7bc6881d4738a3d9fa912b5b22a007c4d2
2011-11-30 18:51:20 -08:00
e1947a9299 Add Alpha encode/decode code.
Add code for Alpha encoding & decoding. The alpha compression is done
via backward reference counts encoded with Arithmetic encoder (TCoder).
Also provided is lossy Alpha pre-processing option via level-quantizations
using kNN heuristic.

Change-Id: Ib6b13530c1a4ab6493edcb586ad29fe242bc1766
2011-11-30 17:53:09 +05:30
afc4c5d695 simplify code by introducing a CopyPlane() helper func
Change-Id: Id1a2a5d8a3bf48cf614213442c1386a77c0d6880
2011-11-23 18:00:39 -08:00
113b312881 Merge "MUX API Updates" 2011-11-23 05:58:02 -08:00
c398f59536 MUX API Updates
- Add alpha support in mux.
- Remove WebPMuxAddNamedData() and WebPMuxGetNamedData() APIs. Add WebPMuxSetImage(), WebPmuxGetImage() and WebPMuxDeleteImage() APIs instead.
- Refactor code using WebPImage struct.
- Corresponding changes in webpmux binary.
- WebPMuxSetImage()/AddFrame()/AddTile() can now work with data which starts from "RIFF...". This simplifies reading a single-image webp file and adding it as an image/frame/tile in mux.

Change-Id: I7d98a6407dfe55c84a682ef7e46bc622f5a6f8d9
2011-11-23 19:03:13 +05:30
5acf04ef8c remove orphan source file
similar to 8962030 enc/enc_sse2.c became a part of dsp/ w/e06ac08.

Change-Id: Ia0cef3133e3f8ec5da0bd7a5172c22e86f1d41cb
2011-11-19 11:01:19 -08:00
059f03ef99 Merge "dec: validate colorspace before using as array index" 2011-11-17 10:24:59 -08:00
70a0398988 Merge "factorize some code" 2011-11-16 19:14:49 -08:00
9b243b3db0 factorize some code
Change-Id: Iac4cf0cf05888b7dd6613028dac619d8f5b0501b
2011-11-16 19:00:27 -08:00
372e2b463b Correct a bug in ReadPNG() with GRAY_ALPHA images
Change-Id: I4676160ee544ed914cc0de3f9cd140d9ee65addc
2011-11-16 18:56:23 -08:00
469d6eb974 Merge "Makefile.am: remove redundant noinst_HEADERS" 2011-11-16 18:41:55 -08:00
9fe3372f19 dec: validate colorspace before using as array index
Change-Id: I5bcf01769d58d39a5f8d50f54cf0cd83a2309602
2011-11-16 18:21:56 -08:00
8962030f52 remove orphan source file
enc/enc.c became a part of dsp/ w/e06ac08.

Change-Id: I9e99aa6eac7b28162f58f3f0dc180a68a279d136
2011-11-14 19:31:02 -08:00
ced3e3f4e0 Makefile.am: remove redundant noinst_HEADERS
When they appear in _SOURCES they won't be installed [1].

[1]: http://www.gnu.org/software/automake/manual/automake.html#Headers

Change-Id: I14fd816294682e7bd0fccefd6428e1526c9470d8
2011-11-11 16:29:32 -08:00
964387ed19 use WEBP_INLINE for inline function declarations
removes a #define inline, objectionable in certain projects

Change-Id: Iebe0ce0b25a030756304d402679ef769e5f854d1
2011-11-11 10:53:58 -08:00
90880a11b4 Merge "manpages: break long lines" 2011-11-09 19:12:32 -08:00
b5910895ed Merge "manpages: minor formatting updates" 2011-11-09 19:11:56 -08:00
4c451e4a34 Merge "Rectify the Chunk parsing logic." 2011-11-09 19:09:57 -08:00
04e84cf1f1 examples: slight cleanup
spelling/indent/condense a few lines
removal/restriction of extern "C" usage
add const where applicable

Change-Id: Idd49b3498b1d7fc391724b4cde63706022217cb0
2011-11-04 15:30:28 -07:00
099717ce92 manpages: break long lines
Change-Id: I3bea93d358e5c3b3f7dd3c91e433ab4f817d1cd8
2011-11-04 11:25:43 -07:00
1daf39bbbc manpages: minor formatting updates
escape '-'s
use consistent section names
webpmux.1:
 document -loop
 create subsections for each OPTION group

Change-Id: If41dc24d80e4a662024e82697d8d2cc4e194a35d
2011-11-04 11:20:59 -07:00
abd030b573 fix missing "(void)" in function signature
Change-Id: I7edfc36174b6d16df909594c2693e75a09e1ac13
2011-11-01 06:24:34 -07:00
f6a7d75885 remove useless test
Change-Id: I1b31842ddf719ddcc185a5d6a5032a20d5e593e2
2011-11-01 05:18:46 -07:00
f07b2138cd Rectify the Chunk parsing logic.
For odd-sized chunk-payload, there's one Byte padding at the end to make the
next chunk start at even-address. The chunk-skip logic needs to be updated to
handle such cases.

Change-Id: I8939ed07584a6195092fbe703eb0ea711fa5f153
2011-10-31 18:47:33 -07:00
b8634f7d8f webpmux: fix lib link order
fixes static link (--disable-shared)

Change-Id: Ife926179490954a1d966d2deb97dd366a9d0dacd
2011-10-28 18:11:00 -07:00
42c2e682e0 Fix missing coma (on uncompiled code)
Spotted by Jakub, Thanks!

Change-Id: Ic2509acc683690748089b831ee3d109ad2162dc2
2011-10-27 06:37:36 -07:00
d8329d41e3 Android.mk: add missing source files
Fell out of date with some of the dsp.c moves.
Fixes Issue #93.

Change-Id: I2fb4424dbb0bc31af236cef2bed5ee542622067b
2011-10-19 20:02:23 -07:00
13a54df529 Merge "More aggressive copy-edit; add TODO; validate HTML5" 2011-10-12 15:59:30 -07:00
868b96aef4 More aggressive copy-edit; add TODO; validate HTML5
Change-Id: I45e7fde3eb33067274b5d454451f1bf8785511fd
2011-10-12 15:54:02 -07:00
767afea250 configure: check for a symbol contained in libpng
rather than 'main'. this fixes mis-detection when cross compiling.

Change-Id: I9560ca4805ef9eea5bd7370aeef2dcf6ed293478
2011-10-07 19:44:03 -07:00
408b8918c1 Merge "Linewrap at 72 cols. Casual copy-edit." 2011-10-07 17:50:31 -07:00
3ae318c770 Merge "Restore (most) emphasis; add emphasis to normative RFC 2119 terms (MUST, etc.)" 2011-10-07 16:07:41 -07:00
918eb2d822 Merge "Basic container doc source clean-up; fix lists and pseudocode blocks." 2011-10-07 15:15:36 -07:00
03bec9e0c0 Linewrap at 72 cols. Casual copy-edit.
Change-Id: Iebecff7eb0a64080eab456f903afacca178d9d59
2011-10-07 14:37:54 -07:00
2678d819a4 Restore (most) emphasis; add emphasis to normative
RFC 2119 terms (MUST, etc.)

Change-Id: Ia07a64dd4eadebfe9ba8a98a4eef613d1b5d614a
2011-10-07 14:31:43 -07:00
428674dad1 Basic container doc source clean-up; fix lists and pseudocode blocks.
Add some furniture (README, template).

Change-Id: Ida154a625fe7013a1a759d16f11fd7ccd867c25d
2011-10-07 14:28:18 -07:00
6a77d92835 Merge "Makefile.vc: cosmetics" 2011-10-05 12:16:24 -07:00
28c38e8c8f Merge "Makefile.vc: condense directory creation rules" 2011-10-05 12:14:06 -07:00
55be2cf878 Initial import of container spec document, from pdftotext transform.
new file:   doc/webp-container-spec.txt

Change-Id: I60b97d6f0219f0041c92b6d980cd8ebae8ae4ca5
2011-10-04 16:27:59 -07:00
a82a788ba0 Makefile.vc: cosmetics
- break long lines
- detab variable assignments
- sort object names

Change-Id: I33a210e617552a97c36ac3b1e255af4c7f2b0e35
2011-10-04 13:46:09 -07:00
c8f41ce54e Makefile.vc: condense directory creation rules
Change-Id: I39fb8278f17498998f8a9cf022a548e0735b1d11
2011-10-04 13:39:39 -07:00
2b877cd0c8 Some fixes to Makefile.vc to support the src\mux directory.
Change-Id: I5a4a3087032dc1d5f75750b2db2a3092d39f8fc0
2011-10-01 23:47:58 +02:00
3eb969b3ed Merge "Add Makefile.vc for Mux library & binary." 2011-09-30 03:55:11 -07:00
e78e971e98 Add Makefile.vc for Mux library & binary.
Add Makefile.vc for Windows platform to build Mux library and example
command line tool.

Change-Id: Ic9e2290feda0ae3e2f2fb3c5f8d46e79eada71a3
2011-09-30 16:05:33 +05:30
6aedde5891 Add manual for WebPMux tool.
This change adds manual page for the command-line tool webpmux.

Change-Id: I01aed259c9db4bc605433f528a7deff4f5292fbe
2011-09-30 14:04:54 +05:30
8a360d0a69 Merge "Added WebPMux Binary." 2011-09-30 00:43:27 -07:00
a4f32caef4 Added WebPMux Binary.
This change adds a command line tool (webpmux) which uses MUX library
for manipulating WebP Mux container. This tool can be used to create a
WebP container file and extract/strip relevant data from the container
file.

Change-Id: If17818239448a428703760747fc84f77586045e4
2011-09-30 12:46:29 +05:30
f3bf4c769f Added Mux Container Spec & README for MUX-API.
Added the Mux Container Spec (RIFF structure) for the features supported
(Color Profile, XMP Metadata, Animation & Tiling) via WebP Mux. Also
added README file with example psudo code for using the Mux API(s) and a
short description on webpmux (comand line tool, planned to be pushed out
in subsequent Git change).

Change-Id: I87c322cada89955bd758dd524a862a8cbc407541
2011-09-30 10:51:35 +05:30
9f761cfae9 Changed function signature for WebPMuxCreate
Changed function signature of method WebPMuxCreate and few other minor nits.
Header file has been re-organised to have declaration of set/get/Delete
methods for different use-cases (Metadata, ColorProfile etc) in one place
instead of declaring all Set methods together followed by Get & Delete.

Change-Id: I52f6dffd216b1c343423d55a5b45fa1b9b9c1347
2011-09-29 10:58:40 +05:30
5f31b5ec64 Merge "Add Mux library for manipulating WebP container." 2011-09-27 11:55:45 -07:00
2315785f2c Add Mux library for manipulating WebP container.
This change adds the WebP Mux library for manipulating the WebP Mux
Container. The library document and command line tool exhibiting the
usage of this libary will follow in subsequent Git change.

Change-Id: I4cba7dd12307483185ad5a68df33af6c36c154c8
2011-09-27 14:14:46 +05:30
7e198abb48 update ChangeLog
Change-Id: I3bd7347337323f727a979dccadddfd22f56ec1c2
2011-09-22 13:51:57 -07:00
dfc9c1eaef Harmonize the dates
Change-Id: I6c6f4766bc217ab0bd2fa6520ce9e2c1cd742b44
2011-09-22 13:50:10 -07:00
28ad70c56d Fix PNG decoding bug
some png with palette-based alpha channels were incorrectly
treated as alpha-less, causing segfault.

Change-Id: I03883590f9539848d5135d359b6f105d2b14329f
2011-09-20 07:59:43 -07:00
846e93c5d1 Update AUTHORS & add .mailmap
Change-Id: I2dd07820cae50c85695da7c40b05780ffeef434a
2011-09-16 14:33:38 -07:00
563e52d62e cosmetics after '76036f5 Refactor decoder library'
reference 'VP8X' consistently / spelling
sort header size defines alphabetically on their logical boundaries
drop useless cast
const updates

Change-Id: I9409814c5b89773ae8910dc74887f91435e6ac82
2011-09-16 12:32:03 -07:00
76036f547e Refactor decoder library
- Move common defines to dec/webpi.h
 - Regularize naming and parameters of various "CheckAndSkip" functions.
   Also they return VP8StatusCode for clarity.
 - Move WebP header/chunk parsing functions to webpi.h
 - Fix a bug in static function GetFeatures()

Change-Id: Ibc3da4ba210d860551724dc40741959750d66b89
2011-09-16 10:55:24 -07:00
377ef43c3e configure.ac: update AC_INIT params
change package name to libwebp, correct version and add bug & project
urls

Change-Id: I3b980ab8088729f90794ffd1ac7b33383983c812
2011-09-13 18:37:11 -07:00
7a8d8762c1 use a user-visible MACRO for max width/height.
This has been pointed as a useful information to have in the header (for
the non VP8-specs savvy ones)

Change-Id: I494b1da41dfafce882a94e3677d1cd6206bc504b
2011-09-13 16:07:30 -07:00
d4e9f5598d NEON decode support in WebP
Change-Id: I0d6fa456ca68468353adcd64669f1737d1446f65
2011-09-13 16:00:47 -07:00
0ee683b593 update libtool version-info
consistent with:
  http://www.gnu.org/software/libtool/manual/libtool.html#Versioning

current=2 matches the ABI version for both encode & decode

Change-Id: Ie175b2bdb8f5e14690f4cf6357fc0e0c6c78fe7d
2011-09-13 15:49:13 -07:00
fdbe02c581 windows: match _cond_destroy logic w/return variable name
CloseHandle returns non-zero on success so earlier versions would leave
'ok' with a misleading value, though the return itself was correct.

Change-Id: I21b74a59d90f7bf1b484a55f3960962e933f577b
2011-09-13 15:48:33 -07:00
206b686b39 README: correct advanced decode api pseudo-code
Change-Id: I09e5365cc15cb9b6c53a1d5d4e16a51bfc353b10
2011-09-13 15:47:53 -07:00
6a32a0f5bf make VP8BitReader a typedef, for better re-use
Change-Id: Id91f8c5649f9fd078facc9f280a314377193b5e8
2011-09-13 15:47:24 -07:00
b112e83647 create a libwebputils under src/utils
with bit_reader bit_writer and thread for now.

Change-Id: If961933fcfc43e60220913fe4d527230ba8f46bb
2011-09-13 15:34:15 -07:00
ee697d9fc9 harmonize the include guards and #endif comments 2011-09-13 15:31:52 -07:00
a1ec07a618 Fixing compiler error in non x86 arch.
Compiler is not getting the definition of NULL.

Change-Id: I521a99c715bb43e633abd4a26d73ad25bbbafc94
2011-09-13 15:27:58 -07:00
dcfa509a28 Fixed recursive inclusion of bit_writer.h and vp8enci.h.
Was getting compiler error when I included bit_writer.h from non libwebp
directory. bit_writer.h includes vp8enci.h and that uses VP8BitWriter without
having it's definition.

Change-Id: I1ca82594292979b9eb7e60e2fffb22c16768dd30
2011-09-13 15:26:39 -07:00
e06ac0887f create a separate libwebpdsp under src/dsp
Gathers all DSP-related function (and SSE2 implementations).
Clean-up some unwanted symbolic dependencies so that webp_encode,
webp_decode and webp_dsp are truly independent libraries.

+ opportunistic clean-up:
  * remove unneeded VP8DspInitTables(), now integrated in VP8DspInit()
  * make consistent use of VP8GetCPUInfo() in the various DspInit() funcs
  * change OUT macro to DST
2011-09-13 12:29:44 -07:00
ebeb412aa5 use unsigned int for bitfields
uint8_t is a gcc extension which msvc similarly supports, but for
greater compatibility, and to match the change already made in
dec/vp8i.h, update the remaining bitfield to use unsigned int.

Change-Id: Id9dca470345871e00e82893255a306dfe5d3fa29
2011-09-13 12:19:00 -07:00
341cc56a8c make kNewRange a static array
Change-Id: I78096e2a28e6f732e13df6bde790a1266053838c
2011-09-13 11:51:32 -07:00
227a91e522 README: minor wording update
Change-Id: I2683f9d8a00a476ccb90bef911804378ec6a5558
2011-08-30 17:27:46 -07:00
05bd8e6af5 add man pages to dist
converted to text & html and stored in doc/

Change-Id: I42572bc6f93ffe5270f3ff1b13ca150292fcede4
2011-08-30 14:31:00 -07:00
812dfa1ae1 bump up versions in preparations for 0.1.3
Change-Id: Icbadada515a5be7810473ff530565c2cb4fb904d
2011-08-29 22:52:47 -07:00
a5b78c81b5 wrap alpha-related options under WEBP_EXPERIMENTAL_FEATURES flag
Change-Id: I6d8f4b4ec7dca53054e28b969a536e7c93c1e5e2
2011-08-29 22:04:46 -07:00
34dc790798 regen ChangeLog for 0.1.3-rc2
update AUTHORS as well

Change-Id: If24bb6366ed7458c21141566f951cf0e86ba3398
2011-08-29 18:42:53 -07:00
7c43663036 Silence some (more) Visual Studio warnings.
Change-Id: Idac44feac894ab13630e032222c4744d6fa785df
2011-08-29 18:08:26 -07:00
60306e8cf3 add top-level gitattributes
ignore .gitignore/.gitattributes when using git-archive

Change-Id: I14f5d0c756298fc48613859c93d16586dfb34855
2011-08-29 17:47:13 -07:00
2aa6b80efe Slience some Visual Studio warnings.
Change-Id: I62078af80bfcaa82bdc165fc2fc8fce2d2aad862
2011-08-29 10:37:13 +02:00
4cbbb2901b Merge "bump up version for next freeze" 2011-08-26 16:24:23 -07:00
a329167426 bump up version for next freeze 2011-08-26 16:23:14 -07:00
c7e86abab6 cosmetics: fix comment line lengths
add additional '-' to //----... style comments globally instead of
polluting further commits

Change-Id: I951acc68b7b5384b4d6e235349b0067d1aa6fa8b
2011-08-26 12:19:33 -07:00
c9e037ab3e makefile.unix: add simple dist target
Change-Id: I31647a97f5892b2dbdc9f4555ea38e2824ac3788
2011-08-25 21:33:28 -04:00
87d58ce9cd makefile.unix: rule maintenance
- use built-in variables where appropriate
- fix some target dependencies

Change-Id: I33584d0e7d9c5341841da89b6aa8f02e1c7c6aea
2011-08-25 20:36:04 -04:00
d477de7759 mend 2011-08-25 10:06:50 +05:30
fac15ec78e Update NEWS & README for next release V0.1.3
Update ChangeLog, NEWS & README file for next release V0.1.3
2011-08-25 09:11:08 +05:30
6215595cd1 Merge "add a -partition_limit option to limit the number of bits used by intra4x4" 2011-08-23 16:09:10 -07:00
3814b76c48 Merge "reorganize chunk-parsing code" 2011-08-23 16:03:05 -07:00
900286e091 add a -partition_limit option to limit the number of bits used by intra4x4
Although it degrades quality, this option is useful to avoid the 512k
limit for partition #0.
If not enough to reach the lower bound of 4bits per macroblock header,
one should also limit the number of segments used (down to -segments 1)

See the man file for extra details.

Change-Id: Ia59ffac13176c85b809ddd6340d37b54ee9487ea
2011-08-23 15:58:22 -07:00
cd12b4b0ac add the missing cost for I4/I16 mode selection
was missing from the RD-computation of intra-4x4 score.
Doesn't change anything significantly, it's just More Correct.

Change-Id: I25c5b53a810d97e6fb7f98c549fd23bbe55e1bf4
2011-08-18 20:48:06 -07:00
dfcc2136e1 reorganize chunk-parsing code
make room for future VP8X extensions

Change-Id: Ic78217c26f142403b733740b17980aa81602f83d
2011-08-18 11:07:13 -07:00
3cf2030653 initialize pointers to function within VP8DspInit()
makes testing easier, allowing a reset to C-version

Change-Id: I707d8338fedff4ae993e52eefe730c236ca3dcb5
2011-08-18 10:03:19 -07:00
d21b479581 Merge "windows: add decode threading support" 2011-08-05 16:31:50 -07:00
473ae95324 fix hang on thread creation failure
with assertions enabled the code would abort in
WebPWorkerChangeState with:
Assertion `worker->status_ >= OK'

without them the code would hang in the _cond_wait.

this change makes WebPWorkerChangeState a no-op in this case.

Change-Id: Iea855568bbdef2865ae61ab54473b3a7c230e91a
2011-08-05 15:01:16 -07:00
fccca4202f windows: add decode threading support
Change-Id: Iad923550569ceec1ff469852ec68e66de3f6062b
2011-08-05 12:28:40 -07:00
a31f843a9f Use the exact PNG_INCLUDES/PNG_LIBS when testing for -lpng
(and same for jpeg)
fixes issue #87

Change-Id: I857a828058f9653be21fe97437bf5a0d2c30835e
2011-08-02 11:58:02 -07:00
ad9b45f1c8 Merge "Makefile.vc: rule maintenance" 2011-07-22 18:57:57 -07:00
565a2cab22 Makefile.vc: rule maintenance
Remove the bulk of xcopys from the TARGET rule as things are built to
the correct location.
Allow the clean rule to be appended and only delete DLLINC for dll
builds to avoid prompting by erase when it's undefined.

Change-Id: If88b2c68090099777b8be9f3a5fbde2c25ed66a6
2011-07-22 18:56:36 -07:00
2d0da681fb makefile.unix: disable Wvla by default
bad merge from fc7815d restored the flag.

Change-Id: Ifbc6c5f78f80934c0ddd26bcd2ea8ea110ab6385
2011-07-22 18:52:17 -07:00
fc7815d692 multi-thread decoding: ~25-30% faster
To be enabled with the flag WEBP_USE_THREAD.
For now it's only available on unix (pthread), when using Makefile.unix
Will be switched on more generally later.

In-loop filtering and output (=rescaling/yuv->rgb conversion)
is done in parallel to bitstream decoding, lagging 1 row behind.

Example:
examples/dwebp bryce.webp -v
Time to decode picture: 0.680s

examples/dwebp bryce.webp -v -mt
Time to decode picture: 0.515s

Change-Id: Ic30a897423137a3bdace9c4e30465ef758fe53f2
2011-07-22 15:14:18 -07:00
acd8ba4229 io->teardown() was not always called upon error
Change-Id: I8317139b583124fc20754b9b19aa4dba51cd05af
2011-07-20 07:49:57 -07:00
c85527b1ae Merge "Makefile.vc: add DLL configs" 2011-07-19 13:38:45 -07:00
e1e9be3502 cosmetics: spelling/grammar in README and lib headers
Change-Id: Ib8648adf652d29dd38887e5e07b09b4aa3965c6e
2011-07-15 18:58:56 -07:00
b4d0ef8f58 Makefile.vc: add DLL configs
(release|debug)-dynamic
These configurations will produce a dll in bin/ and an import lib under
lib/.
Currently the -noasm switch in the examples will be disabled for these
builds due to a dependency on VP8EncGetCPUInfo.

Change-Id: I2cbac0064f0e500698d14ffc03200791ca837090
2011-07-15 15:25:02 -07:00
998754a734 remove unused nb_i4_ and nb_i16_ fields.
Change-Id: Idf361e5528bddb3b25f3bc12502fdfd5c4cf9149
2011-07-15 14:57:07 -07:00
9f01ce3afa rename WebPDecBuffer::memory -> private_memory
This makes it clear that it shouldn't be used externally.

Change-Id: I10c04c6606abbe851b6a3b424832803e842b2057
2011-07-15 14:49:01 -07:00
fb5d659bbd fix an overflow bug in LUT calculation
round(clip()) != clip(round())

Change-Id: Ia53f845b62e01bce672456cb7cdf8581f1a7ce44
2011-07-14 22:22:46 -07:00
d646d5c743 swig: add WebPDecodeARGB
Change-Id: I6f22cf0f87a7274f2ed63e4aa96267a8155a5e35
2011-07-14 19:05:55 -07:00
78aeed4088 add missing WebPDecodeARGBInto() and switch ARGB4444 to RGBA4444 as was intended 2011-07-14 11:41:23 -07:00
cd7c5292e9 explicitly mark library functions as extern
Add WEBP_EXTERN(type) macro which should make Windows DLL builds simpler
by allowing the signature to be changed.

Change-Id: I0cfa45dff779985680b1a38ddff30973a0d26639
2011-07-13 17:48:39 -07:00
19db59f80f add support for RGB565, ARGB4444 and ARGB colorspace (decoder)
RGB565 and ARGB4444 are only supported through the advanced decoding API.
ARGB being somewhat generic, there's an easy WebPDecodeARGB()
new function for convenience.

Patch by Vikas Arora (vikaas dot arora at gmail dot com)

Change-Id: Ic7b6f72bd70aca458d14e7fdd23679212430ebca
2011-07-13 09:08:58 -07:00
c915fb2aa7 encoder speed-up: hardcode special level values
1-3% faster

Change-Id: Ib2131989fbf819bcbfa6456adbeea0ba27c914f7
2011-07-12 18:21:22 -07:00
c558bdad28 Rename and improve the API to retrieve decoded area
Change-Id: Iec7e0a1361c27dcf2dc8445170ab5b400454fce9
2011-07-12 13:59:51 -07:00
bf599d74a4 Merge "makefile.unix: disable -Wvla by default" 2011-07-12 13:38:10 -07:00
c9ea03d770 SSE2 version of strong filtering
~10% faster decoding
Patch by Somnath Banerjee (somnath at google dot com)

Change-Id: I10e380c036ff61afe24afc26084a508ab01e8502
2011-07-11 23:04:26 -07:00
993af3e29a makefile.unix: disable -Wvla by default
Rather than add bulk to test for the new flag, simply comment out -Wvla
to keep the base makefile simple.
-Wvla was added in gcc-4.3.0.

Change-Id: I21feb456d7498ea628defb436a50c3d828e7f971
2011-07-08 21:23:27 -04:00
3827e1bce4 Merge "examples: (windows/WIC) add alpha support" 2011-07-08 14:10:17 -07:00
e291fae0fc SSE2 functions for the fancy upsampler.
~5-10% faster.
Heavy 8bit arithmetic trickery!
Patch by Somnath Banerjee (somnath at google dot com)

Change-Id: I9fd2c511d9f631e9cf4b008c46127b49fb527b47
2011-07-07 18:12:53 -07:00
a06bbe2e80 add WebPISetIOHooks() to set some custom hooks on the incremental decoder object.
Change-Id: I01e973a1e45e3d60dc11fd284df3cbb938cf0485
2011-07-07 16:38:03 -07:00
7643a6f2ef Merge "makefile.unix: use uname to detect OSX environment" 2011-07-07 16:29:25 -07:00
5142a0be3a export alpha channel (if present) when dumping to PGM format
Change-Id: Ica1818937fa03b29a749887d28f49fe675c8b1db
2011-07-07 16:08:15 -07:00
14d5731c7e makefile.unix: use uname to detect OSX environment
HOSTTYPE is x86_64 on e.g.,
bash 3.2.48(1)-release
ProductName:	Mac OS X
ProductVersion:	10.6.7
BuildVersion:	10J869

intel-mac seems to be the value under tcsh.

Change-Id: I814ad6d3b733933057cea605917b185ff6d423d0
2011-06-24 21:29:59 -04:00
0805706252 examples: quiet warnings
When WEBP_HAVE_(JPEG|PNG) were undefined the stub functions would
produce warnings for unused parameters.

Change-Id: I79b2457c769d1f9382be834162de019c5427f94b
2011-06-24 16:50:02 -04:00
3cfe0888ae examples: (windows/WIC) add alpha support
Portions based on a patch by Ismail Keskin (iskeskin at gmail dot com)
Fixes issue #83.

Change-Id: Ib54188910354240a2731b0a3a3d0915d17af2233
2011-06-22 12:01:48 -07:00
13ed94b8ad add compile warning for variable-length-array 2011-06-20 17:42:25 -07:00
5a18eb1a31 Merge "add Advanced Decoding Interface" 2011-06-20 16:30:01 -07:00
5c4f27f9f5 add missing \n 2011-06-20 15:47:35 -07:00
f4c4e416c0 80 cols fix 2011-06-20 15:39:40 -07:00
d260310511 add Advanced Decoding Interface
You can now use WebPDecBuffer, WebPBitstreamFeatures and WebPDecoderOptions
to have better control over the decoding process (and the speed/quality tradeoff).

WebPDecoderOptions allow to:
 - turn fancy upsampler on/off
 - turn in-loop filter on/off
 - perform on-the-fly cropping
 - perform on the-fly rescale
(and more to come. Not all features are implemented yet).

On-the-fly cropping and scaling allow to save quite some memory
(as the decoding operation will now scale with the output's size, not
the input's one). It saves some CPU too (since for instance,
in-loop filtering is partially turned off where it doesn't matter,
and some YUV->RGB conversion operations are ommitted too).

The scaler uses summed area, so is mainly meant to be used for
downscaling (like: for generating thumbnails or previews).

Incremental decoding works with these new options.
More doc to come soon.

dwebp is now using the new decoding interface, with the new flags:
  -nofancy
  -nofilter
  -crop top left width height
  -scale width height

Change-Id: I08baf2fa291941686f4ef70a9cc2e4137874e85e
2011-06-20 15:30:52 -07:00
bd2f65f67c sse2 version of the complex filter
12-15% faster.
(only inner edge is implemented for now)

patch by Somnath Banerjee (somnath at google dot com)
2011-06-20 00:27:47 -07:00
96ed9ce0fb perform two idct transforms at a time when possible
patch by Christian Duvivier (cduvivier at google dot com)
2011-06-20 00:22:37 -07:00
01af7b69cd use aligned stored 2011-06-18 08:27:16 -07:00
0e1d1fdfe0 Merge "Makefile.vc: add experimental target" 2011-06-17 18:34:29 -07:00
2a1292a61f Makefile.vc: add experimental target
Defines WEBP_EXPERIMENTAL_FEATURES for the build.

Change-Id: I1f118ca07018a92bfdf86f562781971d4382fc6e
2011-06-17 18:32:15 -07:00
23bf351e71 Enable decode SSE2 for Visual Studio
Change-Id: If32f8b1cfe415b2f9330af36a5dd0e31e49582b2
2011-06-17 18:12:01 -07:00
131a4b7b7b dec/dsp_sse2: fix visual studio compile
This addresses issue #80

Change-Id: Ia81ae21f85266dd64d39da63ff2fae33f9a572dc
2011-06-17 18:04:08 -07:00
00d9d6807c swig: file reorganization
Rather than %include'ing decode.h and potentially pickup new
(unsupported functions), explicitly list the desired functions as with
encode.
Reorganize a bit to contain most of the language specific additions to
one area. This fixes the visibility of the wrap_* functions in java. The
method modifiers need to come before the function prototypes.

Change-Id: I595df4d1a60edcb263923b5a2621879d3b6233cf
2011-06-17 14:32:15 -07:00
7fc7e0d9eb Merge "swig/java: basic encode support" 2011-06-16 13:45:50 -07:00
3be57b166f fix MSVC compile for WEBP_EXPERIMENTAL_FEATURES
patch by Ismail Keskin (iskeskin at gmail dot com)
fixes issue #82
2011-06-16 13:33:07 -07:00
40a7e347ff dec/dsp: disable sse2 for Visual Studio builds
This is a temporary workaround for issue #80.

Currently dec/dsp_sse2 is not included in Makefile.vc. Simply adding it
will cause a build error, however, as cl does not support aligning
function parameters producing, e.g.,
src\dec\dsp_sse2.c(228) : error C2719: 'q1': formal parameter with
__declspec(align('16')) won't be aligned

Change-Id: Id29e6802dd29110e59c4f6d13ffa5d4793c750a0
2011-06-15 13:53:14 -07:00
e4d540c842 add SSE2 code for transform
Pretty similar to the encoder's version
3% faster decoding on average

patch by Christian Duvivier (cduvivier at google dot com)
2011-06-15 10:51:31 -07:00
54f2170a15 swig/java: basic encode support
Wrap WebPEncode???* to provide an interface similar to decode.
As only WebPGetEncoderVersion is wrapped directly from encode.h avoid
including it in the swig file to reduce %ignore's.
This change also removes unnecessary incremental decoding related enums.

Change-Id: I0b5424026aa6ae012c6a29ad2f2301c2681ca301
2011-06-15 10:37:53 -07:00
c5d4584b2c call function pointers instead of C-version
will potentially call SSE2 version instead of the plain-C one
catch by Christian Duvivier (cduvivier at google dot com)
2011-06-14 18:57:50 -07:00
ea43f045b5 Merge "configure: mingw32 targets: test for WIC support" 2011-06-10 16:11:51 -07:00
a11009d7fc SSE2 version of simple in-loop filtering
~10% faster decoding

Patch by Somnath Banerjee (somnath at google dot com)

Change-Id: I200db408272b4f61cda9d9261d2d4370a698d6c4
2011-06-10 15:10:18 -07:00
42548da9e3 shave one unneeded filter-cache line
There was 1 unneeded sample line allocated for the filter cache in of simple filtering.
+ Add an explaining comment.

Change-Id: I775a596c8b8643e773e0eade8aa341dc23fb290f
2011-06-09 12:08:08 -07:00
31f9dc6fdd configure: mingw32 targets: test for WIC support
Replace usage of _WIN32 in examples as this does not guarantee the
presence of wincodec.h.
mingw-w64 notably includes wincodec.h, though other releases do not.

Under cygwin the following can be used for a WIC enabled binary:
./configure --target=i686-pc-mingw32 CC=i686-w64-mingw32-gcc.exe

Change-Id: Ica6a714c3356a8eaf88486a1c3f5aa6adde394c0
2011-06-08 11:32:41 -07:00
1955969925 Merge "split expression in two." 2011-06-08 09:08:54 -07:00
415dbe4625 split expression in two.
makes order of evaluation strictly defined.
(cf http://en.wikipedia.org/wiki/Sequence_point)

Suggestion by mr dot gnu dot jr at gmail dot com
2011-06-08 09:06:03 -07:00
e29072a8ce configure: test for zlib only w/--enable-experimental
Only builds with --enable-experimental require zlib currently.
A base install of mingw will not include the development headers and
library. libwebp itself will now build in such environments.
Additionally, remove -lz from **/Makefile.am, -lz will be added to LIBS
by AC_CHECK_LIB when necessary.

Change-Id: Iae8319cdf00162ecb7ed44661c02f40beb34f155
2011-06-07 14:12:53 -07:00
b2b0090b4c Simplify Visual Studio ifdefs
Use _MSC_VER as the intrinsics compile without /arch:SSE2 on x86.
Also avoids applying the same flag to all files which defeated the
purpose of the runtime cpu-detection.

Thanks to Frank B. for the suggestion!

Change-Id: Iae9933a3cee704e663d9bbd53d0fa68e8c025425
2011-06-03 11:40:15 -07:00
ca7a2fd66d Add error reporting from encoding failures.
picture->error_code can be looked up for finer error diagnose.
Added readable error messages to cwebp too.

Should close bug #75 (http://code.google.com/p/webp/issues/detail?id=75)

Change-Id: I8889d06642d90702f698cd5c27441a058ddb3636
2011-06-02 07:06:39 -07:00
6c9405dbfb Merge "Makefile.vc: require CFG with clean target" 2011-06-01 17:04:35 -07:00
0424ecd996 Makefile.vc: require CFG with clean target
Allows clean to target a specific CFG output directory which has the
side benefit of supporting of tree builds.
Earlier versions would clean the entire source tree possibly removing
multiple builds.

Change-Id: I63c0f32f73c0035f2b7fae0a88c02de3805d264b
2011-06-01 15:55:22 -07:00
003417c7c7 Enable SSE2 for Visual Studio builds
Based on the remnants of change #2273.
Adds an auto-detect for ARCH based on the environment.

Change-Id: I4644eae7509f3982a8b385b49beac03675a2e0e8
2011-06-01 12:57:18 -07:00
af10db4aa4 little speed up for VP8BitUpdate()
1% faster on average

Patch by Somnath Banerjee (somnath at google dot com)

Change-Id: I44cbc125024d3b7ba8621643e9161b72f0eac281
2011-05-29 22:35:44 -07:00
e71418f899 more MSVC files to ignore
original patch by Vladimir Panteleev (vladimir at thecybershadow dot net)
2011-05-27 10:07:51 -07:00
46d90363af cosmetics 2011-05-27 10:04:36 -07:00
edf59ab320 typo fix 2011-05-27 09:55:47 -07:00
72229f5f34 Add support for x64 and SSE2 builds under Windows. 2011-05-26 16:50:46 +02:00
92e5c6e1d4 VP8GetInfo() + WebPResetDecParams()
- add an internal VP8GetInfo() to parse header
- add WebPResetDecParams() for proper initialization

Change-Id: Ic39ea634d1d8016d25bdcfef2cb0d00b6dad83e9
2011-05-19 19:17:05 -07:00
416b7a6b95 raise the fixed-point precision for the rescaler
for super-large upscaling factor (32x and up), 20bits was not enough.

Change-Id: I7b0d1975d0609948d464cfc3aeff1a70df16dc57
2011-05-16 17:12:37 -07:00
aa87e4e063 fix alignment
Change-Id: I72d2c7a0faf240d3cada1b6fb86ffb32bead3eb2
2011-05-16 14:39:47 -07:00
eb66670c6f disable WEBP_EXPERIMENTAL_FEATURES
Change-Id: I39caa72d261a0fd668910b1bfe067489c48a2de1
2011-05-09 12:10:28 -07:00
c5ae7f653a typo fix: USE_ => WEBP_
Change-Id: I8d31320ff8a28bc89b943606a695421f9eda692d
2011-05-06 20:09:41 -07:00
d041efae00 swig: add libwebp.jar/libwebp_java_wrap.c
for the swig-impaired

Change-Id: I10711c057c11bd9e59bc382fe3c6337883f5c4a6
2011-05-06 18:56:01 -07:00
f6fb3877ed add swig interface
Currently only supports a subset of decode functions and likely only
works fully for java.

For java bindings:
The generated java source can be compiled and the class files added to
libwebp.jar.
The generated jni source can be compiled to, e.g., libwebp_jni.so, which
can then be loaded via System.loadLibrary("webp_jni").

Change-Id: I8225933cbaf85c9cfa4b78c2e5f167cee8b62408
2011-05-06 16:41:00 -07:00
e9273902f1 align buffer for double too
sometimes, gcc insert sse2 storeu instructions (like in VP8InitFilter())
with aligment requirements.

Bug was visible 'sometimes' in non-debug mode, when trying to use -af.

Change-Id: If3ec282bbbb9f9d0d33ca4b2c4bed46cd26fe495
2011-05-05 19:32:38 -07:00
842c009b38 fix -strong option
was checking the presence of a useless second argument

Change-Id: I2c524a79fc7317cb8b6146c10265ee9462cd1958
2011-05-05 18:10:08 -07:00
d0a7038792 Merge "cosmetics" 2011-05-05 16:47:19 -07:00
fc0a02e55d fix the dichotomy loop
we were reading past the end of the dqs[] array.

reported by Mathias Schindler (on cygwin only)
http://code.google.com/p/webp/issues/detail?id=71

Change-Id: Ib38c4c139e3cac3e8915626d63e16b403d6bbd63
2011-05-05 16:35:12 -07:00
38369c03e0 cosmetics
Change-Id: I39c3bc671ab427dcb3e23aedee7fe8d81f4cb860
2011-05-04 23:25:40 -07:00
8dfc4c6f17 factorize and unify GetAlpha() between the C and SSE2 version
patch by Christian Duvivier (cduvivier at google dot com)

Change-Id: I47ac75010aa4036cf09f13d23043e654c4966a00
2011-05-04 17:02:35 -07:00
6d0e66c23e prepare experimentation with yuv444 / 422
+ add a simple rescaling function: WebPPictureRescale() for encoding
+ clean-up the memory managment around the alpha plane
+ fix some includes path by using "../webp/xxx.h" instead of "webp/xxx.h"

New flags for 'cwebp':
 -resize <width> <height>
 -444  (no effect)
 -422  (no effect)
 -400

Change-Id: I25a95f901493f939c2dd789e658493b83bd1abfa
2011-05-04 15:41:08 -07:00
79cc49f5eb add a --enable-experimental option to './configure'
This will enable USE_EXPERIMENTAL_FEATURES instead of having a header-level #define

Change-Id: I860b007f64220ddf92d0becd18f7d100c718f8d1
2011-05-04 15:17:54 -07:00
d757523889 sse2 version of CollectHistogram()
~3% faster encoding.

Patch by Christian Duvivier (cduvivier at google dot com)

Change-Id: I8c11d63d0cffb35e145fe0ea74cb66a53f4950d9
2011-04-28 17:00:57 -07:00
c1c728d617 add an extra #ifdef WEBP_EXPERIMENTAL_FEATURES to avoid 'unused variable' warning
Change-Id: I8a42781eab1fad75e13cb85ac3f768d2405726e0
2011-04-28 16:31:14 -07:00
60c61d2d54 always call VP*EncDeleteAlpha() unconditionnally, for simplicity
Change-Id: I145f94adf6ea11618170c0955e6ef2fa60756f1f
2011-04-28 16:30:48 -07:00
0f8c63849d simply don't call WriteExtensions() if WEBP_EXPERIMENTAL_FEATURES is not defined
Change-Id: I81867dcc505376c800ba65d81f6a50e02161e707
2011-04-28 16:03:34 -07:00
47c661d50f rename swap -> swap_rb
Change-Id: I054a4517376a027611cffb2484b22248adae2b77
2011-04-28 16:01:46 -07:00
10d55bbb06 move chunk[] declaration out of the for() loop
Change-Id: I10df4b5d6d186bae2b9b1a174aab13c401c54b01
2011-04-28 15:52:44 -07:00
517cec21b9 fix indentation
Change-Id: I868ec38999dc5249e9b93048049dd51422113677
2011-04-28 15:52:06 -07:00
f7d9e261c5 fix merge problems
Change-Id: I6d0763734139d2852896872c80c5e7fa7889945a
2011-04-26 11:02:38 -07:00
8fd42b3a81 add a stride 'a_stride' for the alpha plane
(instead of hardcoding it to 'width')

Change-Id: Ibce97285bfe8ff4aea45b5797f53a53d3f60adab
2011-04-26 07:31:57 -07:00
b8dcbf2f35 fix alpha-plane copy and crop methods
the alpha-plane was not reallocated properly.

Change-Id: I5db445c7086b3c7c5cf98631d714350119dd7c2a
2011-04-26 06:37:45 -07:00
cdef89de0e fix some 'unused variable' warning
Change-Id: I1d2747480675b68f57d7ef7bf0b0010d267cb32b
2011-04-26 06:34:39 -07:00
fb29c26201 SSE2 version of the fwd transform and the squared sum metric
average 10% faster encoding.

Patch by Christian Duvivier (cduvivier at google dot com)

Change-Id: Iff1bba402b280522af323f73e0c817a3d665354a
2011-04-26 00:03:55 -07:00
2ab4b72f53 EXPERIMENTAL: add support for alpha channel
This is a (minor) bitstream change: if the 'color_space' bit is set to '1'
(which is normally an undefined/invalid behaviour), we add extra data at the
end of partition #0 (so-called 'extensions')

Namely, we add the size of the extension data as 3 bytes (little-endian),
followed by a set of bits telling which extensions we're incorporating.
The data then _preceeds_ this trailing tags.

This is all experimental, and you'll need to have
'#define WEBP_EXPERIMENTAL_FEATURES' in webp/types.h to enable this code
(at your own risk! :))

Still, this hack produces almost-valid WebP file for decoders that don't
check this color_space bit. In particular, previous 'dwebp' (and for instance
Chrome) will recognize this files and decode them, but without the alpha
of course. Other decoder will just see random extra stuff at the end of
partition #0.

To experiment with the alpha-channel, you need to compile on Unix platform
and use PNGs for input/output.

If 'alpha.png' is a source with alpha channel, then you can try (on Unix):

  cwebp alpha.png -o alpha.webp
  dwebp alpha.webp -o test.png

cwebp now has a '-noalpha' flag to ignore any alpha information from the
source, if present.

More hacking and experimenting welcome!

Change-Id: I3c7b1fd8411c9e7a9f77690e898479ad85c52f3e
2011-04-25 23:29:39 -07:00
cfbf88a6c4 add SSE2 functions. ~2x faster encoding on average.
For now, SSE2 functions are compiled a-minima: only on platforms
where __SSE2__ is defined. Let's later add some autoconf-based
config to enable/disable at will.

One can disable SSE2 at run-time by hooking-up VP8GetInfo.
There is a new option "-noasm" in cwebp for that.
Output should be binary the same between C and SSE2 version. If not,
that's a bug!

patch by Christian Duvivier (cduvivier at google dot com)

Change-Id: Iae006c3cdcb7e8280e846cedb94d239dab1e42ae
2011-04-22 15:34:23 -07:00
e7ff3f9af6 merge two ITransforms together when applicable and change the TTransform
to return the sum directly.

output is bitwise the same, speed up 1-2%. This is preparatory to a
more efficient SSE2 implementation.

Change-Id: I0bcdf05808c93420fbe9dcb75e5e7e55a4ae5b89
2011-04-21 13:35:56 -07:00
ca554137d2 fix WebPIDecGetRGB() to accept any RGB(A) mode, not just MODE_RGB
Change-Id: I8780582ecd0868c84e2b1310addebd6c8989e727
2011-04-20 08:42:08 -07:00
8aa50efd38 fix some 'man' typos 2011-04-18 18:50:34 -07:00
186 changed files with 58259 additions and 5992 deletions

5
.gitattributes vendored Normal file
View File

@ -0,0 +1,5 @@
.gitattributes export-ignore
.gitignore export-ignore
.mailmap export-ignore
*.pdf -text -diff
*.ppm -text -diff

18
.gitignore vendored
View File

@ -1,18 +1,32 @@
*.l[ao]
*.o
*.[ao]
*.pc
.deps
.libs
/aclocal.m4
/ar-lib
/autom4te.cache
/compile
/config.*
/configure
/depcomp
/dist
/install-sh
/libtool
/ltmain.sh
/missing
/mkinstalldirs
/stamp-h1
Makefile
Makefile.in
examples/[cd]webp
examples/[cdv]webp
examples/gif2webp
examples/webpmux
src/webp/config.h*
src/webp/stamp-h1
/output
/doc/output
*.idb
*.pdb
/iosbuild
/WebP.framework

8
.mailmap Normal file
View File

@ -0,0 +1,8 @@
<johann.koenig@duck.com> <johannkoenig@google.com>
Mikołaj Zalewski <mikolajz@google.com>
Pascal Massimino <pascal.massimino@gmail.com>
<pascal.massimino@gmail.com> <skal@google.com>
Vikas Arora <vikasa@google.com>
<vikasa@google.com> <vikasa@gmail.com>
<vikasa@google.com> <vikaas.arora@gmail.com>
<slobodan.prijic@imgtec.com> <Slobodan.Prijic@imgtec.com>

22
AUTHORS
View File

@ -1,7 +1,25 @@
Contributors:
- Charles Munger (clm at google dot com)
- Christian Duvivier (cduvivier at google dot com)
- Djordje Pesut (djordje dot pesut at imgtec dot com)
- James Zern (jzern at google dot com)
- Jan Engelhardt (jengelh at medozas dot de)
- Johann (johann dot koenig at duck dot com)
- Jovan Zelincevic (jovan dot zelincevic at imgtec dot com)
- Jyrki Alakuijala (jyrki at google dot com)
- levytamar82 (tamar dot levy at intel dot com)
- Lou Quillio (louquillio at google dot com)
- Mans Rullgard (mans at mansr dot com)
- Martin Olsson (mnemo at minimum dot se)
- Mikołaj Zalewski (mikolajz at google dot com)
- Noel Chromium (noel at chromium dot org)
- Pascal Massimino (pascal dot massimino at gmail dot com)
- pierre.php@gmail.com
- Somnath Banerjee (somnath at google dot com)
- Paweł Hajdan, Jr (phajdan dot jr at chromium dot org)
- Pierre Joye (pierre dot php at gmail dot com)
- Scott LaVarnway (slavarnway at google dot com)
- 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

@ -1,35 +1,109 @@
LOCAL_PATH:= $(call my-dir)
LOCAL_PATH := $(call my-dir)
WEBP_CFLAGS := -Wall -DANDROID -DHAVE_MALLOC_H -DHAVE_PTHREAD -DWEBP_USE_THREAD
ifeq ($(APP_OPTIM),release)
WEBP_CFLAGS += -finline-functions -ffast-math \
-ffunction-sections -fdata-sections
ifeq ($(findstring clang,$(NDK_TOOLCHAIN_VERSION)),)
WEBP_CFLAGS += -frename-registers -s
endif
endif
include $(CLEAR_VARS)
ifneq ($(findstring armeabi-v7a, $(TARGET_ARCH_ABI)),)
# Setting LOCAL_ARM_NEON will enable -mfpu=neon which may cause illegal
# instructions to be generated for armv7a code. Instead target the neon code
# specifically.
NEON := c.neon
else
NEON := c
endif
LOCAL_SRC_FILES := \
src/dec/bits.c \
src/dec/dsp.c \
src/dec/frame.c \
src/dec/idec.c \
src/dec/quant.c \
src/dec/tree.c \
src/dec/vp8.c \
src/dec/webp.c \
src/dec/yuv.c \
src/enc/analysis.c \
src/enc/bit_writer.c \
src/enc/config.c \
src/enc/dsp.c \
src/enc/filter.c \
src/enc/frame.c \
src/enc/iterator.c \
src/enc/picture.c \
src/enc/quant.c \
src/enc/syntax.c \
src/enc/tree.c \
src/enc/webpenc.c
LOCAL_CFLAGS := -Wall -DANDROID -DHAVE_MALLOC_H -DHAVE_PTHREAD \
-finline-functions -frename-registers -ffast-math \
-s -fomit-frame-pointer -Isrc/webp
src/dec/alpha.c \
src/dec/buffer.c \
src/dec/frame.c \
src/dec/idec.c \
src/dec/io.c \
src/dec/quant.c \
src/dec/tree.c \
src/dec/vp8.c \
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 \
src/dsp/dec_mips32.c \
src/dsp/dec_neon.$(NEON) \
src/dsp/dec_sse2.c \
src/dsp/enc.c \
src/dsp/enc_avx2.c \
src/dsp/enc_mips32.c \
src/dsp/enc_neon.$(NEON) \
src/dsp/enc_sse2.c \
src/dsp/lossless.c \
src/dsp/lossless_mips32.c \
src/dsp/lossless_neon.$(NEON) \
src/dsp/lossless_sse2.c \
src/dsp/upsampling.c \
src/dsp/upsampling_neon.$(NEON) \
src/dsp/upsampling_sse2.c \
src/dsp/yuv.c \
src/dsp/yuv_mips32.c \
src/dsp/yuv_sse2.c \
src/enc/alpha.c \
src/enc/analysis.c \
src/enc/backward_references.c \
src/enc/config.c \
src/enc/cost.c \
src/enc/filter.c \
src/enc/frame.c \
src/enc/histogram.c \
src/enc/iterator.c \
src/enc/picture.c \
src/enc/picture_csp.c \
src/enc/picture_psnr.c \
src/enc/picture_rescale.c \
src/enc/picture_tools.c \
src/enc/quant.c \
src/enc/syntax.c \
src/enc/token.c \
src/enc/tree.c \
src/enc/vp8l.c \
src/enc/webpenc.c \
src/utils/bit_reader.c \
src/utils/bit_writer.c \
src/utils/color_cache.c \
src/utils/filters.c \
src/utils/huffman.c \
src/utils/huffman_encode.c \
src/utils/quant_levels.c \
src/utils/quant_levels_dec.c \
src/utils/random.c \
src/utils/rescaler.c \
src/utils/thread.c \
src/utils/utils.c \
LOCAL_CFLAGS := $(WEBP_CFLAGS)
LOCAL_C_INCLUDES += $(LOCAL_PATH)/src
LOCAL_MODULE:= webp
# prefer arm over thumb mode for performance gains
LOCAL_ARM_MODE := arm
include $(BUILD_STATIC_LIBRARY)
LOCAL_STATIC_LIBRARIES := cpufeatures
LOCAL_MODULE := webp
ifeq ($(ENABLE_SHARED),1)
include $(BUILD_SHARED_LIBRARY)
else
include $(BUILD_STATIC_LIBRARY)
endif
include $(LOCAL_PATH)/examples/Android.mk
$(call import-module,android/cpufeatures)

2105
ChangeLog

File diff suppressed because it is too large Load Diff

View File

@ -1,37 +1,41 @@
#
# Stem for static libs and DLLs
#
LIB_NAME = libwebp_a
LIB_NAME_DEBUG = libwebp_a_debug
#
# Stem for DLL import libs
#
IMPLIB_NAME = libwebp
IMPLIB_NAME_DEBUG = libwepb_debug
!IFNDEF DEP_PATH
DEPS_PATH = ../../deps
!ENDIF
LIBWEBPDECODER_BASENAME = libwebpdecoder
LIBWEBP_BASENAME = libwebp
LIBWEBPMUX_BASENAME = libwebpmux
LIBWEBPDEMUX_BASENAME = libwebpdemux
!IFNDEF ARCH
ARCH = x86
!IF ! [ cl 2>&1 | find "x86" > NUL ]
ARCH = x86
!ELSE IF ! [ cl 2>&1 | find "x64" > NUL ]
ARCH = x64
!ELSE
!ERROR Unable to auto-detect toolchain architecture! \
If cl.exe is in your PATH rerun nmake with ARCH=<arch>.
!ENDIF
!ENDIF
!IF "$(ARCH)" == "x86"
PLATFORM_LDFLAGS = /SAFESEH
!ENDIF
#############################################################
## Nothing more to do below this line!
MT = mt.exe
CCNODBG = cl.exe /nologo /O2 /DNDEBUG
CCDEBUG = cl.exe /nologo /Od /Gm /Zi /D_DEBUG /RTC1
CFLAGS = /Isrc /nologo /W3 /EHsc /DWIN32 /FD /c /GS /D_CRT_SECURE_NO_WARNINGS
LDFLAGS = /LARGEADDRESSAWARE /MANIFEST /NXCOMPAT /SAFESEH /DYNAMICBASE
CFLAGSLIB = /DLIBWEBP_STATICLIB
LNKDLL = link.exe /DLL
LNKLIB = link.exe /lib
LNKEXE = link.exe
LFLAGS = /nologo /machine:$(ARCH)
CFLAGS = $(CFLAGS)
NOLOGO = /nologo
CCNODBG = cl.exe $(NOLOGO) /O2 /DNDEBUG
CCDEBUG = cl.exe $(NOLOGO) /Od /Gm /Zi /D_DEBUG /RTC1
CFLAGS = /Isrc $(NOLOGO) /W3 /EHsc /c /GS
CFLAGS = $(CFLAGS) /DWIN32 /D_CRT_SECURE_NO_WARNINGS /DWIN32_LEAN_AND_MEAN
CFLAGS = $(CFLAGS) /DHAVE_WINCODEC_H /DWEBP_USE_THREAD
LDFLAGS = /LARGEADDRESSAWARE /MANIFEST /NXCOMPAT /DYNAMICBASE
LDFLAGS = $(LDFLAGS) $(PLATFORM_LDFLAGS)
LNKDLL = link.exe /DLL $(NOLOGO)
LNKEXE = link.exe $(NOLOGO)
LNKLIB = lib.exe $(NOLOGO)
MT = mt.exe $(NOLOGO)
CFGSET = FALSE
!IF "$(OBJDIR)" == ""
@ -40,6 +44,11 @@ OUTDIR = ..\obj\
OUTDIR = $(OBJDIR)
!ENDIF
!IF "$(HAVE_AVX2)" == "1"
CFLAGS = $(CFLAGS) /DWEBP_HAVE_AVX2
AVX2_FLAGS = /arch:AVX2
!ENDIF
##############################################################
# Runtime library configuration
!IF "$(RTLIBCFG)" == "static"
@ -54,20 +63,58 @@ DIROBJ = $(DIRBASE)\obj
DIRLIB = $(DIRBASE)\lib
DIRINC = $(DIRBASE)\include
DIRBIN = $(DIRBASE)\bin
LIBWEBP_PDBNAME = $(DIROBJ)\$(LIBWEBP_BASENAME).pdb
OUTPUT_DIRS = $(DIRBIN) $(DIRINC) $(DIRLIB) \
$(DIROBJ)\dec \
$(DIROBJ)\demux \
$(DIROBJ)\dsp \
$(DIROBJ)\enc \
$(DIROBJ)\examples \
$(DIROBJ)\mux \
$(DIROBJ)\utils \
# release-static
# Target configuration
!IF "$(CFG)" == "release-static"
TARGET = $(LIB_NAME).lib
LNK = $(LNKLIB) /out:$(DIRLIB)\$(TARGET)
CC = $(CCNODBG) $(RTLIB) $(CFLAGSLIB)
CFGSET = TRUE
CC = $(CCNODBG)
STATICLIBBUILD = TRUE
!ELSE IF "$(CFG)" == "debug-static"
CC = $(CCDEBUG)
RTLIB = $(RTLIBD)
STATICLIBBUILD = TRUE
LIBWEBPDECODER_BASENAME = $(LIBWEBPDECODER_BASENAME)_debug
LIBWEBP_BASENAME = $(LIBWEBP_BASENAME)_debug
LIBWEBPMUX_BASENAME = $(LIBWEBPMUX_BASENAME)_debug
LIBWEBPDEMUX_BASENAME = $(LIBWEBPDEMUX_BASENAME)_debug
!ELSE IF "$(CFG)" == "release-dynamic"
CC = $(CCNODBG)
DLLBUILD = TRUE
!ELSE IF "$(CFG)" == "debug-dynamic"
CC = $(CCDEBUG)
RTLIB = $(RTLIBD)
DLLBUILD = TRUE
LIBWEBPDECODER_BASENAME = $(LIBWEBPDECODER_BASENAME)_debug
LIBWEBP_BASENAME = $(LIBWEBP_BASENAME)_debug
LIBWEBPMUX_BASENAME = $(LIBWEBPMUX_BASENAME)_debug
LIBWEBPDEMUX_BASENAME = $(LIBWEBPDEMUX_BASENAME)_debug
!ENDIF
# debug-static
!IF "$(CFG)" == "debug-static"
TARGET = $(LIB_NAME_DEBUG).lib
LNK = $(LNKLIB) /out:$(DIRLIB)\$(TARGET)
CC = $(CCDEBUG) $(RTLIBD) $(CFLAGSLIB)
!IF "$(STATICLIBBUILD)" == "TRUE"
CC = $(CC) $(RTLIB)
CFGSET = TRUE
LIBWEBPDECODER = $(DIRLIB)\$(LIBWEBPDECODER_BASENAME).lib
LIBWEBP = $(DIRLIB)\$(LIBWEBP_BASENAME).lib
LIBWEBPMUX = $(DIRLIB)\$(LIBWEBPMUX_BASENAME).lib
LIBWEBPDEMUX = $(DIRLIB)\$(LIBWEBPDEMUX_BASENAME).lib
!ELSE IF "$(DLLBUILD)" == "TRUE"
DLLC = webp_dll.c
DLLINC = webp_dll.h
DLL_OBJS = $(DIROBJ)\$(DLLC:.c=.obj)
CC = $(CC) /I$(DIROBJ) /FI$(DLLINC) $(RTLIB) /DWEBP_DLL
LIBWEBPDECODER = $(DIRLIB)\$(LIBWEBPDECODER_BASENAME)_dll.lib
LIBWEBP = $(DIRLIB)\$(LIBWEBP_BASENAME)_dll.lib
LIBWEBPMUX = $(DIRLIB)\$(LIBWEBPMUX_BASENAME)_dll.lib
LIBWEBPDEMUX = $(DIRLIB)\$(LIBWEBPDEMUX_BASENAME)_dll.lib
LIBWEBP_PDBNAME = $(DIROBJ)\$(LIBWEBP_BASENAME)_dll.pdb
CFGSET = TRUE
!ENDIF
@ -75,16 +122,25 @@ CFGSET = TRUE
# Usage
#
!IF "$(CFGSET)" == "FALSE"
!MESSAGE Usage: nmake /f makefile.vc9 [CFG=<config>] [OBJDIR=<path>] [RTLIBCFG=<rtlib>] [<target>]
!MESSAGE Usage: nmake /f Makefile.vc [CFG=<config>]
!MESSAGE . [OBJDIR=<path>] [RTLIBCFG=<rtlib>] [<target>]
!MESSAGE
!MESSAGE where <config> is one of:
!MESSAGE - release-static - release static library
!MESSAGE - debug-static - debug static library
!MESSAGE - (empty) - perform a clean
!MESSAGE - release-dynamic - release dynamic link library (DLL)
!MESSAGE - debug-dynamic - debug dynamic link library (DLL)
!MESSAGE
!MESSAGE <rtlibcfg> controls the runtime library likage - can be 'static' or 'dynamic'.
!MESSAGE <target> can be left blank in which case all is assumed
!MESSAGE <path> is the path where you like to build (obj, bins, etc.)
!MESSAGE default to ..\obj\
!MESSAGE <target> may be:
!MESSAGE - clean - perform a clean for CFG
!MESSAGE - experimental - build CFG with experimental
!MESSAGE . features enabled.
!MESSAGE - (empty) - build libwebp-based targets for CFG
!MESSAGE - all - build (de)mux-based targets for CFG
!MESSAGE
!MESSAGE RTLIBCFG controls the runtime library linkage - 'static' or 'dynamic'.
!MESSAGE OBJDIR is the path where you like to build (obj, bins, etc.),
!MESSAGE defaults to ..\obj
!IF "$(CFG)" != ""
!MESSAGE
@ -93,99 +149,219 @@ CFGSET = TRUE
!ENDIF
#######################
# Only the clean target can be used if a config was not provided.
# Rules
#
!IF "$(CFGSET)" == "FALSE"
!MESSAGE
!MESSAGE No configuration provided - performing a clean.
clean:
@-erase /s *.dll 2> NUL
@-erase /s *.exp 2> NUL
@-erase /s *.idb 2> NUL
@-erase /s *.lib 2> NUL
@-erase /s *.obj 2> NUL
@-erase /s *.pch 2> NUL
@-erase /s *.pdb 2> NUL
@-erase /s *.res 2> NUL
!ELSE
!IF "$(CFGSET)" == "TRUE"
# A config was provided, so the library can be built.
#
X_OBJS= \
$(DIROBJ)\dec\bits.obj \
$(DIROBJ)\dec\dsp.obj \
$(DIROBJ)\dec\frame.obj \
$(DIROBJ)\dec\quant.obj \
$(DIROBJ)\dec\tree.obj \
$(DIROBJ)\dec\vp8.obj \
$(DIROBJ)\dec\webp.obj \
$(DIROBJ)\dec\yuv.obj \
$(DIROBJ)\dec\idec.obj \
$(DIROBJ)\enc\analysis.obj \
$(DIROBJ)\enc\bit_writer.obj \
$(DIROBJ)\enc\config.obj \
$(DIROBJ)\enc\cost.obj \
$(DIROBJ)\enc\dsp.obj \
$(DIROBJ)\enc\frame.obj \
$(DIROBJ)\enc\filter.obj \
$(DIROBJ)\enc\iterator.obj \
$(DIROBJ)\enc\picture.obj \
$(DIROBJ)\enc\quant.obj \
$(DIROBJ)\enc\syntax.obj \
$(DIROBJ)\enc\tree.obj \
$(DIROBJ)\enc\webpenc.obj \
$(RESOURCE)
DEC_OBJS = \
$(DIROBJ)\dec\alpha.obj \
$(DIROBJ)\dec\buffer.obj \
$(DIROBJ)\dec\frame.obj \
$(DIROBJ)\dec\idec.obj \
$(DIROBJ)\dec\io.obj \
$(DIROBJ)\dec\quant.obj \
$(DIROBJ)\dec\tree.obj \
$(DIROBJ)\dec\vp8.obj \
$(DIROBJ)\dec\vp8l.obj \
$(DIROBJ)\dec\webp.obj \
EXAMPLES_OBJS = \
$(DIROBJ)\examples\cwebp.obj \
$(DIROBJ)\examples\dwebp.obj
DEMUX_OBJS = \
$(DIROBJ)\demux\demux.obj \
all: $(DIRLIB)\$(TARGET) $(DIRBIN)\dwebp.exe $(DIRBIN)\cwebp.exe
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 \
$(DIROBJ)\dsp\dec_mips32.obj \
$(DIROBJ)\dsp\dec_neon.obj \
$(DIROBJ)\dsp\dec_sse2.obj \
$(DIROBJ)\dsp\lossless.obj \
$(DIROBJ)\dsp\lossless_mips32.obj \
$(DIROBJ)\dsp\lossless_neon.obj \
$(DIROBJ)\dsp\lossless_sse2.obj \
$(DIROBJ)\dsp\upsampling.obj \
$(DIROBJ)\dsp\upsampling_neon.obj \
$(DIROBJ)\dsp\upsampling_sse2.obj \
$(DIROBJ)\dsp\yuv.obj \
$(DIROBJ)\dsp\yuv_mips32.obj \
$(DIROBJ)\dsp\yuv_sse2.obj \
$(DIRLIB)\$(TARGET): $(X_OBJS)
$(LNK) $(LFLAGS) $(X_OBJS)
-xcopy $(DIROBJ)\$(LIB_NAME).dll $(DIRBIN) /y
-xcopy $(DIROBJ)\$(LIB_NAME).lib $(DIRLIB) /y
-xcopy $(DIROBJ)\$(LIB_NAME_DEBUG).dll $(DIRBIN) /y
-xcopy $(DIROBJ)\$(LIB_NAME_DEBUG).lib $(DIRLIB) /y
-xcopy $(DIROBJ)\$(IMPLIB_NAME).lib $(DIRLIB) /y
-xcopy $(DIROBJ)\$(IMPLIB_NAME_DEBUG).lib $(DIRLIB) /y
-xcopy $(DIROBJ)\*.exp $(DIRLIB) /y
-xcopy $(DIROBJ)\*.pdb $(DIRLIB) /y
DSP_ENC_OBJS = \
$(DIROBJ)\dsp\enc.obj \
$(DIROBJ)\dsp\enc_avx2.obj \
$(DIROBJ)\dsp\enc_mips32.obj \
$(DIROBJ)\dsp\enc_neon.obj \
$(DIROBJ)\dsp\enc_sse2.obj \
$(X_OBJS): $(DIROBJ)\enc $(DIROBJ)\dec $(DIRLIB) $(DIRINC) $(DIRBIN)
EX_FORMAT_DEC_OBJS = \
$(DIROBJ)\examples\jpegdec.obj \
$(DIROBJ)\examples\metadata.obj \
$(DIROBJ)\examples\pngdec.obj \
$(DIROBJ)\examples\tiffdec.obj \
$(DIROBJ)\examples\webpdec.obj \
$(DIROBJ)\examples\wicdec.obj \
$(EXAMPLES_OBJS): $(DIROBJ)\examples $(DIRLIB)\$(TARGET)
EX_UTIL_OBJS = \
$(DIROBJ)\examples\example_util.obj \
$(DIROBJ)\enc:
@if not exist "$(DIROBJ)\enc" mkdir $(DIROBJ)\enc
ENC_OBJS = \
$(DIROBJ)\enc\alpha.obj \
$(DIROBJ)\enc\analysis.obj \
$(DIROBJ)\enc\backward_references.obj \
$(DIROBJ)\enc\config.obj \
$(DIROBJ)\enc\cost.obj \
$(DIROBJ)\enc\filter.obj \
$(DIROBJ)\enc\frame.obj \
$(DIROBJ)\enc\histogram.obj \
$(DIROBJ)\enc\iterator.obj \
$(DIROBJ)\enc\picture.obj \
$(DIROBJ)\enc\picture_csp.obj \
$(DIROBJ)\enc\picture_psnr.obj \
$(DIROBJ)\enc\picture_rescale.obj \
$(DIROBJ)\enc\picture_tools.obj \
$(DIROBJ)\enc\quant.obj \
$(DIROBJ)\enc\syntax.obj \
$(DIROBJ)\enc\token.obj \
$(DIROBJ)\enc\tree.obj \
$(DIROBJ)\enc\vp8l.obj \
$(DIROBJ)\enc\webpenc.obj \
$(DIROBJ)\examples:
@if not exist "$(DIROBJ)\examples" mkdir $(DIROBJ)\examples
MUX_OBJS = \
$(DIROBJ)\mux\muxedit.obj \
$(DIROBJ)\mux\muxinternal.obj \
$(DIROBJ)\mux\muxread.obj \
$(DIROBJ)\dec:
@if not exist "$(DIROBJ)\dec" mkdir $(DIROBJ)\dec
UTILS_DEC_OBJS = \
$(DIROBJ)\utils\bit_reader.obj \
$(DIROBJ)\utils\color_cache.obj \
$(DIROBJ)\utils\filters.obj \
$(DIROBJ)\utils\huffman.obj \
$(DIROBJ)\utils\quant_levels_dec.obj \
$(DIROBJ)\utils\rescaler.obj \
$(DIROBJ)\utils\random.obj \
$(DIROBJ)\utils\thread.obj \
$(DIROBJ)\utils\utils.obj \
$(DIRLIB):
@if not exist "$(DIRLIB)" mkdir $(DIRLIB)
UTILS_ENC_OBJS = \
$(DIROBJ)\utils\bit_writer.obj \
$(DIROBJ)\utils\huffman_encode.obj \
$(DIROBJ)\utils\quant_levels.obj \
$(DIRINC):
@if not exist "$(DIRINC)" mkdir $(DIRINC)
LIBWEBPDECODER_OBJS = $(DEC_OBJS) $(DSP_DEC_OBJS) $(UTILS_DEC_OBJS)
LIBWEBP_OBJS = $(LIBWEBPDECODER_OBJS) $(ENC_OBJS) $(DSP_ENC_OBJS) \
$(UTILS_ENC_OBJS) $(DLL_OBJS)
LIBWEBPMUX_OBJS = $(MUX_OBJS) $(LIBWEBPMUX_OBJS)
LIBWEBPDEMUX_OBJS = $(DEMUX_OBJS) $(LIBWEBPDEMUX_OBJS)
$(DIRBIN):
@if not exist "$(DIRBIN)" mkdir $(DIRBIN)
OUT_LIBS = $(LIBWEBPDECODER) $(LIBWEBP)
OUT_EXAMPLES = $(DIRBIN)\cwebp.exe $(DIRBIN)\dwebp.exe
EXTRA_EXAMPLES = $(DIRBIN)\vwebp.exe $(DIRBIN)\webpmux.exe
ex: $(OUT_LIBS) $(OUT_EXAMPLES)
all: ex $(EXTRA_EXAMPLES)
$(DIRBIN)\cwebp.exe: $(DIROBJ)\examples\cwebp.obj $(EX_FORMAT_DEC_OBJS)
$(DIRBIN)\dwebp.exe: $(DIROBJ)\examples\dwebp.obj
$(DIRBIN)\vwebp.exe: $(DIROBJ)\examples\vwebp.obj
$(DIRBIN)\vwebp.exe: $(EX_UTIL_OBJS) $(LIBWEBPDEMUX) $(LIBWEBP)
$(DIRBIN)\webpmux.exe: $(DIROBJ)\examples\webpmux.obj $(LIBWEBPMUX)
$(DIRBIN)\webpmux.exe: $(EX_UTIL_OBJS) $(LIBWEBP)
$(OUT_EXAMPLES): $(EX_UTIL_OBJS) $(LIBWEBP)
$(EX_UTIL_OBJS) $(EX_FORMAT_DEC_OBJS): $(OUTPUT_DIRS)
experimental:
$(MAKE) /f Makefile.vc \
CFG=$(CFG) \
CFLAGS="$(CFLAGS) /DWEBP_EXPERIMENTAL_FEATURES" /$(MAKEFLAGS)
$(LIBWEBPDECODER): $(LIBWEBPDECODER_OBJS)
$(LIBWEBP): $(LIBWEBP_OBJS)
$(LIBWEBPMUX): $(LIBWEBPMUX_OBJS)
$(LIBWEBPDEMUX): $(LIBWEBPDEMUX_OBJS)
$(LIBWEBP_OBJS) $(LIBWEBPMUX_OBJS) $(LIBWEBPDEMUX_OBJS): $(OUTPUT_DIRS)
!IF "$(DLLBUILD)" == "TRUE"
$(LIBWEBP_OBJS) $(LIBWEBPMUX_OBJS) $(LIBWEBPDEMUX_OBJS): \
$(DIROBJ)\$(DLLINC) $(DIROBJ)\$(DLLC)
{$(DIROBJ)}.c{$(DIROBJ)}.obj:
$(CC) $(CFLAGS) /Fd$(LIBWEBP_PDBNAME) /Fo$@ $<
$(LIBWEBPMUX): $(LIBWEBP)
$(LIBWEBPDEMUX): $(LIBWEBP)
$(LIBWEBPDECODER) $(LIBWEBP) $(LIBWEBPMUX) $(LIBWEBPDEMUX):
$(LNKDLL) /out:$(DIRBIN)\$(@B:_dll=.dll) /implib:$@ $(LFLAGS) $**
-xcopy $(DIROBJ)\*.pdb $(DIRLIB) /y
clean::
@-erase /s $(DIROBJ)\$(DLLC) $(DIROBJ)\$(DLLINC) 2> NUL
!ELSE
$(LIBWEBPDECODER) $(LIBWEBP) $(LIBWEBPMUX) $(LIBWEBPDEMUX):
$(LNKLIB) /out:$@ $**
-xcopy $(DIROBJ)\*.pdb $(DIRLIB) /y
!ENDIF
$(OUTPUT_DIRS):
@if not exist "$(@)" mkdir "$(@)"
# generate a helper include to define WEBP_EXTERN suitable for the DLL build
$(DIROBJ)\$(DLLINC):
@echo #ifndef WEBP_DLL_H_ > $@
@echo #define WEBP_DLL_H_ >> $@
@echo #define WEBP_EXTERN(type) __declspec(dllexport) type >> $@
@echo #endif /* WEBP_DLL_H_ */ >> $@
# expose a WebPFree() function for use in managed code
$(DIROBJ)\$(DLLC): $(DIROBJ)\$(DLLINC)
@echo #include ^<stdlib.h^> > $@
@echo #include "webp_dll.h" >> $@
@echo // This function should be used in place of free() for memory >> $@
@echo // returned by the WebP API. >> $@
@echo WEBP_EXTERN(void) WebPFree(void* ptr) { >> $@
@echo free(ptr); >> $@
@echo } >> $@
.SUFFIXES: .c .obj .res .exe
{examples}.c{$(DIROBJ)\examples}.obj:
$(CC) $(CFLAGS) /Fo"$@" $<
{src\dec}.c{$(DIROBJ)\dec}.obj:
$(CC) $(CFLAGS) /Fo"$@" $<
{src\enc}.c{$(DIROBJ)\enc}.obj:
$(CC) $(CFLAGS) /Fo"$@" $<
# File-specific flag builds. Note batch rules take precedence over wildcards,
# so for now name each file individually.
$(DIROBJ)\dsp\enc_avx2.obj: src\dsp\enc_avx2.c
$(CC) $(CFLAGS) $(AVX2_FLAGS) /Fd$(LIBWEBP_PDBNAME) /Fo$(DIROBJ)\dsp\ \
src\dsp\$(@B).c
# Batch rules
{examples}.c{$(DIROBJ)\examples}.obj::
$(CC) $(CFLAGS) /Fd$(DIROBJ)\examples\ /Fo$(DIROBJ)\examples\ $<
{src\dec}.c{$(DIROBJ)\dec}.obj::
$(CC) $(CFLAGS) /Fd$(LIBWEBP_PDBNAME) /Fo$(DIROBJ)\dec\ $<
{src\demux}.c{$(DIROBJ)\demux}.obj::
$(CC) $(CFLAGS) /Fd$(LIBWEBP_PDBNAME) /Fo$(DIROBJ)\demux\ $<
{src\dsp}.c{$(DIROBJ)\dsp}.obj::
$(CC) $(CFLAGS) /Fd$(LIBWEBP_PDBNAME) /Fo$(DIROBJ)\dsp\ $<
{src\enc}.c{$(DIROBJ)\enc}.obj::
$(CC) $(CFLAGS) /Fd$(LIBWEBP_PDBNAME) /Fo$(DIROBJ)\enc\ $<
{src\mux}.c{$(DIROBJ)\mux}.obj::
$(CC) $(CFLAGS) /Fd$(LIBWEBP_PDBNAME) /Fo$(DIROBJ)\mux\ $<
{src\utils}.c{$(DIROBJ)\utils}.obj::
$(CC) $(CFLAGS) /Fd$(LIBWEBP_PDBNAME) /Fo$(DIROBJ)\utils\ $<
{$(DIROBJ)\examples}.obj{$(DIRBIN)}.exe:
$(LNKEXE) $(LDFLAGS) /OUT:"$@" $< ole32.lib windowscodecs.lib shlwapi.lib $(DIRLIB)\$(TARGET)
$(LNKEXE) $(LDFLAGS) /OUT:$@ $** \
ole32.lib windowscodecs.lib shlwapi.lib
$(MT) -manifest $@.manifest -outputresource:$@;1
del $@.manifest
clean::
@-erase /s $(DIROBJ)\*.dll 2> NUL
@-erase /s $(DIROBJ)\*.exp 2> NUL
@-erase /s $(DIROBJ)\*.idb 2> NUL
@-erase /s $(DIROBJ)\*.lib 2> NUL
@-erase /s $(DIROBJ)\*.obj 2> NUL
@-erase /s $(DIROBJ)\*.pch 2> NUL
@-erase /s $(DIROBJ)\*.pdb 2> NUL
@-erase /s $(DIROBJ)\*.res 2> NUL
!ENDIF # End of case where a config was provided.

90
NEWS
View File

@ -1,3 +1,93 @@
- 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
* NEON assembly additions:
- ~25% faster lossy decode / encode (-m 4)
- ~10% faster lossless decode
- ~5-10% faster lossless encode (-m 3/4)
* dwebp/vwebp can read from stdin
* cwebp/gif2webp can write to stdout
* cwebp can read webp files; useful if storing sources as webp lossless
- 12/19/13: version 0.4.0
* improved gif2webp tool
* numerous fixes, compression improvement and speed-up
* dither option added to decoder (dwebp -dither 50 ...)
* improved multi-threaded modes (-mt option)
* improved filtering strength determination
* New function: WebPMuxGetCanvasSize
* BMP and TIFF format output added to 'dwebp'
* Significant memory reduction for decoding lossy images with alpha.
* Intertwined decoding of RGB and alpha for a shorter
time-to-first-decoded-pixel.
* WebPIterator has a new member 'has_alpha' denoting whether the frame
contains transparency.
* Container spec amended with new 'blending method' for animation.
- 6/13/13: version 0.3.1
This is a binary compatible release.
* Add incremental decoding support for images containing ALPH and ICCP chunks.
* Python bindings via swig for the simple encode/decode interfaces similar to
Java.
- 3/20/13: version 0.3.0
This is a binary compatible release.
* WebPINewRGB/WebPINewYUVA accept being passed a NULL output buffer
and will perform auto-allocation.
* default filter option is now '-strong -f 60'
* encoding speed-up for lossy methods 3 to 6
* alpha encoding can be done in parallel to lossy using 'cwebp -mt ...'
* color profile, metadata (XMP/EXIF) and animation support finalized in the
container.
* various NEON assembly additions
Tool updates / additions:
* gif2webp added
* vwebp given color profile & animation support
* cwebp can preserve color profile / metadata with '-metadata'
- 10/30/12: version 0.2.1
* Various security related fixes
* cwebp.exe: fix import errors on Windows XP
* enable DLL builds for mingw targets
- 8/3/12: version 0.2.0
* Add support for ARGB -> YUVA conversion for lossless decoder
New functions: WebPINewYUVA, WebPIDecGetYUVA
* Add stats for lossless and alpha encoding
* Security related hardening: allocation and size checks
* Add PAM output support to dwebp
- 7/19/12: version 0.1.99
* This is a pre-release of 0.2.0, not an rc to allow for further
incompatible changes based on user feedback.
* Alpha channel encode/decode support.
* Lossless encoder/decoder.
* Add TIFF input support to cwebp.
Incompatible changes:
* The encode ABI has been modified to support alpha encoding.
* Deprecated function WebPINew() has been removed.
* Decode function signatures have changed to consistently use size_t over
int/uint32_t.
* decode_vp8.h is no longer installed system-wide.
* cwebp will encode the alpha channel if present.
- 9/19/11: version 0.1.3
* Advanced decoding APIs.
* On-the-fly cropping and rescaling of images.
* SSE2 instructions for decoding performance optimizations on x86 based platforms.
* Support Multi-threaded decoding.
* 40% improvement in Decoding performance.
* Add support for RGB565, RGBA4444 & ARGB image colorspace.
* Better handling of large picture encoding.
- 3/25/11: version 0.1.2
* Incremental decoding: picture can be decoded byte-by-byte if needs be.
* lot of bug-fixes, consolidation and stabilization

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.

419
README
View File

@ -4,16 +4,16 @@
\__\__/\____/\_____/__/ ____ ___
/ _/ / \ \ / _ \/ _/
/ \_/ / / \ \ __/ \__
\____/____/\_____/_____/____/v0.1.2
\____/____/\_____/_____/____/v0.4.2
Description:
============
WEBP codec: Library to encode and decode images in WebP format. This package
WebP codec: library to encode and decode images in WebP format. This package
contains the library that can be used in other programs to add WebP support,
as well as the command line tools 'cwebp' and 'dwebp'.
See http://code.google.com/speed/webp
See http://developers.google.com/speed/webp
Latest sources are available from http://www.webmproject.org/code/
@ -32,9 +32,11 @@ By running:
nmake /f Makefile.vc CFG=release-static RTLIBCFG=static OBJDIR=output
the directory output\release-static\x86\bin will contain the tools
cweb.exe and dweb.exe. The directory output\release-static\x86\lib will
contains the libwebp static library.
the directory output\release-static\(x64|x86)\bin will contain the tools
cwebp.exe and dwebp.exe. The directory output\release-static\(x64|x86)\lib will
contain the libwebp static library.
The target architecture (x86/x64) is detected by Makefile.vc from the Visual
Studio compiler (cl.exe) available in the system path.
Unix build using makefile.unix:
-------------------------------
@ -47,22 +49,20 @@ will build the binaries examples/cwebp and examples/dwebp, along
with the static library src/libwebp.a. No system-wide installation
is supplied, as this is a simple alternative to the full installation
system based on the autoconf tools (see below).
Please refer the makefile.unix for additional details and customizations.
Please refer to makefile.unix for additional details and customizations.
Using autoconf tools:
---------------------
./autogen.sh
When building from git sources, you will need to run autogen.sh to generate the
configure script.
./configure
make
make install
Note: In case './configure' step fails, try generating configure & appropriate
Makefile(s) via command 'aclocal && autoconf && automake -a -c;'.
should be all you need to have the following files
/usr/local/include/webp/decode.h
/usr/local/include/webp/decode_vp8.h
/usr/local/include/webp/encode.h
/usr/local/include/webp/types.h
/usr/local/lib/libwebp.*
@ -71,10 +71,52 @@ should be all you need to have the following files
installed.
Note: The encoding and decoding libraries are compiled separately
(as src/dec/libwebpdecode.* and src/dec/libwebpencode.*). They
can be installed independently using a minor modifications in the
corresponding Makefile.am configure files (see comments there).
Note: A decode-only library, libwebpdecoder, is available using the
'--enable-libwebpdecoder' flag. The encode library is built separately and can
be installed independently using a minor modification in the corresponding
Makefile.am configure files (see comments there). See './configure --help' for
more options.
SWIG bindings:
--------------
To generate language bindings from swig/libwebp.swig at least swig-1.3
(http://www.swig.org) is required.
Currently the following functions are mapped:
Decode:
WebPGetDecoderVersion
WebPGetInfo
WebPDecodeRGBA
WebPDecodeARGB
WebPDecodeBGRA
WebPDecodeBGR
WebPDecodeRGB
Encode:
WebPGetEncoderVersion
WebPEncodeRGBA
WebPEncodeBGRA
WebPEncodeRGB
WebPEncodeBGR
WebPEncodeLosslessRGBA
WebPEncodeLosslessBGRA
WebPEncodeLosslessRGB
WebPEncodeLosslessBGR
See swig/README for more detailed build instructions.
Java bindings:
To build the swig-generated JNI wrapper code at least JDK-1.5 (or equivalent)
is necessary for enum support. The output is intended to be a shared object /
DLL that can be loaded via System.loadLibrary("webp_jni").
Python bindings:
To build the swig-generated Python extension code at least Python 2.6 is
required. Python < 2.6 may build with some minor changes to libwebp.swig or the
generated code, but is untested.
Encoding tool:
==============
@ -84,9 +126,13 @@ decoding (dwebp) images.
The easiest use should look like:
cwebp input.png -q 80 -o output.webp
which will convert the input PNG or JPEG file to a WebP one using a
quality factor of 80 on a 0->100 scale (0 being the lowest quality,
100 being the best. Default value is 75).
which will convert the input file to a WebP file using a quality factor of 80
on a 0->100 scale (0 being the lowest quality, 100 being the best. Default
value is 75).
You might want to try the -lossless flag too, which will compress the source
(in RGBA format) without any loss. The -q quality parameter will in this case
control the amount of processing time spent trying to make the output file as
small as possible.
A longer list of options is available using the -longhelp command line flag:
@ -94,41 +140,71 @@ A longer list of options is available using the -longhelp command line flag:
Usage:
cwebp [-preset <...>] [options] in_file [-o out_file]
If input size (-s) for an image is not specified, it is assumed to be a either
PNG or JPEG format file.
options:
If input size (-s) for an image is not specified, it is
assumed to be a PNG, JPEG, TIFF or WebP file.
Options:
-h / -help ............ short help
-H / -longhelp ........ long help
-q <float> ............. quality factor (0:small..100:big)
-preset <string> ....... Preset setting, one of:
-alpha_q <int> ......... transparency-compression quality (0..100)
-preset <string> ....... preset setting, one of:
default, photo, picture,
drawing, icon, text
-preset must come first, as it overwrites other parameters.
-preset must come first, as it overwrites other parameters
-m <int> ............... compression method (0=fast, 6=slowest)
-segments <int> ........ number of segments to use (1..4)
-size <int> ............ target size (in bytes)
-psnr <float> .......... target PSNR (in dB. typically: 42)
-s <int> <int> ......... Input size (width x height) for YUV
-sns <int> ............. Spatial Noise Shaping (0:off, 100:max)
-s <int> <int> ......... input size (width x height) for YUV
-sns <int> ............. spatial noise shaping (0:off, 100:max)
-f <int> ............... filter strength (0=off..100)
-sharpness <int> ....... filter sharpness (0:most .. 7:least sharp)
-strong ................ use strong filter instead of simple.
-strong ................ use strong filter instead of simple (default)
-nostrong .............. use simple filter instead of strong
-partition_limit <int> . limit quality to fit the 512k limit on
the first partition (0=no degradation ... 100=full)
-pass <int> ............ analysis pass number (1..10)
-partitions <int> ...... number of partitions to use (0..3)
-crop <x> <y> <w> <h> .. crop picture with the given rectangle
-map <int> ............. print map of extra info.
-d <file.pgm> .......... dump the compressed output (PGM file).
-resize <w> <h> ........ resize picture (after any cropping)
-mt .................... use multi-threading if available
-low_memory ............ reduce memory usage (slower encoding)
-map <int> ............. print map of extra info
-print_psnr ............ prints averaged PSNR distortion
-print_ssim ............ prints averaged SSIM distortion
-print_lsim ............ prints local-similarity distortion
-d <file.pgm> .......... dump the compressed output (PGM file)
-alpha_method <int> .... transparency-compression method (0..1)
-alpha_filter <string> . predictive filtering for alpha plane,
one of: none, fast (default) or best
-alpha_cleanup ......... clean RGB values in transparent area
-blend_alpha <hex> ..... blend colors against background color
expressed as RGB values written in
hexadecimal, e.g. 0xc0e0d0 for red=0xc0
green=0xe0 and blue=0xd0
-noalpha ............... discard any transparency information
-lossless .............. encode image losslessly
-hint <string> ......... specify image characteristics hint,
one of: photo, picture or graph
-metadata <string> ..... comma separated list of metadata to
copy from the input to the output if present.
Valid values: all, none (default), exif, icc, xmp
-short ................. condense printed message
-quiet ................. don't print anything.
-quiet ................. don't print anything
-version ............... print version number and exit
-noasm ................. disable all assembly optimizations
-v ..................... verbose, e.g. print encoding/decoding times
-progress .............. report encoding progress
Experimental Options:
-size <int> ............ Target size (in bytes)
-psnr <float> .......... Target PSNR (in dB. typically: 42)
-af <int> .............. adjust filter strength (0=off, 1=on)
-jpeg_like ............. roughly match expected JPEG size
-af .................... auto-adjust filter strength
-pre <int> ............. pre-processing filter
The main options you might want to try in order to further tune the
visual quality are:
-preset
@ -137,7 +213,7 @@ visual quality are:
-m
Namely:
* 'preset' will set up a default encoding configuration targetting a
* 'preset' will set up a default encoding configuration targeting a
particular type of input. It should appear first in the list of options,
so that subsequent options can take effect on top of this preset.
Default value is 'default'.
@ -149,10 +225,11 @@ Namely:
but with better quality.
Typical value is around '75'.
* 'f' option directly links to the filtering strength used by the codec's
in-loop processing. The higher, the smoother will highly-compressed area
look. This is particularly useful when aiming at very small files.
Typical values are around 20-30. Note that using the option -strong will
change the type of filtering. Use "-f 0" to turn filtering off.
in-loop processing. The higher the value, the smoother the
highly-compressed area will look. This is particularly useful when aiming
at very small files. Typical values are around 20-30. Note that using the
option -strong/-nostrong will change the type of filtering. Use "-f 0" to
turn filtering off.
* 'm' controls the trade-off between encoding speed and quality. Default is 4.
You can try -m 5 or -m 6 to explore more (time-consuming) encoding
possibilities. A lower value will result in faster encoding at the expense
@ -161,7 +238,7 @@ Namely:
Decoding tool:
==============
There is a decoding sample code as examples/dwebp.c which will take
There is a decoding sample in examples/dwebp.c which will take
a .webp file and decode it to a PNG image file (amongst other formats).
This is simply to demonstrate the use of the API. You can verify the
file test.webp decodes to exactly the same as test_ref.ppm by using:
@ -170,9 +247,127 @@ file test.webp decodes to exactly the same as test_ref.ppm by using:
./dwebp test.webp -ppm -o test.ppm
diff test.ppm test_ref.ppm
The full list of options is available using -h:
> dwebp -h
Usage: dwebp in_file [options] [-o out_file]
Decodes the WebP image file to PNG format [Default]
Use following options to convert into alternate image formats:
-pam ......... save the raw RGBA samples as a color PAM
-ppm ......... save the raw RGB samples as a color PPM
-bmp ......... save as uncompressed BMP format
-tiff ........ save as uncompressed TIFF format
-pgm ......... save the raw YUV samples as a grayscale PGM
file with IMC4 layout
-yuv ......... save the raw YUV samples in flat layout
Other options are:
-version .... print version number and exit
-nofancy ..... don't use the fancy YUV420 upscaler
-nofilter .... disable in-loop filtering
-nodither .... disable dithering
-dither <d> .. dithering strength (in 0..100)
-mt .......... use multi-threading
-crop <x> <y> <w> <h> ... crop output with the given rectangle
-scale <w> <h> .......... scale the output (*after* any cropping)
-alpha ....... only save the alpha plane
-incremental . use incremental decoding (useful for tests)
-h ....... this help message
-v ....... verbose (e.g. print encoding/decoding times)
-noasm ....... disable all assembly optimizations
Visualization tool:
===================
There's a little self-serve visualization tool called 'vwebp' under the
examples/ directory. It uses OpenGL to open a simple drawing window and show
a decoded WebP file. It's not yet integrated in the automake build system, but
you can try to manually compile it using the recommendations below.
Usage: vwebp in_file [options]
Decodes the WebP image file and visualize it using OpenGL
Options are:
-version .... print version number and exit
-noicc ....... don't use the icc profile if present
-nofancy ..... don't use the fancy YUV420 upscaler
-nofilter .... disable in-loop filtering
-dither <int> dithering strength (0..100), default=50
-mt .......... use multi-threading
-info ........ print info
-h ....... this help message
Keyboard shortcuts:
'c' ................ toggle use of color profile
'i' ................ overlay file information
'q' / 'Q' / ESC .... quit
Building:
---------
Prerequisites:
1) OpenGL & OpenGL Utility Toolkit (GLUT)
Linux:
$ sudo apt-get install freeglut3-dev mesa-common-dev
Mac + XCode:
- These libraries should be available in the OpenGL / GLUT frameworks.
Windows:
http://freeglut.sourceforge.net/index.php#download
2) (Optional) qcms (Quick Color Management System)
i. Download qcms from Mozilla / Chromium:
http://hg.mozilla.org/mozilla-central/file/0e7639e3bdfb/gfx/qcms
http://src.chromium.org/viewvc/chrome/trunk/src/third_party/qcms
ii. Build and archive the source files as libqcms.a / qcms.lib
iii. Update makefile.unix / Makefile.vc
a) Define WEBP_HAVE_QCMS
b) Update include / library paths to reference the qcms directory.
Build using makefile.unix / Makefile.vc:
$ make -f makefile.unix examples/vwebp
> nmake /f Makefile.vc CFG=release-static \
../obj/x64/release-static/bin/vwebp.exe
Animated GIF conversion:
========================
Animated GIF files can be converted to WebP files with animation using the
gif2webp utility available under examples/. The files can then be viewed using
vwebp.
Usage:
gif2webp [options] gif_file -o webp_file
Options:
-h / -help ............ this help
-lossy ................. encode image using lossy compression
-mixed ................. for each frame in the image, pick lossy
or lossless compression heuristically
-q <float> ............. quality factor (0:small..100:big)
-m <int> ............... compression method (0=fast, 6=slowest)
-kmin <int> ............ min distance between key frames
-kmax <int> ............ max distance between key frames
-f <int> ............... filter strength (0=off..100)
-metadata <string> ..... comma separated list of metadata to
copy from the input to the output if present
Valid values: all, none, icc, xmp (default)
-mt .................... use multi-threading if available
-version ............... print version number and exit
-v ..................... verbose
-quiet ................. don't print anything
Building:
---------
With the libgif development files installed, gif2webp can be built using
makefile.unix:
$ make -f makefile.unix examples/gif2webp
or using autoconf:
$ ./configure --enable-everything
$ make
Encoding API:
===========
=============
The main encoding functions are available in the header src/webp/encode.h
The ready-to-use ones are:
@ -188,10 +383,26 @@ size_t WebPEncodeBGRA(const uint8_t* bgra, int width, int height, int stride,
They will convert raw RGB samples to a WebP data. The only control supplied
is the quality factor.
There are some variants for using the lossless format:
size_t WebPEncodeLosslessRGB(const uint8_t* rgb, int width, int height,
int stride, uint8_t** output);
size_t WebPEncodeLosslessBGR(const uint8_t* bgr, int width, int height,
int stride, uint8_t** output);
size_t WebPEncodeLosslessRGBA(const uint8_t* rgba, int width, int height,
int stride, uint8_t** output);
size_t WebPEncodeLosslessBGRA(const uint8_t* bgra, int width, int height,
int stride, uint8_t** output);
Of course in this case, no quality factor is needed since the compression
occurs without loss of the input values, at the expense of larger output sizes.
Advanced encoding API:
----------------------
A more advanced API is based on the WebPConfig and WebPPicture structures.
WebPConfig contains the encoding settings and is not tied a to a particular
WebPConfig contains the encoding settings and is not tied to a particular
picture.
WebPPicture contains input data, on which some WebPConfig will be used for
compression.
@ -210,7 +421,7 @@ The encoding flow looks like:
// ... additional tuning
config.sns_strength = 90;
config.filter_sharpness = 6;
config_error = WebPValidateConfig(&config); // not mandartory, but useful
config_error = WebPValidateConfig(&config); // not mandatory, but useful
// Setup the input data
WebPPicture pic;
@ -223,50 +434,51 @@ The encoding flow looks like:
if (!WebPPictureAllocate(&pic)) {
return 0; // memory error
}
// add that point, 'pic' has been initialized as a container,
// at this point, 'pic' has been initialized as a container,
// and can receive the Y/U/V samples.
// Alternatively, one could use ready-made import functions like
// WebPPictureImportRGB(), which will take care of memory allocation.
// In any case, past this point, one will have to call
// WebPPictureFree(&pic) to reclaim memory.
// Set up a byte-output write method. WebPMemoryWriter, for instance.
WebPMemoryWriter wrt;
WebPMemoryWriterInit(&wrt); // initialize 'wrt'
pic.writer = MyFileWriter;
pic.custom_ptr = my_opaque_structure_to_make_MyFileWriter_work;
// initialize 'wrt' here...
// Compress!
int ok = WebPEncode(&config, &pic); // ok = 0 => error occured!
int ok = WebPEncode(&config, &pic); // ok = 0 => error occurred!
WebPPictureFree(&pic); // must be called independently of the 'ok' result.
// output data should have been handled by the writer at that point.
// -> compressed data is the memory buffer described by wrt.mem / wrt.size
// deallocate the memory used by compressed data
WebPMemoryWriterClear(&wrt);
-------------------------------------- END PSEUDO EXAMPLE
Decoding API:
=============
This is mainly just one function to call:
#include "webp/decode.h"
uint8_t* WebPDecodeRGB(const uint8_t* data, uint32_t data_size,
int *width, int *height);
uint8_t* WebPDecodeRGB(const uint8_t* data, size_t data_size,
int* width, int* height);
Please have a look at the file src/webp/decode.h for the details.
There are variants for decoding in BGR/RGBA/BGRA order, along with decoding to
raw Y'CbCr samples. One can also decode the image directly into a pre-allocated
buffer.
There are variants for decoding in BGR/RGBA/ARGB/BGRA order, along with
decoding to raw Y'CbCr samples. One can also decode the image directly into a
pre-allocated buffer.
To detect a WebP file and gather picture's dimensions, the function:
int WebPGetInfo(const uint8_t* data, uint32_t data_size,
int *width, int *height);
To detect a WebP file and gather the picture's dimensions, the function:
int WebPGetInfo(const uint8_t* data, size_t data_size,
int* width, int* height);
is supplied. No decoding is involved when using it.
A lower-level API is available from the header file <webp/decode_vp8.h>
Incremental decoding API:
=========================
@ -276,7 +488,11 @@ is stored into an instance of the WebPIDecoder object. This object can be
created with the purpose of decoding either RGB or Y'CbCr samples.
For instance:
WebPIDecoder* idec = WebPINew(MODE_BGR);
WebPDecBuffer buffer;
WebPInitDecBuffer(&buffer);
buffer.colorspace = MODE_BGR;
...
WebPIDecoder* idec = WebPINewDecoder(&buffer);
As data is made progressively available, this incremental-decoder object
can be used to decode the picture further. There are two (mutually exclusive)
@ -290,26 +506,92 @@ or by just mentioning the new size of the transmitted data:
WebPIUpdate(idec, buffer, size_of_transmitted_buffer);
Note that 'buffer' can be modified between each calls to WebPIUpdate, in
particular when the buffer is resized to accomodate larger data.
Note that 'buffer' can be modified between each call to WebPIUpdate, in
particular when the buffer is resized to accommodate larger data.
These functions will return the decoding status: either VP8_STATUS_SUSPENDED if
decoding is not finished yet, or VP8_STATUS_OK when decoding is done.
Any other status is an error condition.
decoding is not finished yet or VP8_STATUS_OK when decoding is done. Any other
status is an error condition.
The idec object must always be released (even upon an error condition)
by calling: WebPDelete(idec)
The 'idec' object must always be released (even upon an error condition) by
calling: WebPDelete(idec).
To retrieve partially decoded picture samples, one must use the corresponding
method: WebPIDecGetRGB or WebPIDecGetYUV.
method: WebPIDecGetRGB or WebPIDecGetYUVA.
It will return the last displayable pixel row.
Lastly, note that decoding can also be performed into a pre-allocated pixel
buffer. This buffer must be passed when creating a WebPIDecoder, calling
WebPINewRGB() or WebPINewYUV().
WebPINewRGB() or WebPINewYUVA().
Please have a look at the src/webp/decode.h header for further details.
Advanced Decoding API:
======================
WebP decoding supports an advanced API which provides on-the-fly cropping and
rescaling, something of great usefulness on memory-constrained environments like
mobile phones. Basically, the memory usage will scale with the output's size,
not the input's, when one only needs a quick preview or a zoomed in portion of
an otherwise too-large picture. Some CPU can be saved too, incidentally.
-------------------------------------- BEGIN PSEUDO EXAMPLE
// A) Init a configuration object
WebPDecoderConfig config;
CHECK(WebPInitDecoderConfig(&config));
// B) optional: retrieve the bitstream's features.
CHECK(WebPGetFeatures(data, data_size, &config.input) == VP8_STATUS_OK);
// C) Adjust 'config' options, if needed
config.options.no_fancy_upsampling = 1;
config.options.use_scaling = 1;
config.options.scaled_width = scaledWidth();
config.options.scaled_height = scaledHeight();
// etc.
// D) Specify 'config' output options for specifying output colorspace.
// Optionally the external image decode buffer can also be specified.
config.output.colorspace = MODE_BGRA;
// Optionally, the config.output can be pointed to an external buffer as
// well for decoding the image. This externally supplied memory buffer
// should be big enough to store the decoded picture.
config.output.u.RGBA.rgba = (uint8_t*) memory_buffer;
config.output.u.RGBA.stride = scanline_stride;
config.output.u.RGBA.size = total_size_of_the_memory_buffer;
config.output.is_external_memory = 1;
// E) Decode the WebP image. There are two variants w.r.t decoding image.
// The first one (E.1) decodes the full image and the second one (E.2) is
// used to incrementally decode the image using small input buffers.
// Any one of these steps can be used to decode the WebP image.
// E.1) Decode full image.
CHECK(WebPDecode(data, data_size, &config) == VP8_STATUS_OK);
// E.2) Decode image incrementally.
WebPIDecoder* const idec = WebPIDecode(NULL, NULL, &config);
CHECK(idec != NULL);
while (bytes_remaining > 0) {
VP8StatusCode status = WebPIAppend(idec, input, bytes_read);
if (status == VP8_STATUS_OK || status == VP8_STATUS_SUSPENDED) {
bytes_remaining -= bytes_read;
} else {
break;
}
}
WebPIDelete(idec);
// F) Decoded image is now in config.output (and config.output.u.RGBA).
// It can be saved, displayed or otherwise processed.
// G) Reclaim memory allocated in config's object. It's safe to call
// this function even if the memory is external and wasn't allocated
// by WebPDecode().
WebPFreeDecBuffer(&config.output);
-------------------------------------- END PSEUDO EXAMPLE
Bugs:
=====
@ -322,3 +604,4 @@ Discuss:
========
Email: webp-discuss@webmproject.org
Web: http://groups.google.com/a/webmproject.org/group/webp-discuss

186
README.mux Normal file
View File

@ -0,0 +1,186 @@
 __ __ ____ ____ ____ __ __ _ __ __
/ \\/ \/ _ \/ _ \/ _ \/ \ \/ \___/_ / _\
\ / __/ _ \ __/ / / (_/ /__
\__\__/\_____/_____/__/ \__//_/\_____/__/___/v0.2.2
Description:
============
WebPMux: set of two libraries 'Mux' and 'Demux' for creation, extraction and
manipulation of an extended format WebP file, which can have features like
color profile, metadata and animation. Reference command-line tools 'webpmux'
and 'vwebp' as well as the WebP container specification
'doc/webp-container-spec.txt' are also provided in this package.
WebP Mux tool:
==============
The examples/ directory contains a tool (webpmux) for manipulating WebP
files. The webpmux tool can be used to create an extended format WebP file and
also to extract or strip relevant data from such a file.
A list of options is available using the -help command line flag:
> webpmux -help
Usage: webpmux -get GET_OPTIONS INPUT -o OUTPUT
webpmux -set SET_OPTIONS INPUT -o OUTPUT
webpmux -strip STRIP_OPTIONS INPUT -o OUTPUT
webpmux -frame FRAME_OPTIONS [-frame...] [-loop LOOP_COUNT]
[-bgcolor BACKGROUND_COLOR] -o OUTPUT
webpmux -info INPUT
webpmux [-h|-help]
webpmux -version
GET_OPTIONS:
Extract relevant data:
icc get ICC profile
exif get EXIF metadata
xmp get XMP metadata
frame n get nth frame
SET_OPTIONS:
Set color profile/metadata:
icc file.icc set ICC profile
exif file.exif set EXIF metadata
xmp file.xmp set XMP metadata
where: 'file.icc' contains the ICC profile to be set,
'file.exif' contains the EXIF metadata to be set
'file.xmp' contains the XMP metadata to be set
STRIP_OPTIONS:
Strip color profile/metadata:
icc strip ICC profile
exif strip EXIF metadata
xmp strip XMP metadata
FRAME_OPTIONS(i):
Create animation:
file_i +di+[xi+yi[+mi[bi]]]
where: 'file_i' is the i'th animation frame (WebP format),
'di' is the pause duration before next frame,
'xi','yi' specify the image offset for this frame,
'mi' is the dispose method for this frame (0 or 1),
'bi' is the blending method for this frame (+b or -b)
LOOP_COUNT:
Number of times to repeat the animation.
Valid range is 0 to 65535 [Default: 0 (infinite)].
BACKGROUND_COLOR:
Background color of the canvas.
A,R,G,B
where: 'A', 'R', 'G' and 'B' are integers in the range 0 to 255 specifying
the Alpha, Red, Green and Blue component values respectively
[Default: 255,255,255,255]
INPUT & OUTPUT are in WebP format.
Note: The nature of EXIF, XMP and ICC data is not checked and is assumed to be
valid.
Visualization tool:
===================
The examples/ directory also contains a tool (vwebp) for viewing WebP files.
It decodes the image and visualizes it using OpenGL. See the libwebp README
for details on building and running this program.
Mux API:
========
The Mux API contains methods for adding data to and reading data from WebP
files. This API currently supports XMP/EXIF metadata, ICC profile and animation.
Other features may be added in subsequent releases.
Example#1 (pseudo code): Creating a WebPMux object with image data, color
profile and XMP metadata.
int copy_data = 0;
WebPMux* mux = WebPMuxNew();
// ... (Prepare image data).
WebPMuxSetImage(mux, &image, copy_data);
// ... (Prepare ICC profile data).
WebPMuxSetChunk(mux, "ICCP", &icc_profile, copy_data);
// ... (Prepare XMP metadata).
WebPMuxSetChunk(mux, "XMP ", &xmp, copy_data);
// Get data from mux in WebP RIFF format.
WebPMuxAssemble(mux, &output_data);
WebPMuxDelete(mux);
// ... (Consume output_data; e.g. write output_data.bytes to file).
WebPDataClear(&output_data);
Example#2 (pseudo code): Get image and color profile data from a WebP file.
int copy_data = 0;
// ... (Read data from file).
WebPMux* mux = WebPMuxCreate(&data, copy_data);
WebPMuxGetFrame(mux, 1, &image);
// ... (Consume image; e.g. call WebPDecode() to decode the data).
WebPMuxGetChunk(mux, "ICCP", &icc_profile);
// ... (Consume icc_profile).
WebPMuxDelete(mux);
free(data);
For a detailed Mux API reference, please refer to the header file
(src/webp/mux.h).
Demux API:
==========
The Demux API enables extraction of images and extended format data from
WebP files. This API currently supports reading of XMP/EXIF metadata, ICC
profile and animated images. Other features may be added in subsequent
releases.
Code Example: Demuxing WebP data to extract all the frames, ICC profile
and EXIF/XMP metadata.
WebPDemuxer* demux = WebPDemux(&webp_data);
uint32_t width = WebPDemuxGetI(demux, WEBP_FF_CANVAS_WIDTH);
uint32_t height = WebPDemuxGetI(demux, WEBP_FF_CANVAS_HEIGHT);
// ... (Get information about the features present in the WebP file).
uint32_t flags = WebPDemuxGetI(demux, WEBP_FF_FORMAT_FLAGS);
// ... (Iterate over all frames).
WebPIterator iter;
if (WebPDemuxGetFrame(demux, 1, &iter)) {
do {
// ... (Consume 'iter'; e.g. Decode 'iter.fragment' with WebPDecode(),
// ... and get other frame properties like width, height, offsets etc.
// ... see 'struct WebPIterator' below for more info).
} while (WebPDemuxNextFrame(&iter));
WebPDemuxReleaseIterator(&iter);
}
// ... (Extract metadata).
WebPChunkIterator chunk_iter;
if (flags & ICCP_FLAG) WebPDemuxGetChunk(demux, "ICCP", 1, &chunk_iter);
// ... (Consume the ICC profile in 'chunk_iter.chunk').
WebPDemuxReleaseChunkIterator(&chunk_iter);
if (flags & EXIF_FLAG) WebPDemuxGetChunk(demux, "EXIF", 1, &chunk_iter);
// ... (Consume the EXIF metadata in 'chunk_iter.chunk').
WebPDemuxReleaseChunkIterator(&chunk_iter);
if (flags & XMP_FLAG) WebPDemuxGetChunk(demux, "XMP ", 1, &chunk_iter);
// ... (Consume the XMP metadata in 'chunk_iter.chunk').
WebPDemuxReleaseChunkIterator(&chunk_iter);
WebPDemuxDelete(demux);
For a detailed Demux API reference, please refer to the header file
(src/webp/demux.h).
Bugs:
=====
Please report all bugs to our issue tracker:
http://code.google.com/p/webp/issues
Patches welcome! See this page to get started:
http://www.webmproject.org/code/contribute/submitting-patches/
Discuss:
========
Email: webp-discuss@webmproject.org
Web: http://groups.google.com/a/webmproject.org/group/webp-discuss

View File

@ -1,73 +1,573 @@
AC_INIT([webpdecode], [0.1])
AC_INIT([libwebp], [0.4.2],
[http://code.google.com/p/webp/issues],,
[http://developers.google.com/speed/webp])
AC_CANONICAL_HOST
AC_PREREQ([2.60])
AM_INIT_AUTOMAKE([-Wall foreign subdir-objects])
dnl === automake >= 1.12 requires this for 'unusual archivers' support.
dnl === it must occur before LT_INIT (AC_PROG_LIBTOOL).
m4_ifdef([AM_PROG_AR], [AM_PROG_AR])
AC_PROG_LIBTOOL
AM_PROG_CC_C_O
AC_ARG_WITH([pkgconfigdir], AS_HELP_STRING([--with-pkgconfigdir=PATH],
[Path to the pkgconfig directory [[LIBDIR/pkgconfig]]]),
[pkgconfigdir="$withval"], [pkgconfigdir='${libdir}/pkgconfig'])
dnl === Enable less verbose output when building.
m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])])
dnl == test endianness
AC_C_BIGENDIAN
dnl === SET_IF_UNSET(shell_var, value)
dnl === Set the shell variable 'shell_var' to 'value' if it is unset.
AC_DEFUN([SET_IF_UNSET], [test "${$1+set}" = "set" || $1=$2])
AC_ARG_ENABLE([everything],
AS_HELP_STRING([--enable-everything],
[Enable all optional targets. These can still be
disabled with --disable-target]),
[SET_IF_UNSET([enable_libwebpdecoder], [$enableval])
SET_IF_UNSET([enable_libwebpdemux], [$enableval])
SET_IF_UNSET([enable_libwebpmux], [$enableval])])
AC_ARG_WITH([pkgconfigdir], AS_HELP_STRING([--with-pkgconfigdir=DIR],
[Path to the pkgconfig directory @<:@LIBDIR/pkgconfig@:>@]),
[pkgconfigdir="$withval"], [pkgconfigdir='${libdir}/pkgconfig'])
AC_SUBST([pkgconfigdir])
dnl === TEST_AND_ADD_CFLAGS(var, flag)
dnl === Checks whether $CC supports 'flag' and adds it to 'var'
dnl === on success.
AC_DEFUN([TEST_AND_ADD_CFLAGS],
[SAVED_CFLAGS="$CFLAGS"
CFLAGS="-Werror $2"
AC_MSG_CHECKING([whether $CC supports $2])
dnl Note AC_LANG_PROGRAM([]) uses an old-style main definition.
AC_COMPILE_IFELSE([AC_LANG_SOURCE([int main(void) { return 0; }])],
[AC_MSG_RESULT([yes])]
dnl Simply append the variable avoiding a
dnl compatibility ifdef for AS_VAR_APPEND as this
dnl variable shouldn't grow all that large.
[$1="${$1} $2"],
[AC_MSG_RESULT([no])])
CFLAGS="$SAVED_CFLAGS"])
TEST_AND_ADD_CFLAGS([AM_CFLAGS], [-Wall])
TEST_AND_ADD_CFLAGS([AM_CFLAGS], [-Wdeclaration-after-statement])
TEST_AND_ADD_CFLAGS([AM_CFLAGS], [-Wextra])
TEST_AND_ADD_CFLAGS([AM_CFLAGS], [-Wformat-security])
TEST_AND_ADD_CFLAGS([AM_CFLAGS], [-Wmissing-declarations])
TEST_AND_ADD_CFLAGS([AM_CFLAGS], [-Wmissing-prototypes])
TEST_AND_ADD_CFLAGS([AM_CFLAGS], [-Wold-style-definition])
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
TEST_AND_ADD_CFLAGS([AVX2_FLAGS], [-mavx2])
AS_IF([test -n "$AVX2_FLAGS"], [
SAVED_CFLAGS=$CFLAGS
CFLAGS="$CFLAGS $AVX2_FLAGS"
AC_CHECK_HEADER([immintrin.h],
[AC_DEFINE(WEBP_HAVE_AVX2, [1],
[Set to 1 if AVX2 is supported])],
[AVX2_FLAGS=""],
dnl it's illegal to directly include avx2intrin.h, but it's
dnl included conditionally in immintrin.h, tricky!
[#ifndef __AVX2__
#error avx2 is not enabled
#endif
])
CFLAGS=$SAVED_CFLAGS])
AC_SUBST([AVX2_FLAGS])
TEST_AND_ADD_CFLAGS([SSE2_FLAGS], [-msse2])
AS_IF([test -n "$SSE2_FLAGS"], [
SAVED_CFLAGS=$CFLAGS
CFLAGS="$CFLAGS $SSE2_FLAGS"
AC_CHECK_HEADER([emmintrin.h],
[AC_DEFINE(WEBP_HAVE_SSE2, [1],
[Set to 1 if SSE2 is supported])],
[SSE2_FLAGS=""])
CFLAGS=$SAVED_CFLAGS])
AC_SUBST([SSE2_FLAGS])
dnl === CLEAR_LIBVARS([var_pfx])
dnl === Clears <var_pfx>_{INCLUDES,LIBS}.
AC_DEFUN([CLEAR_LIBVARS], [$1_INCLUDES=""; $1_LIBS=""])
dnl === WITHLIB_OPTION([opt_pfx], [outvar_pfx])
dnl === Defines --with-<opt_pfx>{include,lib}dir options which set
dnl === the variables <outvar_pfx>_{INCLUDES,LIBS}.
AC_DEFUN([WITHLIB_OPTION],
[AC_ARG_WITH([$1includedir],
AS_HELP_STRING([--with-$1includedir=DIR],
[use $2 includes from DIR]),
$2_INCLUDES="-I$withval")
AC_ARG_WITH([$1libdir],
AS_HELP_STRING([--with-$1libdir=DIR],
[use $2 libraries from DIR]),
[$2_LIBS="-L$withval"])])
dnl === LIBCHECK_PROLOGUE([var_pfx])
dnl === Caches the current values of CPPFLAGS/LIBS in SAVED_* then
dnl === prepends the current values with <var_pfx>_{INCLUDES,LIBS}.
AC_DEFUN([LIBCHECK_PROLOGUE],
[SAVED_CPPFLAGS=$CPPFLAGS
SAVED_LIBS=$LIBS
CPPFLAGS="$$1_INCLUDES $CPPFLAGS"
LIBS="$$1_LIBS $LIBS"])
dnl === LIBCHECK_EPILOGUE([var_pfx])
dnl === Restores the values of CPPFLAGS/LIBS from SAVED_* and exports
dnl === <var_pfx>_{INCLUDES,LIBS} with AC_SUBST.
AC_DEFUN([LIBCHECK_EPILOGUE],
[AC_SUBST($1_LIBS)
AC_SUBST($1_INCLUDES)
CPPFLAGS=$SAVED_CPPFLAGS
LIBS=$SAVED_LIBS])
dnl === Check for gcc builtins
dnl === CHECK_FOR_BUILTIN([builtin], [param], [define])
dnl === links a C AC_LANG_PROGRAM, with <builtin>(<param>)
dnl === AC_DEFINE'ing <define> if successful.
AC_DEFUN([CHECK_FOR_BUILTIN],
[AC_LANG_PUSH([C])
AC_MSG_CHECKING([for $1])
AC_LINK_IFELSE([AC_LANG_PROGRAM([], [$1($2)])],
[AC_MSG_RESULT([yes])
AC_DEFINE([$3], [1],
[Set to 1 if $1 is available])],
[AC_MSG_RESULT([no])]),
AC_LANG_POP])
dnl AC_CHECK_FUNC doesn't work with builtin's.
CHECK_FOR_BUILTIN([__builtin_bswap16], [1u << 15], [HAVE_BUILTIN_BSWAP16])
CHECK_FOR_BUILTIN([__builtin_bswap32], [1u << 31], [HAVE_BUILTIN_BSWAP32])
CHECK_FOR_BUILTIN([__builtin_bswap64], [1ull << 63], [HAVE_BUILTIN_BSWAP64])
dnl === Check for pthread support
AC_ARG_ENABLE([threading],
AS_HELP_STRING([--disable-threading],
[Disable detection of thread support]),,
[enable_threading=yes])
if test "$enable_threading" = "yes"; then
AC_MSG_NOTICE([checking for threading support...])
AX_PTHREAD([AC_DEFINE([WEBP_USE_THREAD], [1],
[Undefine this to disable thread support.])
LIBS="$PTHREAD_LIBS $LIBS"
CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
CC="$PTHREAD_CC"
],
[AC_CHECK_FUNC([_beginthreadex],
[AC_DEFINE([WEBP_USE_THREAD], [1],
[Undefine this to disable thread
support.])],
[enable_threading=no])])
fi
AC_MSG_NOTICE([checking if threading is enabled... ${enable_threading-no}])
dnl === check for OpenGL/GLUT support ===
AC_ARG_ENABLE([gl], AS_HELP_STRING([--disable-gl],
[Disable detection of OpenGL support
@<:@default=auto@:>@]))
AS_IF([test "x$enable_gl" != "xno"], [
CLEAR_LIBVARS([GL])
WITHLIB_OPTION([gl], [GL])
LIBCHECK_PROLOGUE([GL])
glut_cflags="none"
glut_ldflags="none"
case $host_os in
darwin*)
# Special case for OSX builds. Append these to give the user a chance to
# override with --with-gl*
glut_cflags="$glut_cflags|-framework GLUT -framework OpenGL"
glut_ldflags="$glut_ldflags|-framework GLUT -framework OpenGL"
;;
esac
GLUT_SAVED_CPPFLAGS="$CPPFLAGS"
SAVED_IFS="$IFS"
IFS="|"
for flag in $glut_cflags; do
# restore IFS immediately as the autoconf macros may need the default.
IFS="$SAVED_IFS"
unset ac_cv_header_GL_glut_h
unset ac_cv_header_OpenGL_glut_h
case $flag in
none) ;;
*) CPPFLAGS="$flag $CPPFLAGS";;
esac
AC_CHECK_HEADERS([GL/glut.h GLUT/glut.h OpenGL/glut.h],
[glut_headers=yes;
test "$flag" = "none" || GL_INCLUDES="$CPPFLAGS";
break])
CPPFLAGS="$GLUT_SAVED_CPPFLAGS"
test "$glut_headers" = "yes" && break
done
IFS="$SAVED_IFS"
if test "$glut_headers" = "yes"; then
AC_LANG_PUSH([C])
GLUT_SAVED_LDFLAGS="$LDFLAGS"
SAVED_IFS="$IFS"
IFS="|"
for flag in $glut_ldflags; do
# restore IFS immediately as the autoconf macros may need the default.
IFS="$SAVED_IFS"
unset ac_cv_search_glBegin
case $flag in
none) ;;
*) LDFLAGS="$flag $LDFLAGS";;
esac
# find libGL
GL_SAVED_LIBS="$LIBS"
AC_SEARCH_LIBS([glBegin], [GL OpenGL opengl32])
LIBS="$GL_SAVED_LIBS"
# A direct link to libGL may not be necessary on e.g., linux.
GLUT_SAVED_LIBS="$LIBS"
for lib in "" "-lglut" "-lglut $ac_cv_search_glBegin"; do
LIBS="$lib"
AC_LINK_IFELSE(
[AC_LANG_PROGRAM([
#ifdef __cplusplus
# define EXTERN_C extern "C"
#else
# define EXTERN_C
#endif
EXTERN_C char glOrtho();
EXTERN_C char glutMainLoop();
],[
glOrtho();
glutMainLoop();
])
],
AC_DEFINE(WEBP_HAVE_GL, [1],
[Set to 1 if OpenGL is supported])
[glut_support=yes], []
)
if test "$glut_support" = "yes"; then
GL_LIBS="$LDFLAGS $lib"
break
fi
done
LIBS="$GLUT_SAVED_LIBS"
LDFLAGS="$GLUT_SAVED_LDFLAGS"
test "$glut_support" = "yes" && break
done
IFS="$SAVED_IFS"
AC_LANG_POP
fi
LIBCHECK_EPILOGUE([GL])
if test "$glut_support" = "yes" -a "$enable_libwebpdemux" = "yes"; then
build_vwebp=yes
fi
])
AM_CONDITIONAL([BUILD_VWEBP], [test "$build_vwebp" = "yes"])
dnl === check for PNG support ===
PNG_INCLUDES=""
PNG_LIBS=""
AC_PATH_PROG(LIBPNG_CONFIG, libpng-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"
AC_ARG_ENABLE([png], AS_HELP_STRING([--disable-png],
[Disable detection of PNG format support
@<:@default=auto@:>@]))
AS_IF([test "x$enable_png" != "xno"], [
CLEAR_LIBVARS([PNG])
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_LIBS="`$LIBPNG_CONFIG --ldflags`"
fi
fi
AC_ARG_WITH(pngincludedir,
[--with-pngincludedir=DIR use PNG includes from DIR],
PNG_INCLUDES="-I$withval")
AC_ARG_WITH(pnglibdir,
[--with-pnglibdir=DIR use PNG libraries from DIR],
[PNG_LIBS="-L$withval"])
WITHLIB_OPTION([png], [PNG])
AC_CHECK_HEADER(png.h,
AC_CHECK_LIB(png, main,
[PNG_LIBS="$PNG_LIBS -lpng"
PNG_INCLUDES="$PNG_INCLUDES -DWEBP_HAVE_PNG"
AC_DEFINE(WEBP_HAVE_PNG, [1], [Set to 1 if PNG library is installed])
],
AC_MSG_WARN(Optional png library not found),
[$MATH_LIBS]),
AC_MSG_WARN(png library not available - no png.h)
)
AC_SUBST(PNG_LIBS)
AC_SUBST(PNG_INCLUDES)
LIBCHECK_PROLOGUE([PNG])
AC_CHECK_HEADER(png.h,
AC_SEARCH_LIBS(png_get_libpng_ver, [png],
[test "$ac_cv_search_png_get_libpng_ver" = "none required" \
|| PNG_LIBS="$PNG_LIBS $ac_cv_search_png_get_libpng_ver"
PNG_INCLUDES="$PNG_INCLUDES -DWEBP_HAVE_PNG"
AC_DEFINE(WEBP_HAVE_PNG, [1],
[Set to 1 if PNG library is installed])
png_support=yes
],
[AC_MSG_WARN(Optional png library not found)
PNG_LIBS=""
PNG_INCLUDES=""
],
[$MATH_LIBS]),
[AC_MSG_WARN(png library not available - no png.h)
PNG_LIBS=""
PNG_INCLUDES=""
],
)
LIBCHECK_EPILOGUE([PNG])
])
dnl === check for JPEG support ===
JPEG_INCLUDES=""
JPEG_LIBS=""
AC_ARG_WITH(jpegincludedir,
[--with-jpegincludedir=DIR use JPEG includes from DIR],
JPEG_INCLUDES="-I$withval")
AC_ARG_WITH(jpeglibdir,
[--with-jpeglibdir=DIR use JPEG libraries from DIR],
[JPEG_LIBS="-L$withval"])
AC_ARG_ENABLE([jpeg],
AS_HELP_STRING([--disable-jpeg],
[Disable detection of JPEG format support
@<:@default=auto@:>@]))
AS_IF([test "x$enable_jpeg" != "xno"], [
CLEAR_LIBVARS([JPEG])
WITHLIB_OPTION([jpeg], [JPEG])
AC_CHECK_HEADER(jpeglib.h,
AC_CHECK_LIB(jpeg, jpeg_set_defaults,
[JPEG_LIBS="$JPEG_LIBS -ljpeg"
JPEG_INCLUDES="$JPEG_INCLUDES -DWEBP_HAVE_JPEG"
AC_DEFINE(WEBP_HAVE_JPEG, [1], [Set to 1 if JPEG library is installed])
],
AC_MSG_WARN(Optional jpeg library not found),
[$MATH_LIBS]),
AC_MSG_WARN(jpeg library not available - no jpeglib.h)
)
AC_SUBST(JPEG_LIBS)
AC_SUBST(JPEG_INCLUDES)
LIBCHECK_PROLOGUE([JPEG])
AC_CHECK_HEADER(jpeglib.h,
AC_CHECK_LIB(jpeg, jpeg_set_defaults,
[JPEG_LIBS="$JPEG_LIBS -ljpeg"
JPEG_INCLUDES="$JPEG_INCLUDES -DWEBP_HAVE_JPEG"
AC_DEFINE(WEBP_HAVE_JPEG, [1],
[Set to 1 if JPEG library is installed])
jpeg_support=yes
],
AC_MSG_WARN(Optional jpeg library not found),
[$MATH_LIBS]),
AC_MSG_WARN(jpeg library not available - no jpeglib.h)
)
LIBCHECK_EPILOGUE([JPEG])
])
dnl === check for TIFF support ===
AC_ARG_ENABLE([tiff],
AS_HELP_STRING([--disable-tiff],
[Disable detection of TIFF format support
@<:@default=auto@:>@]))
AS_IF([test "x$enable_tiff" != "xno"], [
CLEAR_LIBVARS([TIFF])
WITHLIB_OPTION([tiff], [TIFF])
LIBCHECK_PROLOGUE([TIFF])
AC_CHECK_HEADER(tiffio.h,
AC_CHECK_LIB(tiff, TIFFGetVersion,
[TIFF_LIBS="$TIFF_LIBS -ltiff"
TIFF_INCLUDES="$TIFF_INCLUDES -DWEBP_HAVE_TIFF"
AC_DEFINE(WEBP_HAVE_TIFF, [1],
[Set to 1 if TIFF library is installed])
tiff_support=yes
],
AC_MSG_WARN(Optional tiff library not found),
[$MATH_LIBS]),
AC_MSG_WARN(tiff library not available - no tiffio.h)
)
LIBCHECK_EPILOGUE([TIFF])
])
dnl === check for GIF support ===
AC_ARG_ENABLE([gif], AS_HELP_STRING([--disable-gif],
[Disable detection of GIF format support
@<:@default=auto@:>@]))
AS_IF([test "x$enable_gif" != "xno"], [
CLEAR_LIBVARS([GIF])
WITHLIB_OPTION([gif], [GIF])
LIBCHECK_PROLOGUE([GIF])
AC_CHECK_HEADER(gif_lib.h,
AC_CHECK_LIB([gif], [DGifOpenFileHandle],
[GIF_LIBS="$GIF_LIBS -lgif"
AC_DEFINE(WEBP_HAVE_GIF, [1],
[Set to 1 if GIF library is installed])
gif_support=yes
],
AC_MSG_WARN(Optional gif library not found),
[$MATH_LIBS]),
AC_MSG_WARN(gif library not available - no gif_lib.h)
)
LIBCHECK_EPILOGUE([GIF])
if test "$gif_support" = "yes" -a \
"$enable_libwebpmux" = "yes"; then
build_gif2webp=yes
fi
])
AM_CONDITIONAL([BUILD_GIF2WEBP], [test "${build_gif2webp}" = "yes"])
dnl === check for WIC support ===
AC_ARG_ENABLE([wic],
AS_HELP_STRING([--disable-wic],
[Disable Windows Imaging Component (WIC) detection.
@<:@default=auto@:>@]),,
[enable_wic=yes])
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)
SAVED_LIBS=$LIBS
LIBS="-lshlwapi -lole32 $LIBS"
# match include structure from [cd]webp.c
wic_headers="
#define INITGUID
#define CINTERFACE
#define COBJMACROS
#define _WIN32_IE 0x500
#include <shlwapi.h>
#include <windows.h>
#include <wincodec.h>
"
# test for functions from each lib and the GUID is created properly
wic_main="
int main(void) {
CLSID_WICImagingFactory;
CoInitialize(NULL);
SHCreateStreamOnFile(NULL, 0, NULL);
return 0;
}
"
AC_LANG_PUSH(C)
AC_LINK_IFELSE(
[AC_LANG_SOURCE([
$wic_headers
$wic_main])],
[wic_support=yes],
[wic_support=no]
)
AC_LANG_POP
test "$wic_support" = "yes" || LIBS=$SAVED_LIBS
AC_MSG_RESULT(${wic_support-no})
fi
fi
esac
dnl === If --enable-aligned is defined, define WEBP_FORCE_ALIGNED
AC_MSG_CHECKING(if --enable-aligned option is specified)
AC_ARG_ENABLE([aligned],
AS_HELP_STRING([--enable-aligned],
[Force aligned memory operations in non-dsp code
(may be slower)]))
if test "$enable_aligned" = "yes"; then
AC_DEFINE(WEBP_FORCE_ALIGNED, [1],
[Define to 1 to force aligned memory operations])
fi
AC_MSG_RESULT(${enable_aligned-no})
dnl === If --enable-swap-16bit-csp is defined, add -DWEBP_SWAP_16BIT_CSP
USE_SWAP_16BIT_CSP=""
AC_MSG_CHECKING(if --enable-swap-16bit-csp option is specified)
AC_ARG_ENABLE([swap-16bit-csp],
AS_HELP_STRING([--enable-swap-16bit-csp],
[Enable byte swap for 16 bit colorspaces]))
if test "$enable_swap_16bit_csp" = "yes"; then
USE_SWAP_16BIT_CSP="-DWEBP_SWAP_16BIT_CSP"
fi
AC_MSG_RESULT(${enable_swap_16bit_csp-no})
AC_SUBST(USE_SWAP_16BIT_CSP)
dnl === If --enable-experimental is defined, add -DWEBP_EXPERIMENTAL_FEATURES
USE_EXPERIMENTAL_CODE=""
AC_MSG_CHECKING(if --enable-experimental option is specified)
AC_ARG_ENABLE([experimental], AS_HELP_STRING([--enable-experimental],
[Activate experimental features]))
if test "$enable_experimental" = "yes"; then
AC_DEFINE(WEBP_EXPERIMENTAL_FEATURES, [1], [Enable experimental code])
USE_EXPERIMENTAL_CODE="-DWEBP_EXPERIMENTAL_FEATURES"
fi
AC_MSG_RESULT(${enable_experimental-no})
AC_SUBST(USE_EXPERIMENTAL_CODE)
dnl === Check whether libwebpmux should be built
AC_MSG_CHECKING(whether libwebpmux is to be built)
AC_ARG_ENABLE([libwebpmux],
AS_HELP_STRING([--enable-libwebpmux],
[Build libwebpmux @<:@default=no@:>@]))
AC_MSG_RESULT(${enable_libwebpmux-no})
AM_CONDITIONAL([WANT_MUX], [test "$enable_libwebpmux" = "yes"])
dnl === Check whether libwebpdemux should be built
AC_MSG_CHECKING(whether libwebpdemux is to be built)
AC_ARG_ENABLE([libwebpdemux],
AS_HELP_STRING([--enable-libwebpdemux],
[Build libwebpdemux @<:@default=no@:>@]))
AC_MSG_RESULT(${enable_libwebpdemux-no})
AM_CONDITIONAL([WANT_DEMUX], [test "$enable_libwebpdemux" = "yes"])
dnl === Check whether decoder library should be built.
AC_MSG_CHECKING(whether decoder library is to be built)
AC_ARG_ENABLE([libwebpdecoder],
AS_HELP_STRING([--enable-libwebpdecoder],
[Build libwebpdecoder @<:@default=no@:>@]))
AC_MSG_RESULT(${enable_libwebpdecoder-no})
AM_CONDITIONAL([BUILD_LIBWEBPDECODER], [test "$enable_libwebpdecoder" = "yes"])
dnl =========================
AC_CONFIG_MACRO_DIR([m4])
AC_CONFIG_HEADERS([config.h])
AC_CONFIG_FILES([Makefile src/Makefile man/Makefile examples/Makefile src/dec/Makefile src/enc/Makefile src/libwebp.pc])
AC_CONFIG_HEADERS([src/webp/config.h])
AC_CONFIG_FILES([Makefile src/Makefile man/Makefile \
examples/Makefile src/dec/Makefile \
src/enc/Makefile src/dsp/Makefile \
src/demux/Makefile src/mux/Makefile \
src/utils/Makefile \
src/libwebp.pc src/libwebpdecoder.pc \
src/demux/libwebpdemux.pc src/mux/libwebpmux.pc])
AC_OUTPUT
AC_MSG_NOTICE([
WebP Configuration Summary
--------------------------
Shared libraries: ${enable_shared}
Static libraries: ${enable_static}
Threading support: ${enable_threading-no}
libwebp: yes
libwebpdecoder: ${enable_libwebpdecoder-no}
libwebpdemux: ${enable_libwebpdemux-no}
libwebpmux: ${enable_libwebpmux-no}
Tools:
cwebp : yes
Input format support
====================
JPEG : ${jpeg_support-no}
PNG : ${png_support-no}
TIFF : ${tiff_support-no}
WIC : ${wic_support-no}
dwebp : yes
Output format support
=====================
PNG : ${png_support-no}
WIC : ${wic_support-no}
GIF support : ${gif_support-no}
gif2webp : ${build_gif2webp-no}
webpmux : ${enable_libwebpmux-no}
vwebp : ${build_vwebp-no}
])

29
doc/README Normal file
View File

@ -0,0 +1,29 @@
Generate libwebp Container Spec Docs from Text Source
=====================================================
HTML generation requires kramdown [1], easily installed as a
rubygem [2]. Rubygems installation should satisfy dependencies
automatically.
[1]: http://kramdown.rubyforge.org/
[2]: http://rubygems.org/
HTML generation can then be done from the project root:
$ kramdown doc/webp-container-spec.txt --template doc/template.html > \
doc/output/webp-container-spec.html
kramdown can optionally syntax highlight code blocks, using CodeRay [3],
a dependency of kramdown that rubygems will install automatically. The
following will apply inline CSS styling; an external stylesheet is not
needed.
$ kramdown doc/webp-lossless-bitstream-spec.txt --template \
doc/template.html --coderay-css style --coderay-line-numbers ' ' \
--coderay-default-lang c > \
doc/output/webp-lossless-bitstream-spec.html
Optimally, use kramdown 0.13.7 or newer if syntax highlighting desired.
[3]: http://coderay.rubychan.de/

13
doc/TODO Normal file
View File

@ -0,0 +1,13 @@
<louquillio@google.com>, 20111004
* Determine that normative RFC 2119 terms (MUST, SHOULD, MAY, etc.) are
truly intended in all cases where capitalized.
* Several passages could be made clearer.
* Overall edit for scope. Portions are phrased as an introduction to
the 0.1.3 RIFF container additions, rather than a holistic guide to
WebP.
* To wit, suggest s/[spec|specification]/guide/g . "Spec" can imply a
standards track; in any case it's too formal for a work in progress.

94
doc/template.html Normal file
View File

@ -0,0 +1,94 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>WebP Container Specification</title>
<meta name="generator" content="kramdown <%= ::Kramdown::VERSION %>" />
<style type="text/css">
body {
color: #000;
background-color: #fff;
margin: 10%;
font-family: "Liberation Sans", "DejaVu Sans", "Bitstream Vera Sans", Arial, sans-serif;
line-height: 1.4;
}
h2 {
border-bottom: 1px solid #ccc;
padding-bottom: 0;
}
table {
border-collapse: collapse;
}
th, td {
border: 1px solid #999;
padding: .5em .7em;;
}
th {
color: #fff;
background-color: #000;
}
td {
}
hr {
}
code {
color: #000;
background-color: #f7f7f7;
padding: 0 3px;
font-family: "Liberation Mono", "DejaVu Sans Mono", "Bitstream Vera Sans Mono", Consolata, monospace;
}
pre {
background-color: #f7f7f7;
padding: 1em;
border: 1px solid #ccc;
width: 42em;
overflow: auto;
font-family: "Liberation Mono", "DejaVu Sans Mono", "Bitstream Vera Sans Mono", Consolata, monospace;
}
pre code {
background-color: #f7f7f7;
padding: 0; /* Only want padding on inline code, not blocks */
}
pre.terminal {
color: #fff;
background-color: #000;
border: 1px solid #ccc;
max-height: 30em;
}
pre.terminal code {
color: #fff;
background-color: #000;
font-size: smaller;
}
#markdown-toc ul {
list-style-type: disc;
}
ul#markdown-toc {
margin-top: -1em;
visibility: hidden;
-webkit-padding-start: 0;
}
ul#markdown-toc ul {
visibility: visible;
}
ul#markdown-toc ul ul{
visibility: visible;
}
ul#markdown-toc + hr {
margin-bottom: 4em;
}
ol ol { /* Format nested ordered lists */
list-style-type: lower-alpha;
}
dt {
font-style: italic;
font-weight: bold;
}
.caption {
}
</style>
</head>
<body>
<%= @body %>
</body>
</html>

909
doc/webp-container-spec.txt Normal file
View File

@ -0,0 +1,909 @@
<!--
Although you may be viewing an alternate representation, this document
is sourced in Markdown, a light-duty markup scheme, and is optimized for
the [kramdown](http://kramdown.rubyforge.org/) transformer.
See the accompanying README. External link targets are referenced at the
end of this file.
-->
WebP Container Specification
============================
* TOC placeholder
{:toc}
Introduction
------------
WebP is an image format that uses either (i) the VP8 key frame encoding
to compress image data in a lossy way, or (ii) the WebP lossless encoding
(and possibly other encodings in the future). These encoding schemes should
make it more efficient than currently used formats. It is optimized for fast
image transfer over the network (e.g., for websites). The WebP format has
feature parity (color profile, metadata, animation etc) with other formats as
well. This document describes the structure of a WebP file.
The WebP container (i.e., RIFF container for WebP) allows feature support over
and above the basic use case of WebP (i.e., a file containing a single image
encoded as a VP8 key frame). The WebP container provides additional support
for:
* **Lossless compression.** An image can be losslessly compressed, using the
WebP Lossless Format.
* **Metadata.** An image may have metadata stored in EXIF or XMP formats.
* **Transparency.** An image may have transparency, i.e., an alpha channel.
* **Color Profile.** An image may have an embedded ICC profile as described
by the [International Color Consortium][iccspec].
* **Animation.** An image may have multiple frames with pauses between them,
making it an animation.
* **Image Fragmentation.** A single bitstream in WebP has an inherent
limitation for width or height of 2^14 pixels, and, when using VP8, a 512
KiB limit on the size of the first compressed partition. To support larger
images, the format supports images that are composed of multiple fragments,
each encoded as a separate bitstream. All fragments logically form a single
image: they have common metadata, color profile, etc. Image fragmentation
may also improve efficiency for larger images, e.g., grass can be encoded
differently than sky.
The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT",
"SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this
document are to be interpreted as described in [RFC 2119][].
**Note:** Out of the features mentioned above, lossy compression, lossless
compression, transparency, metadata, color profile and animation are finalized
and are to be considered stable. On the other hand, image fragmentation is
experimental as of now, and is open to discussion, feedback and comments.
The same is indicated using annotation "_status: experimental_" in the relevant
sections of this document.
Terminology &amp; Basics
------------------------
A WebP file contains either a still image (i.e., an encoded matrix of pixels)
or an [animation](#animation). Optionally, it can also contain transparency
information, color profile and metadata. In case we need to refer only to the
matrix of pixels, we will call it the _canvas_ of the image.
Below are additional terms used throughout this document:
_Reader/Writer_
: Code that reads WebP files is referred to as a _reader_, while code that
writes them is referred to as a _writer_.
_uint16_
: A 16-bit, little-endian, unsigned integer.
_uint24_
: A 24-bit, little-endian, unsigned integer.
_uint32_
: A 32-bit, little-endian, unsigned integer.
_FourCC_
: A _FourCC_ (four-character code) is a _uint32_ created by concatenating four
ASCII characters in little-endian order.
_1-based_
: An unsigned integer field storing values offset by `-1`. e.g., Such a field
would store value _25_ as _24_.
RIFF file format
----------------
The WebP file format is based on the RIFF (resource interchange file format)
document format.
The basic element of a RIFF file is a _chunk_. It consists of:
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Chunk FourCC |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Chunk Size |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Chunk Payload |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Chunk FourCC: 32 bits
: ASCII four-character code used for chunk identification.
Chunk Size: 32 bits (_uint32_)
: The size of the chunk not including this field, the chunk identifier or
padding.
Chunk Payload: _Chunk Size_ bytes
: The data payload. If _Chunk Size_ is odd, a single padding byte -- that
SHOULD be `0` -- is added.
_ChunkHeader('ABCD')_
: This is used to describe the _FourCC_ and _Chunk Size_ header of individual
chunks, where 'ABCD' is the FourCC for the chunk. This element's
size is 8 bytes.
**Note:** RIFF has a convention that all-uppercase chunk FourCCs are standard
chunks that apply to any RIFF file format, while FourCCs specific to a file
format are all lowercase. WebP does not follow this convention.
WebP file header
----------------
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| 'R' | 'I' | 'F' | 'F' |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| File Size |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| 'W' | 'E' | 'B' | 'P' |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
'RIFF': 32 bits
: The ASCII characters 'R' 'I' 'F' 'F'.
File Size: 32 bits (_uint32_)
: The size of the file in bytes starting at offset 8. The maximum value of
this field is 2^32 minus 10 bytes and thus the size of the whole file is at
most 4GiB minus 2 bytes.
'WEBP': 32 bits
: The ASCII characters 'W' 'E' 'B' 'P'.
A WebP file MUST begin with a RIFF header with the FourCC 'WEBP'. The file size
in the header is the total size of the chunks that follow plus `4` bytes for
the 'WEBP' FourCC. The file SHOULD NOT contain anything after it. As the size
of any chunk is even, the size given by the RIFF header is also even. The
contents of individual chunks will be described in the following sections.
Simple file format (lossy)
--------------------------
This layout SHOULD be used if the image requires _lossy_ encoding and does not
require transparency or other advanced features provided by the extended format.
Files with this layout are smaller and supported by older software.
Simple WebP (lossy) file format:
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| WebP file header (12 bytes) |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| VP8 chunk |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
VP8 chunk:
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| ChunkHeader('VP8 ') |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| VP8 data |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
VP8 data: _Chunk Size_ bytes
: VP8 bitstream data.
The VP8 bitstream format specification can be found at [VP8 Data Format and
Decoding Guide][vp8spec]. Note that the VP8 frame header contains the VP8 frame
width and height. That is assumed to be the width and height of the canvas.
The VP8 specification describes how to decode the image into Y'CbCr
format. To convert to RGB, Rec. 601 SHOULD be used.
Simple file format (lossless)
-----------------------------
**Note:** Older readers may not support files using the lossless format.
This layout SHOULD be used if the image requires _lossless_ encoding (with an
optional transparency channel) and does not require advanced features provided
by the extended format.
Simple WebP (lossless) file format:
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| WebP file header (12 bytes) |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| VP8L chunk |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
VP8L chunk:
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| ChunkHeader('VP8L') |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| VP8L data |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
VP8L data: _Chunk Size_ bytes
: VP8L bitstream data.
The current specification of the VP8L bitstream can be found at
[WebP Lossless Bitstream Format][webpllspec]. Note that the VP8L header
contains the VP8L image width and height. That is assumed to be the width
and height of the canvas.
Extended file format
--------------------
**Note:** Older readers may not support files using the extended format.
An extended format file consists of:
* A 'VP8X' chunk with information about features used in the file.
* An optional 'ICCP' chunk with color profile.
* An optional 'ANIM' chunk with animation control data.
* Image data.
* An optional 'EXIF' chunk with EXIF metadata.
* An optional 'XMP ' chunk with XMP metadata.
* An optional list of [unknown chunks](#unknown-chunks). _\[status: experimental\]_
For a _still image_, the _image data_ consists of a single frame, whereas for
an _animated image_, it consists of multiple frames. More details about frames
can be found in the [Animation](#animation) section.
Moreover, each frame can be fragmented or non-fragmented, as will be described
in the [Extended WebP file header](#extended_header) section. More details about
fragments can be found in the [Fragments](#fragments) section.
All chunks SHOULD be placed in the same order as listed above. If a chunk
appears in the wrong place, the file is invalid, but readers MAY parse the
file, ignoring the chunks that come too late.
**Rationale:** Setting the order of chunks should allow quicker file
parsing. For example, if an 'ALPH' chunk does not appear in its required
position, a decoder can choose to stop searching for it. The rule of
ignoring late chunks should make programs that need to do a full search
give the same results as the ones stopping early.
Extended WebP file header:
{:#extended_header}
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| WebP file header (12 bytes) |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| ChunkHeader('VP8X') |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|Rsv|I|L|E|X|A|F| Reserved |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Canvas Width Minus One | ...
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
... Canvas Height Minus One |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Reserved (Rsv): 2 bits
: SHOULD be `0`.
ICC profile (I): 1 bit
: Set if the file contains an ICC profile.
Alpha (L): 1 bit
: Set if any of the frames of the image contain transparency information
("alpha").
EXIF metadata (E): 1 bit
: Set if the file contains EXIF metadata.
XMP metadata (X): 1 bit
: Set if the file contains XMP metadata.
Animation (A): 1 bit
: Set if this is an animated image. Data in 'ANIM' and 'ANMF' chunks should be
used to control the animation.
Image Fragmentation (F): 1 bit _\[status: experimental\]_
: Set if any of the frames in the image are represented by fragments.
Reserved: 24 bits
: SHOULD be `0`.
Canvas Width Minus One: 24 bits
: _1-based_ width of the canvas in pixels.
The actual canvas width is '1 + Canvas Width Minus One'
Canvas Height Minus One: 24 bits
: _1-based_ height of the canvas in pixels.
The actual canvas height is '1 + Canvas Height Minus One'
The product of _Canvas Width_ and _Canvas Height_ MUST be at most `2^32 - 1`.
Future specifications MAY add more fields.
### Chunks
#### Animation
An animation is controlled by ANIM and ANMF chunks.
ANIM Chunk:
{:#anim_chunk}
For an animated image, this chunk contains the _global parameters_ of the
animation.
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| ChunkHeader('ANIM') |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Background Color |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Loop Count |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Background Color: 32 bits (_uint32_)
: The default background color of the canvas in \[Blue, Green, Red, Alpha\]
byte order. This color MAY be used to fill the unused space on the canvas around
the frames, as well as the transparent pixels of the first frame. Background
color is also used when disposal method is `1`.
**Note**:
* Background color MAY contain a transparency value (alpha), even if the
_Alpha_ flag in [VP8X chunk](#extended_header) is unset.
* Viewer applications SHOULD treat the background color value as a hint, and
are not required to use it.
Loop Count: 16 bits (_uint16_)
: The number of times to loop the animation. `0` means infinitely.
This chunk MUST appear if the _Animation_ flag in the VP8X chunk is set.
If the _Animation_ flag is not set and this chunk is present, it
SHOULD be ignored.
ANMF chunk:
For animated images, this chunk contains information about a _single_ frame.
If the _Animation flag_ is not set, then this chunk SHOULD NOT be present.
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| ChunkHeader('ANMF') |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Frame X | ...
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
... Frame Y | Frame Width Minus One ...
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
... | Frame Height Minus One |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Frame Duration | Reserved |B|D|
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Frame Data |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Frame X: 24 bits (_uint24_)
: The X coordinate of the upper left corner of the frame is `Frame X * 2`
Frame Y: 24 bits (_uint24_)
: The Y coordinate of the upper left corner of the frame is `Frame Y * 2`
Frame Width Minus One: 24 bits (_uint24_)
: The _1-based_ width of the frame.
The frame width is `1 + Frame Width Minus One`
Frame Height Minus One: 24 bits (_uint24_)
: The _1-based_ height of the frame.
The frame height is `1 + Frame Height Minus One`
Frame Duration: 24 bits (_uint24_)
: The time to wait before displaying the next frame, in 1 millisecond units.
In particular, frame duration of 0 is useful when one wants to update multiple
areas of the canvas at once during the animation.
Reserved: 6 bits
: SHOULD be 0.
Blending method (B): 1 bit
: Indicates how transparent pixels of _the current frame_ are to be blended with
corresponding pixels of the previous canvas:
* `0`: Use alpha blending. After disposing of the previous frame, render the
current frame on the canvas using [alpha-blending](#alpha-blending). If the
current frame does not have an alpha channel, assume alpha value of 255,
effectively replacing the rectangle.
* `1`: Do not blend. After disposing of the previous frame, render the
current frame on the canvas by overwriting the rectangle covered by the
current frame.
Disposal method (D): 1 bit
: Indicates how _the current frame_ is to be treated after it has been displayed
(before rendering the next frame) on the canvas:
* `0`: Do not dispose. Leave the canvas as is.
* `1`: Dispose to background color. Fill the _rectangle_ on the canvas covered
by the _current frame_ with background color specified in the
[ANIM chunk](#anim_chunk).
**Notes**:
* The frame disposal only applies to the _frame rectangle_, that is, the
rectangle defined by _Frame X_, _Frame Y_, _frame width_ and _frame height_.
It may or may not cover the whole canvas.
{:#alpha-blending}
* **Alpha-blending**:
Given that each of the R, G, B and A channels is 8-bit, and the RGB
channels are _not premultiplied_ by alpha, the formula for blending
'dst' onto 'src' is:
~~~~~
blend.A = src.A + dst.A * (1 - src.A / 255)
if blend.A = 0 then
blend.RGB = 0
else
blend.RGB = (src.RGB * src.A +
dst.RGB * dst.A * (1 - src.A / 255)) / blend.A
~~~~~
* Alpha-blending SHOULD be done in linear color space, by taking into account
the [color profile](#color-profile) of the image. If the color profile is
not present, sRGB is to be assumed. (Note that sRGB also needs to be
linearized due to a gamma of ~2.2).
Frame Data: _Chunk Size_ - `16` bytes
: For a fragmented frame, it consists of multiple [fragment chunks](#fragments).
: For a non-fragmented frame, it consists of:
* An optional [alpha subchunk](#alpha) for the frame.
* A [bitstream subchunk](#bitstream-vp8vp8l) for the frame.
* An optional list of [unknown chunks](#unknown-chunks).
**Note**: The 'ANMF' payload, _Frame Data_ above, consists of individual
_padded_ chunks as described by the [RIFF file format](#riff-file-format).
#### Fragments _\[status: experimental\]_
For images that are represented by fragments, this chunk contains data for
a single fragment. If the _Image Fragmentation Flag_ is not set, then this chunk
SHOULD NOT be present.
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| ChunkHeader('FRGM') |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Fragment X | ...
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
... Fragment Y | Fragment Data |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Fragment X: 24 bits (_uint24_)
: The X coordinate of the upper left corner of the fragment is `Fragment X * 2`
Fragment Y: 24 bits (_uint24_)
: The Y coordinate of the upper left corner of the fragment is `Fragment Y * 2`
Fragment Data: _Chunk Size_ - `6` bytes
: It contains:
* An optional [alpha subchunk](#alpha) for the fragment.
* The [bitstream subchunk](#bitstream-vp8vp8l) for the fragment.
* An optional list of [unknown chunks](#unknown-chunks).
Note: The width and height of the fragment is obtained from the bitstream
subchunk.
The fragments of a frame SHOULD have the following properties:
* They collectively cover the whole frame.
* No pair of fragments have any overlapping region on the frame.
* No portion of any fragment should be located outside of the canvas.
#### Alpha
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| ChunkHeader('ALPH') |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|Rsv| P | F | C | Alpha Bitstream... |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Reserved (Rsv): 2 bits
: SHOULD be `0`.
Pre-processing (P): 2 bits
: These INFORMATIVE bits are used to signal the pre-processing that has
been performed during compression. The decoder can use this information to
e.g. dither the values or smooth the gradients prior to display.
* `0`: no pre-processing
* `1`: level reduction
Filtering method (F): 2 bits
: The filtering method used:
* `0`: None.
* `1`: Horizontal filter.
* `2`: Vertical filter.
* `3`: Gradient filter.
For each pixel, filtering is performed using the following calculations.
Assume the alpha values surrounding the current `X` position are labeled as:
C | B |
---+---+
A | X |
We seek to compute the alpha value at position `X`. First, a prediction is
made depending on the filtering method:
* Method `0`: predictor = 0
* Method `1`: predictor = A
* Method `2`: predictor = B
* Method `3`: predictor = clip(A + B - C)
where `clip(v)` is equal to:
* 0 if v < 0
* 255 if v > 255
* v otherwise
The final value is derived by adding the decompressed value `X` to the
predictor and using modulo-256 arithmetic to wrap the \[256-511\] range
into the \[0-255\] one:
`alpha = (predictor + X) % 256`
There are special cases for left-most and top-most pixel positions:
* Top-left value at location (0,0) uses 0 as predictor value. Otherwise,
* For horizontal or gradient filtering methods, the left-most pixels at
location (0, y) are predicted using the location (0, y-1) just above.
* For vertical or gradient filtering methods, the top-most pixels at
location (x, 0) are predicted using the location (x-1, 0) on the left.
Decoders are not required to use this information in any specified way.
Compression method (C): 2 bits
: The compression method used:
* `0`: No compression.
* `1`: Compressed using the WebP lossless format.
Alpha bitstream: _Chunk Size_ - `1` bytes
: Encoded alpha bitstream.
This optional chunk contains encoded alpha data for this frame/fragment. A
frame/fragment containing a 'VP8L' chunk SHOULD NOT contain this chunk.
**Rationale**: The transparency information is already part of the 'VP8L'
chunk.
The alpha channel data is stored as uncompressed raw data (when
compression method is '0') or compressed using the lossless format
(when the compression method is '1').
* Raw data: consists of a byte sequence of length width * height,
containing all the 8-bit transparency values in scan order.
* Lossless format compression: the byte sequence is a compressed
image-stream (as described in the [WebP Lossless Bitstream Format]
[webpllspec]) of implicit dimension width x height. That is, this
image-stream does NOT contain any headers describing the image dimension.
**Rationale**: the dimension is already known from other sources,
so storing it again would be redundant and error-prone.
Once the image-stream is decoded into ARGB color values, following
the process described in the lossless format specification, the
transparency information must be extracted from the *green* channel
of the ARGB quadruplet.
**Rationale**: the green channel is allowed extra transformation
steps in the specification -- unlike the other channels -- that can
improve compression.
#### Bitstream (VP8/VP8L)
This chunk contains compressed bitstream data for a single frame/fragment.
A bitstream chunk may be either (i) a VP8 chunk, using "VP8 " (note the
significant fourth-character space) as its tag _or_ (ii) a VP8L chunk, using
"VP8L" as its tag.
The formats of VP8 and VP8L chunks are as described in sections
[Simple file format (lossy)](#simple-file-format-lossy)
and [Simple file format (lossless)](#simple-file-format-lossless) respectively.
#### Color profile
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| ChunkHeader('ICCP') |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Color Profile |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Color Profile: _Chunk Size_ bytes
: ICC profile.
This chunk MUST appear before the image data.
There SHOULD be at most one such chunk. If there are more such chunks, readers
MAY ignore all except the first one.
See the [ICC Specification][iccspec] for details.
If this chunk is not present, sRGB SHOULD be assumed.
#### Metadata
Metadata can be stored in 'EXIF' or 'XMP ' chunks.
There SHOULD be at most one chunk of each type ('EXIF' and 'XMP '). If there
are more such chunks, readers MAY ignore all except the first one. Also, a file
may possibly contain both 'EXIF' and 'XMP ' chunks.
The chunks are defined as follows:
EXIF chunk:
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| ChunkHeader('EXIF') |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| EXIF Metadata |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
EXIF Metadata: _Chunk Size_ bytes
: image metadata in EXIF format.
XMP chunk:
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| ChunkHeader('XMP ') |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| XMP Metadata |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
XMP Metadata: _Chunk Size_ bytes
: image metadata in XMP format.
Additional guidance about handling metadata can be found in the
Metadata Working Group's [Guidelines for Handling Metadata][metadata].
#### Unknown Chunks _\[status: experimental\]_
A RIFF chunk (described in [this](#terminology-amp-basics) section) whose _chunk
tag_ is different from any of the chunks described in this document, is
considered an _unknown chunk_.
**Rationale**: Allowing unknown chunks gives a provision for future extension
of the format, and also allows storage of any application-specific data.
A file MAY contain unknown chunks:
* At the end of the file as described in [Extended WebP file
header](#extended_header) section.
* At the end of FRGM and ANMF chunks as described in [Fragments](#fragments)
and [Animation](#animation) sections.
Readers SHOULD ignore these chunks. Writers SHOULD preserve them in their
original order (unless they specifically intend to modify these chunks).
### Assembling the Canvas from fragments/frames
Here we provide an overview of how a reader should assemble a canvas in case
of a fragmented-image and in case of an animated image. The notation
_VP8X.field_ means the field in the 'VP8X' chunk with the same description.
Displaying a _fragmented image_ canvas MUST be equivalent to the following
pseudocode: _\[status: experimental\]_
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
assert VP8X.flags.hasFragments
canvas ← new black image of size VP8X.canvasWidth x VP8X.canvasHeight.
frgm_params ← nil
for chunk in image_data:
assert chunk.tag is "FRGM"
frgm_params.fragmentX = Fragment X
frgm_params.fragmentY = Fragment Y
for subchunk in 'Fragment Data':
if subchunk.tag == "ALPH":
assert alpha subchunks not found in 'Fragment Data' earlier
frgm_params.alpha = alpha_data
else if subchunk.tag == "VP8 " OR subchunk.tag == "VP8L":
assert bitstream subchunks not found in 'Fragment Data' earlier
frgm_params.bitstream = bitstream_data
frgm_params.fragmentWidth = Width extracted from bitstream subchunk
frgm_params.fragmentHeight = Height extracted from bitstream subchunk
assert VP8X.canvasWidth >=
frgm_params.fragmentX + frgm_params.fragmentWidth
assert VP8X.canvasHeight >=
frgm_params.fragmentY + frgm_params.fragmentHeight
assert fragment has the properties mentioned in "Image Fragments" section.
render fragment with frame_params.alpha and frame_params.bitstream on canvas
with top-left corner in (frgm_params.fragmentX, frgm_params.fragmentY).
canvas contains the decoded canvas.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Displaying an _animated image_ canvas MUST be equivalent to the following
pseudocode:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
assert VP8X.flags.hasAnimation
canvas ← new image of size VP8X.canvasWidth x VP8X.canvasHeight with
background color ANIM.background_color.
loop_count ← ANIM.loopCount
dispose_method ← ANIM.disposeMethod
if loop_count == 0:
loop_count = ∞
frame_params ← nil
for loop = 0, ..., loop_count - 1
assert next chunk in image_data is ANMF
frame_params.frameX = Frame X
frame_params.frameY = Frame Y
frame_params.frameWidth = Frame Width Minus One + 1
frame_params.frameHeight = Frame Height Minus One + 1
frame_params.frameDuration = Frame Duration
assert VP8X.canvasWidth >= frame_params.frameX + frame_params.frameWidth
assert VP8X.canvasHeight >= frame_params.frameY + frame_params.frameHeight
if VP8X.flags.hasFragments and first subchunk in 'Frame Data' is FRGM
// Fragmented frame.
frame_params.{bitstream,alpha} = canvas decoded from subchunks in
'Frame Data' as per the pseudocode for
_fragmented image_ above.
else
// Non-fragmented frame.
for subchunk in 'Frame Data':
if subchunk.tag == "ALPH":
assert alpha subchunks not found in 'Frame Data' earlier
frame_params.alpha = alpha_data
else if subchunk.tag == "VP8 " OR subchunk.tag == "VP8L":
assert bitstream subchunks not found in 'Frame Data' earlier
frame_params.bitstream = bitstream_data
render frame with frame_params.alpha and frame_params.bitstream on canvas
with top-left corner in (frame_params.frameX, frame_params.frameY), using
dispose method dispose_method.
Show the contents of the image for frame_params.frameDuration * 1ms.
canvas contains the decoded canvas.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Example file layouts
--------------------
A lossy encoded image with alpha may look as follows:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
RIFF/WEBP
+- VP8X (descriptions of features used)
+- ALPH (alpha bitstream)
+- VP8 (bitstream)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
A losslessly encoded image may look as follows:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
RIFF/WEBP
+- VP8X (descriptions of features used)
+- XYZW (unknown chunk)
+- VP8L (lossless bitstream)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
A lossless image with ICC profile and XMP metadata may
look as follows:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
RIFF/WEBP
+- VP8X (descriptions of features used)
+- ICCP (color profile)
+- VP8L (lossless bitstream)
+- XMP (metadata)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
A fragmented image may look as follows:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
RIFF/WEBP
+- VP8X (descriptions of features used)
+- FRGM (fragment1 parameters + data)
+- FRGM (fragment2 parameters + data)
+- FRGM (fragment3 parameters + data)
+- FRGM (fragment4 parameters + data)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
An animated image with EXIF metadata may look as follows:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
RIFF/WEBP
+- VP8X (descriptions of features used)
+- ANIM (global animation parameters)
+- ANMF (frame1 parameters + data)
+- ANMF (frame2 parameters + data)
+- ANMF (frame3 parameters + data)
+- ANMF (frame4 parameters + data)
+- EXIF (metadata)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
[vp8spec]: http://tools.ietf.org/html/rfc6386
[webpllspec]: https://gerrit.chromium.org/gerrit/gitweb?p=webm/libwebp.git;a=blob;f=doc/webp-lossless-bitstream-spec.txt;hb=master
[iccspec]: http://www.color.org/icc_specs2.xalter
[metadata]: http://www.metadataworkinggroup.org/pdf/mwg_guidance.pdf
[rfc 2119]: http://tools.ietf.org/html/rfc2119

File diff suppressed because it is too large Load Diff

46
examples/Android.mk Normal file
View File

@ -0,0 +1,46 @@
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_SRC_FILES := \
example_util.c \
LOCAL_CFLAGS := $(WEBP_CFLAGS)
LOCAL_C_INCLUDES := $(LOCAL_PATH)/../src
LOCAL_MODULE := example_util
include $(BUILD_STATIC_LIBRARY)
include $(CLEAR_VARS)
# Note: to enable jpeg/png encoding the sources from AOSP can be used with
# minor modification to their Android.mk files.
LOCAL_SRC_FILES := \
cwebp.c \
jpegdec.c \
metadata.c \
pngdec.c \
tiffdec.c \
webpdec.c \
LOCAL_CFLAGS := $(WEBP_CFLAGS)
LOCAL_C_INCLUDES := $(LOCAL_PATH)/../src
LOCAL_STATIC_LIBRARIES := example_util webp
LOCAL_MODULE := cwebp
include $(BUILD_EXECUTABLE)
include $(CLEAR_VARS)
LOCAL_SRC_FILES := \
dwebp.c \
LOCAL_CFLAGS := $(WEBP_CFLAGS)
LOCAL_C_INCLUDES := $(LOCAL_PATH)/../src
LOCAL_STATIC_LIBRARIES := example_util webp
LOCAL_MODULE := dwebp
include $(BUILD_EXECUTABLE)

View File

@ -1,11 +1,54 @@
AM_CPPFLAGS = -I$(top_srcdir)/src
AM_CPPFLAGS = -I$(top_builddir)/src -I$(top_srcdir)/src
bin_PROGRAMS = dwebp cwebp
if BUILD_VWEBP
bin_PROGRAMS += vwebp
endif
if WANT_MUX
bin_PROGRAMS += webpmux
endif
if BUILD_GIF2WEBP
bin_PROGRAMS += gif2webp
endif
noinst_LTLIBRARIES = libexampleutil.la
libexampleutil_la_SOURCES = example_util.c example_util.h stopwatch.h
dwebp_SOURCES = dwebp.c stopwatch.h
dwebp_CPPFLAGS = $(AM_CPPFLAGS) $(PNG_INCLUDES) $(JPEG_INCLUDES)
dwebp_LDADD = ../src/libwebp.la $(PNG_LIBS) $(JPEG_LIBS)
dwebp_CPPFLAGS = $(AM_CPPFLAGS) $(USE_EXPERIMENTAL_CODE)
dwebp_CPPFLAGS += $(JPEG_INCLUDES) $(PNG_INCLUDES)
dwebp_LDADD = libexampleutil.la $(PNG_LIBS) $(JPEG_LIBS)
cwebp_SOURCES = cwebp.c stopwatch.h
cwebp_CPPFLAGS = $(AM_CPPFLAGS) $(PNG_INCLUDES) $(JPEG_INCLUDES)
cwebp_LDADD = ../src/libwebp.la $(PNG_LIBS) $(JPEG_LIBS)
cwebp_SOURCES = cwebp.c metadata.c metadata.h stopwatch.h
cwebp_SOURCES += jpegdec.c jpegdec.h
cwebp_SOURCES += pngdec.c pngdec.h
cwebp_SOURCES += tiffdec.c tiffdec.h
cwebp_SOURCES += webpdec.c webpdec.h
cwebp_SOURCES += wicdec.c wicdec.h
cwebp_CPPFLAGS = $(AM_CPPFLAGS) $(USE_EXPERIMENTAL_CODE)
cwebp_CPPFLAGS += $(JPEG_INCLUDES) $(PNG_INCLUDES) $(TIFF_INCLUDES)
cwebp_LDADD = libexampleutil.la ../src/libwebp.la
cwebp_LDADD += $(JPEG_LIBS) $(PNG_LIBS) $(TIFF_LIBS)
gif2webp_SOURCES = gif2webp.c gif2webp_util.c
gif2webp_CPPFLAGS = $(AM_CPPFLAGS) $(USE_EXPERIMENTAL_CODE) $(GIF_INCLUDES)
gif2webp_LDADD = libexampleutil.la ../src/mux/libwebpmux.la ../src/libwebp.la
gif2webp_LDADD += $(GIF_LIBS)
webpmux_SOURCES = webpmux.c
webpmux_CPPFLAGS = $(AM_CPPFLAGS) $(USE_EXPERIMENTAL_CODE)
webpmux_LDADD = libexampleutil.la ../src/mux/libwebpmux.la ../src/libwebp.la
vwebp_SOURCES = vwebp.c
vwebp_CPPFLAGS = $(AM_CPPFLAGS) $(USE_EXPERIMENTAL_CODE) $(GL_INCLUDES)
vwebp_LDADD = libexampleutil.la ../src/demux/libwebpdemux.la $(GL_LIBS)
if BUILD_LIBWEBPDECODER
dwebp_LDADD += ../src/libwebpdecoder.la
vwebp_LDADD += ../src/libwebpdecoder.la
else
dwebp_LDADD += ../src/libwebp.la
vwebp_LDADD += ../src/libwebp.la
endif

File diff suppressed because it is too large Load Diff

View File

@ -1,14 +1,13 @@
// Copyright 2010 Google Inc.
// Copyright 2010 Google Inc. All Rights Reserved.
//
// This code is licensed under the same terms as WebM:
// Software License Agreement: http://www.webmproject.org/license/software/
// Additional IP Rights Grant: http://www.webmproject.org/license/additional/
// 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.
// -----------------------------------------------------------------------------
//
// simple command-line example calling libwebpdecode to
// decode a WebP image into a PPM image.
//
// Compile with: gcc -o dwebp dwebp.c -lwebpdecode
// Command-line tool for decoding a WebP image.
//
// Author: Skal (pascal.massimino@gmail.com)
@ -17,41 +16,67 @@
#include <stdlib.h>
#include <string.h>
#ifdef HAVE_CONFIG_H
#include "webp/config.h"
#endif
#ifdef WEBP_HAVE_PNG
#include <png.h>
#endif
#ifdef _WIN32
#ifdef HAVE_WINCODEC_H
#ifdef __MINGW32__
#define INITGUID // Without this GUIDs are declared extern and fail to link
#endif
#define CINTERFACE
#define COBJMACROS
#define _WIN32_IE 0x500 // Workaround bug in shlwapi.h when compiling C++
// code with COBJMACROS.
#include <ole2.h> // CreateStreamOnHGlobal()
#include <shlwapi.h>
#include <windows.h>
#include <wincodec.h>
#endif
#include "webp/decode.h"
#include "stopwatch.h"
#include "./example_util.h"
#include "./stopwatch.h"
#if defined(__cplusplus) || defined(c_plusplus)
static int verbose = 0;
#ifndef WEBP_DLL
#ifdef __cplusplus
extern "C" {
#endif
//-----------------------------------------------------------------------------
extern void* VP8GetCPUInfo; // opaque forward declaration.
static int verbose = 0;
#ifdef __cplusplus
} // extern "C"
#endif
#endif // WEBP_DLL
#ifdef _WIN32
//------------------------------------------------------------------------------
#define IFS(fn) \
do { \
if (SUCCEEDED(hr)) \
{ \
hr = (fn); \
if (FAILED(hr) && verbose) \
printf(#fn " failed %08x\n", hr); \
} \
// Output types
typedef enum {
PNG = 0,
PAM,
PPM,
PGM,
BMP,
TIFF,
YUV,
ALPHA_PLANE_ONLY // this is for experimenting only
} OutputFileFormat;
#ifdef HAVE_WINCODEC_H
#define IFS(fn) \
do { \
if (SUCCEEDED(hr)) { \
hr = (fn); \
if (FAILED(hr)) fprintf(stderr, #fn " failed %08lx\n", hr); \
} \
} while (0)
#ifdef __cplusplus
@ -60,75 +85,119 @@ static int verbose = 0;
#define MAKE_REFGUID(x) &(x)
#endif
static HRESULT CreateOutputStream(const char* out_file_name, IStream** ppStream) {
static HRESULT CreateOutputStream(const char* out_file_name,
int write_to_mem, IStream** stream) {
HRESULT hr = S_OK;
IFS(SHCreateStreamOnFileA(out_file_name, STGM_WRITE | STGM_CREATE, ppStream));
if (FAILED(hr))
printf("Error opening output file %s (%08x)\n", out_file_name, hr);
if (write_to_mem) {
// Output to a memory buffer. This is freed when 'stream' is released.
IFS(CreateStreamOnHGlobal(NULL, TRUE, stream));
} else {
IFS(SHCreateStreamOnFileA(out_file_name, STGM_WRITE | STGM_CREATE, stream));
}
if (FAILED(hr)) {
fprintf(stderr, "Error opening output file %s (%08lx)\n",
out_file_name, hr);
}
return hr;
}
static HRESULT WriteUsingWIC(const char* out_file_name, REFGUID container_guid,
unsigned char* rgb, int stride,
uint32_t width, uint32_t height) {
static HRESULT WriteUsingWIC(const char* out_file_name, int use_stdout,
REFGUID container_guid,
uint8_t* rgb, int stride,
uint32_t width, uint32_t height, int has_alpha) {
HRESULT hr = S_OK;
IWICImagingFactory* pFactory = NULL;
IWICBitmapFrameEncode* pFrame = NULL;
IWICBitmapEncoder* pEncoder = NULL;
IStream* pStream = NULL;
GUID pixel_format = GUID_WICPixelFormat24bppBGR;
IWICImagingFactory* factory = NULL;
IWICBitmapFrameEncode* frame = NULL;
IWICBitmapEncoder* encoder = NULL;
IStream* stream = NULL;
WICPixelFormatGUID pixel_format = has_alpha ? GUID_WICPixelFormat32bppBGRA
: GUID_WICPixelFormat24bppBGR;
IFS(CoInitialize(NULL));
IFS(CoCreateInstance(MAKE_REFGUID(CLSID_WICImagingFactory), NULL,
CLSCTX_INPROC_SERVER, MAKE_REFGUID(IID_IWICImagingFactory),
(LPVOID*)&pFactory));
CLSCTX_INPROC_SERVER,
MAKE_REFGUID(IID_IWICImagingFactory),
(LPVOID*)&factory));
if (hr == REGDB_E_CLASSNOTREG) {
printf("Couldn't access Windows Imaging Component (are you running \n");
printf("Windows XP SP3 or newer?). PNG support not available.\n");
printf("Use -ppm or -pgm for available PPM and PGM formats.\n");
fprintf(stderr,
"Couldn't access Windows Imaging Component (are you running "
"Windows XP SP3 or newer?). PNG support not available. "
"Use -ppm or -pgm for available PPM and PGM formats.\n");
}
IFS(CreateOutputStream(out_file_name, &pStream));
IFS(IWICImagingFactory_CreateEncoder(pFactory, container_guid, NULL,
&pEncoder));
IFS(IWICBitmapEncoder_Initialize(pEncoder, pStream,
IFS(CreateOutputStream(out_file_name, use_stdout, &stream));
IFS(IWICImagingFactory_CreateEncoder(factory, container_guid, NULL,
&encoder));
IFS(IWICBitmapEncoder_Initialize(encoder, stream,
WICBitmapEncoderNoCache));
IFS(IWICBitmapEncoder_CreateNewFrame(pEncoder, &pFrame, NULL));
IFS(IWICBitmapFrameEncode_Initialize(pFrame, NULL));
IFS(IWICBitmapFrameEncode_SetSize(pFrame, width, height));
IFS(IWICBitmapFrameEncode_SetPixelFormat(pFrame, &pixel_format));
IFS(IWICBitmapFrameEncode_WritePixels(pFrame, height, stride,
height * stride, rgb));
IFS(IWICBitmapFrameEncode_Commit(pFrame));
IFS(IWICBitmapEncoder_Commit(pEncoder));
IFS(IWICBitmapEncoder_CreateNewFrame(encoder, &frame, NULL));
IFS(IWICBitmapFrameEncode_Initialize(frame, NULL));
IFS(IWICBitmapFrameEncode_SetSize(frame, width, height));
IFS(IWICBitmapFrameEncode_SetPixelFormat(frame, &pixel_format));
IFS(IWICBitmapFrameEncode_WritePixels(frame, height, stride,
height * stride, rgb));
IFS(IWICBitmapFrameEncode_Commit(frame));
IFS(IWICBitmapEncoder_Commit(encoder));
if (pFrame != NULL) IUnknown_Release(pFrame);
if (pEncoder != NULL) IUnknown_Release(pEncoder);
if (pFactory != NULL) IUnknown_Release(pFactory);
if (pStream != NULL) IUnknown_Release(pStream);
if (SUCCEEDED(hr) && use_stdout) {
HGLOBAL image;
IFS(GetHGlobalFromStream(stream, &image));
if (SUCCEEDED(hr)) {
HANDLE std_output = GetStdHandle(STD_OUTPUT_HANDLE);
DWORD mode;
const BOOL update_mode = GetConsoleMode(std_output, &mode);
const void* const image_mem = GlobalLock(image);
DWORD bytes_written = 0;
// Clear output processing if necessary, then output the image.
if (update_mode) SetConsoleMode(std_output, 0);
if (!WriteFile(std_output, image_mem, (DWORD)GlobalSize(image),
&bytes_written, NULL) ||
bytes_written != GlobalSize(image)) {
hr = E_FAIL;
}
if (update_mode) SetConsoleMode(std_output, mode);
GlobalUnlock(image);
}
}
if (frame != NULL) IUnknown_Release(frame);
if (encoder != NULL) IUnknown_Release(encoder);
if (factory != NULL) IUnknown_Release(factory);
if (stream != NULL) IUnknown_Release(stream);
return hr;
}
static int WritePNG(const char* out_file_name, unsigned char* rgb, int stride,
uint32_t width, uint32_t height) {
return SUCCEEDED(WriteUsingWIC(out_file_name,
MAKE_REFGUID(GUID_ContainerFormatPng), rgb, stride, width,
height));
static int WritePNG(const char* out_file_name, int use_stdout,
const WebPDecBuffer* const buffer) {
const uint32_t width = buffer->width;
const uint32_t height = buffer->height;
uint8_t* const rgb = buffer->u.RGBA.rgba;
const int stride = buffer->u.RGBA.stride;
const int has_alpha = (buffer->colorspace == MODE_BGRA);
return SUCCEEDED(WriteUsingWIC(out_file_name, use_stdout,
MAKE_REFGUID(GUID_ContainerFormatPng),
rgb, stride, width, height, has_alpha));
}
#elif defined(WEBP_HAVE_PNG) // !WIN32
static void PNGAPI error_function(png_structp png, png_const_charp dummy) {
#elif defined(WEBP_HAVE_PNG) // !HAVE_WINCODEC_H
static void PNGAPI PNGErrorFunction(png_structp png, png_const_charp dummy) {
(void)dummy; // remove variable-unused warning
longjmp(png_jmpbuf(png), 1);
}
static int WritePNG(FILE* out_file, unsigned char* rgb, int stride,
png_uint_32 width, png_uint_32 height) {
static int WritePNG(FILE* out_file, const WebPDecBuffer* const buffer) {
const uint32_t width = buffer->width;
const uint32_t height = buffer->height;
uint8_t* const rgb = buffer->u.RGBA.rgba;
const int stride = buffer->u.RGBA.stride;
const int has_alpha = (buffer->colorspace == MODE_RGBA);
png_structp png;
png_infop info;
png_uint_32 y;
png = png_create_write_struct(PNG_LIBPNG_VER_STRING,
NULL, error_function, NULL);
NULL, PNGErrorFunction, NULL);
if (png == NULL) {
return 0;
}
@ -142,7 +211,8 @@ static int WritePNG(FILE* out_file, unsigned char* rgb, int stride,
return 0;
}
png_init_io(png, out_file);
png_set_IHDR(png, info, width, height, 8, PNG_COLOR_TYPE_RGB,
png_set_IHDR(png, info, width, height, 8,
has_alpha ? PNG_COLOR_TYPE_RGBA : PNG_COLOR_TYPE_RGB,
PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT,
PNG_FILTER_TYPE_DEFAULT);
png_write_info(png, info);
@ -154,218 +224,527 @@ static int WritePNG(FILE* out_file, unsigned char* rgb, int stride,
png_destroy_write_struct(&png, &info);
return 1;
}
#else // !WIN32 && !WEBP_HAVE_PNG
typedef uint32_t png_uint_32;
static int WritePNG(FILE* out_file, unsigned char* rgb, int stride,
png_uint_32 width, png_uint_32 height) {
printf("PNG support not compiled. Please install the libpng development "
"package before building.\n");
printf("You can run with -ppm flag to decode in PPM format.\n");
#else // !HAVE_WINCODEC_H && !WEBP_HAVE_PNG
static int WritePNG(FILE* out_file, const WebPDecBuffer* const buffer) {
(void)out_file;
(void)buffer;
fprintf(stderr, "PNG support not compiled. Please install the libpng "
"development package before building.\n");
fprintf(stderr, "You can run with -ppm flag to decode in PPM format.\n");
return 0;
}
#endif
static int WritePPM(FILE* fout, unsigned char* rgb,
uint32_t width, uint32_t height) {
fprintf(fout, "P6\n%d %d\n255\n", width, height);
return (fwrite(rgb, width * height, 3, fout) == 3);
static int WritePPM(FILE* fout, const WebPDecBuffer* const buffer, int alpha) {
const uint32_t width = buffer->width;
const uint32_t height = buffer->height;
const uint8_t* const rgb = buffer->u.RGBA.rgba;
const int stride = buffer->u.RGBA.stride;
const size_t bytes_per_px = alpha ? 4 : 3;
uint32_t y;
if (alpha) {
fprintf(fout, "P7\nWIDTH %d\nHEIGHT %d\nDEPTH 4\nMAXVAL 255\n"
"TUPLTYPE RGB_ALPHA\nENDHDR\n", width, height);
} else {
fprintf(fout, "P6\n%d %d\n255\n", width, height);
}
for (y = 0; y < height; ++y) {
if (fwrite(rgb + y * stride, width, bytes_per_px, fout) != bytes_per_px) {
return 0;
}
}
return 1;
}
static int WritePGM(FILE* fout,
unsigned char* y_plane, unsigned char *u, unsigned char* v,
int y_stride, int uv_stride,
uint32_t width, uint32_t height) {
// Save a grayscale PGM file using the IMC4 layout
// (http://www.fourcc.org/yuv.php#IMC4). This is a very
// convenient format for viewing the samples, esp. for
// odd dimensions.
int ok = 1;
unsigned int y;
const unsigned int uv_width = (width + 1) / 2;
const unsigned int uv_height = (height + 1) / 2;
const unsigned int out_stride = (width + 1) & ~1;
fprintf(fout, "P5\n%d %d\n255\n", out_stride, height + uv_height);
for (y = 0; ok && y < height; ++y) {
ok &= (fwrite(y_plane + y * y_stride, width, 1, fout) == 1);
if (width & 1) fputc(0, fout); // padding byte
static void PutLE16(uint8_t* const dst, uint32_t value) {
dst[0] = (value >> 0) & 0xff;
dst[1] = (value >> 8) & 0xff;
}
static void PutLE32(uint8_t* const dst, uint32_t value) {
PutLE16(dst + 0, (value >> 0) & 0xffff);
PutLE16(dst + 2, (value >> 16) & 0xffff);
}
#define BMP_HEADER_SIZE 54
static int WriteBMP(FILE* fout, const WebPDecBuffer* const buffer) {
const int has_alpha = (buffer->colorspace != MODE_BGR);
const uint32_t width = buffer->width;
const uint32_t height = buffer->height;
const uint8_t* const rgba = buffer->u.RGBA.rgba;
const int stride = buffer->u.RGBA.stride;
const uint32_t bytes_per_px = has_alpha ? 4 : 3;
uint32_t y;
const uint32_t line_size = bytes_per_px * width;
const uint32_t bmp_stride = (line_size + 3) & ~3; // pad to 4
const uint32_t total_size = bmp_stride * height + BMP_HEADER_SIZE;
uint8_t bmp_header[BMP_HEADER_SIZE] = { 0 };
// bitmap file header
PutLE16(bmp_header + 0, 0x4d42); // signature 'BM'
PutLE32(bmp_header + 2, total_size); // size including header
PutLE32(bmp_header + 6, 0); // reserved
PutLE32(bmp_header + 10, BMP_HEADER_SIZE); // offset to pixel array
// bitmap info header
PutLE32(bmp_header + 14, 40); // DIB header size
PutLE32(bmp_header + 18, width); // dimensions
PutLE32(bmp_header + 22, -(int)height); // vertical flip!
PutLE16(bmp_header + 26, 1); // number of planes
PutLE16(bmp_header + 28, bytes_per_px * 8); // bits per pixel
PutLE32(bmp_header + 30, 0); // no compression (BI_RGB)
PutLE32(bmp_header + 34, 0); // image size (dummy)
PutLE32(bmp_header + 38, 2400); // x pixels/meter
PutLE32(bmp_header + 42, 2400); // y pixels/meter
PutLE32(bmp_header + 46, 0); // number of palette colors
PutLE32(bmp_header + 50, 0); // important color count
// TODO(skal): color profile
// write header
if (fwrite(bmp_header, sizeof(bmp_header), 1, fout) != 1) {
return 0;
}
for (y = 0; ok && y < uv_height; ++y) {
ok &= (fwrite(u + y * uv_stride, uv_width, 1, fout) == 1);
ok &= (fwrite(v + y * uv_stride, uv_width, 1, fout) == 1);
// write pixel array
for (y = 0; y < height; ++y) {
if (fwrite(rgba + y * stride, line_size, 1, fout) != 1) {
return 0;
}
// write padding zeroes
if (bmp_stride != line_size) {
const uint8_t zeroes[3] = { 0 };
if (fwrite(zeroes, bmp_stride - line_size, 1, fout) != 1) {
return 0;
}
}
}
return 1;
}
#undef BMP_HEADER_SIZE
#define NUM_IFD_ENTRIES 15
#define EXTRA_DATA_SIZE 16
// 10b for signature/header + n * 12b entries + 4b for IFD terminator:
#define EXTRA_DATA_OFFSET (10 + 12 * NUM_IFD_ENTRIES + 4)
#define TIFF_HEADER_SIZE (EXTRA_DATA_OFFSET + EXTRA_DATA_SIZE)
static int WriteTIFF(FILE* fout, const WebPDecBuffer* const buffer) {
const int has_alpha = (buffer->colorspace != MODE_RGB);
const uint32_t width = buffer->width;
const uint32_t height = buffer->height;
const uint8_t* const rgba = buffer->u.RGBA.rgba;
const int stride = buffer->u.RGBA.stride;
const uint8_t bytes_per_px = has_alpha ? 4 : 3;
// For non-alpha case, we omit tag 0x152 (ExtraSamples).
const uint8_t num_ifd_entries = has_alpha ? NUM_IFD_ENTRIES
: NUM_IFD_ENTRIES - 1;
uint8_t tiff_header[TIFF_HEADER_SIZE] = {
0x49, 0x49, 0x2a, 0x00, // little endian signature
8, 0, 0, 0, // offset to the unique IFD that follows
// IFD (offset = 8). Entries must be written in increasing tag order.
num_ifd_entries, 0, // Number of entries in the IFD (12 bytes each).
0x00, 0x01, 3, 0, 1, 0, 0, 0, 0, 0, 0, 0, // 10: Width (TBD)
0x01, 0x01, 3, 0, 1, 0, 0, 0, 0, 0, 0, 0, // 22: Height (TBD)
0x02, 0x01, 3, 0, bytes_per_px, 0, 0, 0, // 34: BitsPerSample: 8888
EXTRA_DATA_OFFSET + 0, 0, 0, 0,
0x03, 0x01, 3, 0, 1, 0, 0, 0, 1, 0, 0, 0, // 46: Compression: none
0x06, 0x01, 3, 0, 1, 0, 0, 0, 2, 0, 0, 0, // 58: Photometric: RGB
0x11, 0x01, 4, 0, 1, 0, 0, 0, // 70: Strips offset:
TIFF_HEADER_SIZE, 0, 0, 0, // data follows header
0x12, 0x01, 3, 0, 1, 0, 0, 0, 1, 0, 0, 0, // 82: Orientation: topleft
0x15, 0x01, 3, 0, 1, 0, 0, 0, // 94: SamplesPerPixels
bytes_per_px, 0, 0, 0,
0x16, 0x01, 3, 0, 1, 0, 0, 0, 0, 0, 0, 0, // 106: Rows per strip (TBD)
0x17, 0x01, 4, 0, 1, 0, 0, 0, 0, 0, 0, 0, // 118: StripByteCount (TBD)
0x1a, 0x01, 5, 0, 1, 0, 0, 0, // 130: X-resolution
EXTRA_DATA_OFFSET + 8, 0, 0, 0,
0x1b, 0x01, 5, 0, 1, 0, 0, 0, // 142: Y-resolution
EXTRA_DATA_OFFSET + 8, 0, 0, 0,
0x1c, 0x01, 3, 0, 1, 0, 0, 0, 1, 0, 0, 0, // 154: PlanarConfiguration
0x28, 0x01, 3, 0, 1, 0, 0, 0, 2, 0, 0, 0, // 166: ResolutionUnit (inch)
0x52, 0x01, 3, 0, 1, 0, 0, 0, 1, 0, 0, 0, // 178: ExtraSamples: rgbA
0, 0, 0, 0, // 190: IFD terminator
// EXTRA_DATA_OFFSET:
8, 0, 8, 0, 8, 0, 8, 0, // BitsPerSample
72, 0, 0, 0, 1, 0, 0, 0 // 72 pixels/inch, for X/Y-resolution
};
uint32_t y;
// Fill placeholders in IFD:
PutLE32(tiff_header + 10 + 8, width);
PutLE32(tiff_header + 22 + 8, height);
PutLE32(tiff_header + 106 + 8, height);
PutLE32(tiff_header + 118 + 8, width * bytes_per_px * height);
if (!has_alpha) PutLE32(tiff_header + 178, 0); // IFD terminator
// write header
if (fwrite(tiff_header, sizeof(tiff_header), 1, fout) != 1) {
return 0;
}
// write pixel values
for (y = 0; y < height; ++y) {
if (fwrite(rgba + y * stride, bytes_per_px, width, fout) != width) {
return 0;
}
}
return 1;
}
#undef TIFF_HEADER_SIZE
#undef EXTRA_DATA_OFFSET
#undef EXTRA_DATA_SIZE
#undef NUM_IFD_ENTRIES
static int WriteAlphaPlane(FILE* fout, const WebPDecBuffer* const buffer) {
const uint32_t width = buffer->width;
const uint32_t height = buffer->height;
const uint8_t* const a = buffer->u.YUVA.a;
const int a_stride = buffer->u.YUVA.a_stride;
uint32_t y;
assert(a != NULL);
fprintf(fout, "P5\n%d %d\n255\n", width, height);
for (y = 0; y < height; ++y) {
if (fwrite(a + y * a_stride, width, 1, fout) != 1) {
return 0;
}
}
return 1;
}
// format=PGM: save a grayscale PGM file using the IMC4 layout
// (http://www.fourcc.org/yuv.php#IMC4). This is a very convenient format for
// viewing the samples, esp. for odd dimensions.
// format=YUV: just save the Y/U/V/A planes sequentially without header.
static int WritePGMOrYUV(FILE* fout, const WebPDecBuffer* const buffer,
OutputFileFormat format) {
const int width = buffer->width;
const int height = buffer->height;
const WebPYUVABuffer* const yuv = &buffer->u.YUVA;
int ok = 1;
int y;
const int pad = (format == YUV) ? 0 : 1;
const int uv_width = (width + 1) / 2;
const int uv_height = (height + 1) / 2;
const int out_stride = (width + pad) & ~pad;
const int a_height = yuv->a ? height : 0;
if (format == PGM) {
fprintf(fout, "P5\n%d %d\n255\n",
out_stride, height + uv_height + a_height);
}
for (y = 0; ok && y < height; ++y) {
ok &= (fwrite(yuv->y + y * yuv->y_stride, width, 1, fout) == 1);
if (format == PGM) {
if (width & 1) fputc(0, fout); // padding byte
}
}
if (format == PGM) { // IMC4 layout
for (y = 0; ok && y < uv_height; ++y) {
ok &= (fwrite(yuv->u + y * yuv->u_stride, uv_width, 1, fout) == 1);
ok &= (fwrite(yuv->v + y * yuv->v_stride, uv_width, 1, fout) == 1);
}
} else {
for (y = 0; ok && y < uv_height; ++y) {
ok &= (fwrite(yuv->u + y * yuv->u_stride, uv_width, 1, fout) == 1);
}
for (y = 0; ok && y < uv_height; ++y) {
ok &= (fwrite(yuv->v + y * yuv->v_stride, uv_width, 1, fout) == 1);
}
}
for (y = 0; ok && y < a_height; ++y) {
ok &= (fwrite(yuv->a + y * yuv->a_stride, width, 1, fout) == 1);
if (format == PGM) {
if (width & 1) fputc(0, fout); // padding byte
}
}
return ok;
}
typedef enum {
PNG = 0,
PPM,
PGM,
} OutputFileFormat;
static int SaveOutput(const WebPDecBuffer* const buffer,
OutputFileFormat format, const char* const out_file) {
FILE* fout = NULL;
int needs_open_file = 1;
const int use_stdout = !strcmp(out_file, "-");
int ok = 1;
Stopwatch stop_watch;
if (verbose) {
StopwatchReset(&stop_watch);
}
#ifdef HAVE_WINCODEC_H
needs_open_file = (format != PNG);
#endif
if (needs_open_file) {
fout = use_stdout ? ExUtilSetBinaryMode(stdout) : fopen(out_file, "wb");
if (fout == NULL) {
fprintf(stderr, "Error opening output file %s\n", out_file);
return 0;
}
}
if (format == PNG) {
#ifdef HAVE_WINCODEC_H
ok &= WritePNG(out_file, use_stdout, buffer);
#else
ok &= WritePNG(fout, buffer);
#endif
} else if (format == PAM) {
ok &= WritePPM(fout, buffer, 1);
} else if (format == PPM) {
ok &= WritePPM(fout, buffer, 0);
} else if (format == BMP) {
ok &= WriteBMP(fout, buffer);
} else if (format == TIFF) {
ok &= WriteTIFF(fout, buffer);
} else if (format == PGM || format == YUV) {
ok &= WritePGMOrYUV(fout, buffer, format);
} else if (format == ALPHA_PLANE_ONLY) {
ok &= WriteAlphaPlane(fout, buffer);
}
if (fout != NULL && fout != stdout) {
fclose(fout);
}
if (ok) {
if (use_stdout) {
fprintf(stderr, "Saved to stdout\n");
} else {
fprintf(stderr, "Saved file %s\n", out_file);
}
if (verbose) {
const double write_time = StopwatchReadAndReset(&stop_watch);
fprintf(stderr, "Time to write output: %.3fs\n", write_time);
}
} else {
if (use_stdout) {
fprintf(stderr, "Error writing to stdout !!\n");
} else {
fprintf(stderr, "Error writing file %s !!\n", out_file);
}
}
return ok;
}
static void Help(void) {
printf("Usage: dwebp "
"[in_file] [-h] [-v] [-ppm] [-pgm] [-version] [-o out_file]\n\n"
printf("Usage: dwebp in_file [options] [-o out_file]\n\n"
"Decodes the WebP image file to PNG format [Default]\n"
"Use following options to convert into alternate image formats:\n"
" -ppm: save the raw RGB samples as color PPM\n"
" -pgm: save the raw YUV samples as a grayscale PGM\n"
" file with IMC4 layout.\n"
" -version: print version number and exit.\n"
"Use -v for verbose (e.g. print encoding/decoding times)\n"
" -pam ......... save the raw RGBA samples as a color PAM\n"
" -ppm ......... save the raw RGB samples as a color PPM\n"
" -bmp ......... save as uncompressed BMP format\n"
" -tiff ........ save as uncompressed TIFF format\n"
" -pgm ......... save the raw YUV samples as a grayscale PGM\n"
" file with IMC4 layout\n"
" -yuv ......... save the raw YUV samples in flat layout\n"
"\n"
" Other options are:\n"
" -version .... print version number and exit\n"
" -nofancy ..... don't use the fancy YUV420 upscaler\n"
" -nofilter .... disable in-loop filtering\n"
" -nodither .... disable dithering\n"
" -dither <d> .. dithering strength (in 0..100)\n"
#if WEBP_DECODER_ABI_VERSION > 0x0204
" -alpha_dither use alpha-plane dithering if needed\n"
#endif
" -mt .......... use multi-threading\n"
" -crop <x> <y> <w> <h> ... crop output with the given rectangle\n"
" -scale <w> <h> .......... scale the output (*after* any cropping)\n"
#if WEBP_DECODER_ABI_VERSION > 0x0203
" -flip ........ flip the output vertically\n"
#endif
" -alpha ....... only save the alpha plane\n"
" -incremental . use incremental decoding (useful for tests)\n"
" -h ....... this help message\n"
" -v ....... verbose (e.g. print encoding/decoding times)\n"
#ifndef WEBP_DLL
" -noasm ....... disable all assembly optimizations\n"
#endif
);
}
static const char* const kFormatType[] = {
"unspecified", "lossy", "lossless"
};
int main(int argc, const char *argv[]) {
int ok = 0;
const char *in_file = NULL;
const char *out_file = NULL;
int width, height, stride, uv_stride;
uint8_t* out = NULL, *u = NULL, *v = NULL;
WebPDecoderConfig config;
WebPDecBuffer* const output_buffer = &config.output;
WebPBitstreamFeatures* const bitstream = &config.input;
OutputFileFormat format = PNG;
Stopwatch stop_watch;
int incremental = 0;
int c;
if (!WebPInitDecoderConfig(&config)) {
fprintf(stderr, "Library version mismatch!\n");
return -1;
}
for (c = 1; c < argc; ++c) {
int parse_error = 0;
if (!strcmp(argv[c], "-h") || !strcmp(argv[c], "-help")) {
Help();
return 0;
} else if (!strcmp(argv[c], "-o") && c < argc - 1) {
out_file = argv[++c];
} else if (!strcmp(argv[c], "-alpha")) {
format = ALPHA_PLANE_ONLY;
} else if (!strcmp(argv[c], "-nofancy")) {
config.options.no_fancy_upsampling = 1;
} else if (!strcmp(argv[c], "-nofilter")) {
config.options.bypass_filtering = 1;
} else if (!strcmp(argv[c], "-pam")) {
format = PAM;
} else if (!strcmp(argv[c], "-ppm")) {
format = PPM;
} else if (!strcmp(argv[c], "-bmp")) {
format = BMP;
} else if (!strcmp(argv[c], "-tiff")) {
format = TIFF;
} else if (!strcmp(argv[c], "-version")) {
const int version = WebPGetDecoderVersion();
printf("%d.%d.%d\n",
(version >> 16) & 0xff, (version >> 8) & 0xff, version & 0xff);
(version >> 16) & 0xff, (version >> 8) & 0xff, version & 0xff);
return 0;
} else if (!strcmp(argv[c], "-pgm")) {
format = PGM;
} else if (!strcmp(argv[c], "-yuv")) {
format = YUV;
} else if (!strcmp(argv[c], "-mt")) {
config.options.use_threads = 1;
#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 =
ExUtilGetInt(argv[++c], 0, &parse_error);
} else if (!strcmp(argv[c], "-crop") && c < argc - 4) {
config.options.use_cropping = 1;
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 = 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;
#endif
} else if (!strcmp(argv[c], "-v")) {
verbose = 1;
#ifndef WEBP_DLL
} else if (!strcmp(argv[c], "-noasm")) {
VP8GetCPUInfo = NULL;
#endif
} else if (!strcmp(argv[c], "-incremental")) {
incremental = 1;
} else if (!strcmp(argv[c], "--")) {
if (c < argc - 1) in_file = argv[++c];
break;
} else if (argv[c][0] == '-') {
printf("Unknown option '%s'\n", argv[c]);
fprintf(stderr, "Unknown option '%s'\n", argv[c]);
Help();
return -1;
} else {
in_file = argv[c];
}
if (parse_error) {
Help();
return -1;
}
}
if (in_file == NULL) {
printf("missing input file!!\n");
fprintf(stderr, "missing input file!!\n");
Help();
return -1;
}
{
uint32_t data_size = 0;
void* data = NULL;
int ok;
FILE* const in = fopen(in_file, "rb");
if (!in) {
fprintf(stderr, "cannot open input file '%s'\n", in_file);
return 1;
}
fseek(in, 0, SEEK_END);
data_size = ftell(in);
fseek(in, 0, SEEK_SET);
data = malloc(data_size);
ok = (fread(data, data_size, 1, in) == 1);
fclose(in);
if (!ok) {
free(data);
VP8StatusCode status = VP8_STATUS_OK;
size_t data_size = 0;
const uint8_t* data = NULL;
if (!ExUtilLoadWebP(in_file, &data, &data_size, bitstream)) {
return -1;
}
if (verbose)
StopwatchReadAndReset(&stop_watch);
switch (format) {
case PNG:
#ifdef _WIN32
out = WebPDecodeBGR((const uint8_t*)data, data_size, &width, &height);
#ifdef HAVE_WINCODEC_H
output_buffer->colorspace = bitstream->has_alpha ? MODE_BGRA : MODE_BGR;
#else
out = WebPDecodeRGB((const uint8_t*)data, data_size, &width, &height);
output_buffer->colorspace = bitstream->has_alpha ? MODE_RGBA : MODE_RGB;
#endif
break;
case PAM:
output_buffer->colorspace = MODE_RGBA;
break;
case PPM:
out = WebPDecodeRGB((const uint8_t*)data, data_size, &width, &height);
output_buffer->colorspace = MODE_RGB; // drops alpha for PPM
break;
case BMP:
output_buffer->colorspace = bitstream->has_alpha ? MODE_BGRA : MODE_BGR;
break;
case TIFF: // note: force pre-multiplied alpha
output_buffer->colorspace =
bitstream->has_alpha ? MODE_rgbA : MODE_RGB;
break;
case PGM:
out = WebPDecodeYUV((const uint8_t*)data, data_size, &width, &height,
&u, &v, &stride, &uv_stride);
case YUV:
output_buffer->colorspace = bitstream->has_alpha ? MODE_YUVA : MODE_YUV;
break;
case ALPHA_PLANE_ONLY:
output_buffer->colorspace = MODE_YUVA;
break;
default:
free(data);
free((void*)data);
return -1;
}
if (verbose) {
const double time = StopwatchReadAndReset(&stop_watch);
printf("Time to decode picture: %.3fs\n", time);
}
free(data);
}
if (!out) {
fprintf(stderr, "Decoding of %s failed.\n", in_file);
return -1;
}
if (out_file) {
FILE* fout = NULL;
int needs_open_file = 0;
printf("Decoded %s. Dimensions: %d x %d. Now saving...\n", in_file, width, height);
StopwatchReadAndReset(&stop_watch);
#ifdef _WIN32
if (format != PNG) {
needs_open_file = 1;
}
#else
needs_open_file = 1;
#endif
if (needs_open_file) fout = fopen(out_file, "wb");
if (!needs_open_file || fout) {
int ok = 1;
if (format == PNG) {
#ifdef _WIN32
ok &= WritePNG(out_file, out, 3 * width, width, height);
#else
ok &= WritePNG(fout, out, 3 * width, width, height);
#endif
} else if (format == PPM) {
ok &= WritePPM(fout, out, width, height);
} else if (format == PGM) {
ok &= WritePGM(fout, out, u, v, stride, uv_stride, width, height);
}
if (fout)
fclose(fout);
if (ok) {
printf("Saved file %s\n", out_file);
if (verbose) {
const double time = StopwatchReadAndReset(&stop_watch);
printf("Time to write output: %.3fs\n", time);
}
} else {
fprintf(stderr, "Error writing file %s !!\n", out_file);
}
if (incremental) {
status = ExUtilDecodeWebPIncremental(data, data_size, verbose, &config);
} else {
fprintf(stderr, "Error opening output file %s\n", out_file);
status = ExUtilDecodeWebP(data, data_size, verbose, &config);
}
} else {
printf("File %s can be decoded (dimensions: %d x %d).\n",
in_file, width, height);
printf("Nothing written; use -o flag to save the result as e.g. PNG.\n");
}
free(out);
return 0;
free((void*)data);
ok = (status == VP8_STATUS_OK);
if (!ok) {
ExUtilPrintWebPError(in_file, status);
goto Exit;
}
}
if (out_file != NULL) {
fprintf(stderr, "Decoded %s. Dimensions: %d x %d %s. Format: %s. "
"Now saving...\n",
in_file, output_buffer->width, output_buffer->height,
bitstream->has_alpha ? " (with alpha)" : "",
kFormatType[bitstream->format]);
ok = SaveOutput(output_buffer, format, out_file);
} else {
fprintf(stderr, "File %s can be decoded "
"(dimensions: %d x %d %s. Format: %s).\n",
in_file, output_buffer->width, output_buffer->height,
bitstream->has_alpha ? " (with alpha)" : "",
kFormatType[bitstream->format]);
fprintf(stderr, "Nothing written; "
"use -o flag to save the result as e.g. PNG.\n");
}
Exit:
WebPFreeDecBuffer(output_buffer);
return ok ? 0 : -1;
}
//-----------------------------------------------------------------------------
#if defined(__cplusplus) || defined(c_plusplus)
} // extern "C"
#endif
//------------------------------------------------------------------------------

258
examples/example_util.c Normal file
View File

@ -0,0 +1,258 @@
// Copyright 2012 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.
// -----------------------------------------------------------------------------
//
// Utility functions used by the example programs.
//
#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>
#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
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;
if (data == NULL || data_size == NULL) return 0;
*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;
void* const new_data = realloc(input, max_size + extra_size);
if (new_data == NULL) goto Error;
input = (uint8_t*)new_data;
max_size += extra_size;
size += fread(input + size, 1, extra_size, stdin);
if (size < max_size) break;
}
if (ferror(stdin)) goto Error;
*data = input;
*data_size = size;
return 1;
Error:
free(input);
fprintf(stderr, "Could not read from stdin\n");
return 0;
}
int ExUtilReadFile(const char* const file_name,
const uint8_t** data, size_t* data_size) {
int ok;
void* file_data;
size_t file_size;
FILE* in;
const int from_stdin = (file_name == NULL) || !strcmp(file_name, "-");
if (from_stdin) return ExUtilReadFromStdin(data, data_size);
if (data == NULL || data_size == NULL) return 0;
*data = NULL;
*data_size = 0;
in = fopen(file_name, "rb");
if (in == NULL) {
fprintf(stderr, "cannot open input file '%s'\n", file_name);
return 0;
}
fseek(in, 0, SEEK_END);
file_size = ftell(in);
fseek(in, 0, SEEK_SET);
file_data = malloc(file_size);
if (file_data == NULL) return 0;
ok = (fread(file_data, file_size, 1, in) == 1);
fclose(in);
if (!ok) {
fprintf(stderr, "Could not read %d bytes of data from file %s\n",
(int)file_size, file_name);
free(file_data);
return 0;
}
*data = (uint8_t*)file_data;
*data_size = file_size;
return 1;
}
int ExUtilWriteFile(const char* const file_name,
const uint8_t* data, size_t data_size) {
int ok;
FILE* out;
const int to_stdout = (file_name == NULL) || !strcmp(file_name, "-");
if (data == NULL) {
return 0;
}
out = to_stdout ? stdout : fopen(file_name, "wb");
if (out == NULL) {
fprintf(stderr, "Error! Cannot open output file '%s'\n", file_name);
return 0;
}
ok = (fwrite(data, data_size, 1, out) == 1);
if (out != stdout) fclose(out);
return ok;
}
//------------------------------------------------------------------------------
// WebP decoding
static const char* const kStatusMessages[VP8_STATUS_NOT_ENOUGH_DATA + 1] = {
"OK", "OUT_OF_MEMORY", "INVALID_PARAM", "BITSTREAM_ERROR",
"UNSUPPORTED_FEATURE", "SUSPENDED", "USER_ABORT", "NOT_ENOUGH_DATA"
};
static void PrintAnimationWarning(const WebPDecoderConfig* const config) {
if (config->input.has_animation) {
fprintf(stderr,
"Error! Decoding of an animated WebP file is not supported.\n"
" Use webpmux to extract the individual frames or\n"
" vwebp to view this image.\n");
}
}
void ExUtilPrintWebPError(const char* const in_file, int status) {
fprintf(stderr, "Decoding of %s failed.\n", in_file);
fprintf(stderr, "Status: %d", status);
if (status >= VP8_STATUS_OK && status <= VP8_STATUS_NOT_ENOUGH_DATA) {
fprintf(stderr, "(%s)", kStatusMessages[status]);
}
fprintf(stderr, "\n");
}
int ExUtilLoadWebP(const char* const in_file,
const uint8_t** data, size_t* data_size,
WebPBitstreamFeatures* bitstream) {
VP8StatusCode status;
WebPBitstreamFeatures local_features;
if (!ExUtilReadFile(in_file, data, data_size)) return 0;
if (bitstream == NULL) {
bitstream = &local_features;
}
status = WebPGetFeatures(*data, *data_size, bitstream);
if (status != VP8_STATUS_OK) {
free((void*)*data);
*data = NULL;
*data_size = 0;
ExUtilPrintWebPError(in_file, status);
return 0;
}
return 1;
}
//------------------------------------------------------------------------------
VP8StatusCode ExUtilDecodeWebP(const uint8_t* const data, size_t data_size,
int verbose, WebPDecoderConfig* const config) {
Stopwatch stop_watch;
VP8StatusCode status = VP8_STATUS_OK;
if (config == NULL) return VP8_STATUS_INVALID_PARAM;
PrintAnimationWarning(config);
StopwatchReset(&stop_watch);
// Decoding call.
status = WebPDecode(data, data_size, config);
if (verbose) {
const double decode_time = StopwatchReadAndReset(&stop_watch);
fprintf(stderr, "Time to decode picture: %.3fs\n", decode_time);
}
return status;
}
VP8StatusCode ExUtilDecodeWebPIncremental(
const uint8_t* const data, size_t data_size,
int verbose, WebPDecoderConfig* const config) {
Stopwatch stop_watch;
VP8StatusCode status = VP8_STATUS_OK;
if (config == NULL) return VP8_STATUS_INVALID_PARAM;
PrintAnimationWarning(config);
StopwatchReset(&stop_watch);
// Decoding call.
{
WebPIDecoder* const idec = WebPIDecode(data, data_size, config);
if (idec == NULL) {
fprintf(stderr, "Failed during WebPINewDecoder().\n");
return VP8_STATUS_OUT_OF_MEMORY;
} else {
status = WebPIUpdate(idec, data, data_size);
WebPIDelete(idec);
}
}
if (verbose) {
const double decode_time = StopwatchReadAndReset(&stop_watch);
fprintf(stderr, "Time to decode picture: %.3fs\n", decode_time);
}
return status;
}
// -----------------------------------------------------------------------------

89
examples/example_util.h Normal file
View File

@ -0,0 +1,89 @@
// Copyright 2012 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.
// -----------------------------------------------------------------------------
//
// Utility functions used by the example programs.
//
#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().
// If 'file_name' is NULL or equal to "-", input is read from stdin by calling
// the function ExUtilReadFromStdin().
int ExUtilReadFile(const char* const file_name,
const uint8_t** data, size_t* data_size);
// Same as ExUtilReadFile(), but reads until EOF from stdin instead.
int ExUtilReadFromStdin(const uint8_t** data, size_t* data_size);
// Write a data segment into a file named 'file_name'. Returns true if ok.
// If 'file_name' is NULL or equal to "-", output is written to stdout.
int ExUtilWriteFile(const char* const file_name,
const uint8_t* data, size_t data_size);
//------------------------------------------------------------------------------
// WebP decoding
// Prints an informative error message regarding decode failure of 'in_file'.
// 'status' is treated as a VP8StatusCode and if valid will be printed as a
// text string.
void ExUtilPrintWebPError(const char* const in_file, int status);
// Reads a WebP from 'in_file', returning the contents and size in 'data' and
// 'data_size'. If not NULL, 'bitstream' is populated using WebPGetFeatures().
// Returns true on success.
int ExUtilLoadWebP(const char* const in_file,
const uint8_t** data, size_t* data_size,
WebPBitstreamFeatures* bitstream);
// Decodes the WebP contained in 'data'.
// 'config' is a structure previously initialized by WebPInitDecoderConfig().
// 'config->output' should have the desired colorspace selected. 'verbose' will
// cause decode timing to be reported.
// Returns the decoder status. On success 'config->output' will contain the
// decoded picture.
VP8StatusCode ExUtilDecodeWebP(const uint8_t* const data, size_t data_size,
int verbose, WebPDecoderConfig* const config);
// Same as ExUtilDecodeWebP(), but using the incremental decoder.
VP8StatusCode ExUtilDecodeWebPIncremental(
const uint8_t* const data, size_t data_size,
int verbose, WebPDecoderConfig* const config);
#ifdef __cplusplus
} // extern "C"
#endif
#endif // WEBP_EXAMPLES_EXAMPLE_UTIL_H_

732
examples/gif2webp.c Normal file
View File

@ -0,0 +1,732 @@
// Copyright 2012 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.
// -----------------------------------------------------------------------------
//
// simple tool to convert animated GIFs to WebP
//
// Authors: Skal (pascal.massimino@gmail.com)
// Urvang (urvang@google.com)
#include <assert.h>
#include <stdio.h>
#include <string.h>
#ifdef HAVE_CONFIG_H
#include "webp/config.h"
#endif
#ifdef WEBP_HAVE_GIF
#include <gif_lib.h>
#include "webp/encode.h"
#include "webp/mux.h"
#include "./example_util.h"
#include "./gif2webp_util.h"
// GIFLIB_MAJOR is only defined in libgif >= 4.2.0.
#if defined(GIFLIB_MAJOR) && defined(GIFLIB_MINOR)
# define LOCAL_GIF_VERSION ((GIFLIB_MAJOR << 8) | GIFLIB_MINOR)
# define LOCAL_GIF_PREREQ(maj, min) \
(LOCAL_GIF_VERSION >= (((maj) << 8) | (min)))
#else
# define LOCAL_GIF_VERSION 0
# define LOCAL_GIF_PREREQ(maj, min) 0
#endif
#define GIF_TRANSPARENT_MASK 0x01
#define GIF_DISPOSE_MASK 0x07
#define GIF_DISPOSE_SHIFT 2
#define WHITE_COLOR 0xffffffff
#define MAX_CACHE_SIZE 30
//------------------------------------------------------------------------------
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) {
size_t kmin = *kmin_ptr;
size_t kmax = *kmax_ptr;
int print_warning = 1;
if (kmin == 0) { // Disable keyframe insertion.
kmax = ~0;
kmin = kmax - 1;
print_warning = 0;
}
if (kmax == 0) {
kmax = ~0;
print_warning = 0;
}
if (kmin >= kmax) {
kmin = kmax - 1;
if (print_warning) {
fprintf(stderr,
"WARNING: Setting kmin = %d, so that kmin < kmax.\n", (int)kmin);
}
} else if (kmin < (kmax / 2 + 1)) {
// This ensures that cache.keyframe + kmin >= kmax is always true. So, we
// can flush all the frames in the count_since_key_frame == kmax case.
kmin = (kmax / 2 + 1);
if (print_warning) {
fprintf(stderr,
"WARNING: Setting kmin = %d, so that kmin >= kmax / 2 + 1.\n",
(int)kmin);
}
}
// Limit the max number of frames that are allocated.
if (kmax - kmin > MAX_CACHE_SIZE) {
kmin = kmax - MAX_CACHE_SIZE;
if (print_warning) {
fprintf(stderr,
"WARNING: Setting kmin = %d, so that kmax - kmin <= 30.\n",
(int)kmin);
}
}
*kmin_ptr = kmin;
*kmax_ptr = kmax;
}
static void Remap(const uint8_t* const src, const GifFileType* const gif,
uint32_t* dst, int len) {
int i;
const GifColorType* colors;
const ColorMapObject* const cmap =
gif->Image.ColorMap ? gif->Image.ColorMap : gif->SColorMap;
if (cmap == NULL) return;
colors = cmap->Colors;
for (i = 0; i < len; ++i) {
const GifColorType c = colors[src[i]];
dst[i] = (src[i] == transparent_index) ? WEBP_UTIL_TRANSPARENT_COLOR
: c.Blue | (c.Green << 8) | (c.Red << 16) | (0xff << 24);
}
}
// Read the GIF image frame.
static int ReadFrame(GifFileType* const gif, WebPFrameRect* const gif_rect,
WebPPicture* const webp_frame) {
WebPPicture sub_image;
const GifImageDesc* const image_desc = &gif->Image;
uint32_t* dst = NULL;
uint8_t* tmp = NULL;
int ok = 0;
WebPFrameRect rect = {
image_desc->Left, image_desc->Top, image_desc->Width, image_desc->Height
};
*gif_rect = rect;
// Use a view for the sub-picture:
if (!WebPPictureView(webp_frame, rect.x_offset, rect.y_offset,
rect.width, rect.height, &sub_image)) {
fprintf(stderr, "Sub-image %dx%d at position %d,%d is invalid!\n",
rect.width, rect.height, rect.x_offset, rect.y_offset);
return 0;
}
dst = sub_image.argb;
tmp = (uint8_t*)malloc(rect.width * sizeof(*tmp));
if (tmp == NULL) goto End;
if (image_desc->Interlace) { // Interlaced image.
// We need 4 passes, with the following offsets and jumps.
const int interlace_offsets[] = { 0, 4, 2, 1 };
const int interlace_jumps[] = { 8, 8, 4, 2 };
int pass;
for (pass = 0; pass < 4; ++pass) {
int y;
for (y = interlace_offsets[pass]; y < rect.height;
y += interlace_jumps[pass]) {
if (DGifGetLine(gif, tmp, rect.width) == GIF_ERROR) goto End;
Remap(tmp, gif, dst + y * sub_image.argb_stride, rect.width);
}
}
} else { // Non-interlaced image.
int y;
for (y = 0; y < rect.height; ++y) {
if (DGifGetLine(gif, tmp, rect.width) == GIF_ERROR) goto End;
Remap(tmp, gif, dst + y * sub_image.argb_stride, rect.width);
}
}
ok = 1;
End:
if (!ok) webp_frame->error_code = sub_image.error_code;
WebPPictureFree(&sub_image);
free(tmp);
return ok;
}
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.
} else if (color_map == NULL || color_map->Colors == NULL
|| bgcolor_idx >= color_map->ColorCount) {
*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);
}
}
static void DisplayGifError(const GifFileType* const gif, int gif_error) {
// libgif 4.2.0 has retired PrintGifError() and added GifErrorString().
#if LOCAL_GIF_PREREQ(4,2)
#if LOCAL_GIF_PREREQ(5,0)
// Static string actually, hence the const char* cast.
const char* error_str = (const char*)GifErrorString(
(gif == NULL) ? gif_error : gif->Error);
#else
const char* error_str = (const char*)GifErrorString();
(void)gif;
#endif
if (error_str == NULL) error_str = "Unknown error";
fprintf(stderr, "GIFLib Error %d: %s\n", gif_error, error_str);
#else
(void)gif;
fprintf(stderr, "GIFLib Error %d: ", gif_error);
PrintGifError();
fprintf(stderr, "\n");
#endif
}
static const char* const kErrorMessages[-WEBP_MUX_NOT_ENOUGH_DATA + 1] = {
"WEBP_MUX_NOT_FOUND", "WEBP_MUX_INVALID_ARGUMENT", "WEBP_MUX_BAD_DATA",
"WEBP_MUX_MEMORY_ERROR", "WEBP_MUX_NOT_ENOUGH_DATA"
};
static const char* ErrorString(WebPMuxError err) {
assert(err <= WEBP_MUX_NOT_FOUND && err >= WEBP_MUX_NOT_ENOUGH_DATA);
return kErrorMessages[-err];
}
enum {
METADATA_ICC = (1 << 0),
METADATA_XMP = (1 << 1),
METADATA_ALL = METADATA_ICC | METADATA_XMP
};
//------------------------------------------------------------------------------
static void Help(void) {
printf("Usage:\n");
printf(" gif2webp [options] gif_file -o webp_file\n");
printf("Options:\n");
printf(" -h / -help ............ this help\n");
printf(" -lossy ................. encode image using lossy compression\n");
printf(" -mixed ................. for each frame in the image, pick lossy\n"
" or lossless compression heuristically\n");
printf(" -q <float> ............. quality factor (0:small..100:big)\n");
printf(" -m <int> ............... compression method (0=fast, 6=slowest)\n");
printf(" -kmin <int> ............ min distance between key frames\n");
printf(" -kmax <int> ............ max distance between key frames\n");
printf(" -f <int> ............... filter strength (0=off..100)\n");
printf(" -metadata <string> ..... comma separated list of metadata to\n");
printf(" ");
printf("copy from the input to the output if present\n");
printf(" "
"Valid values: all, none, icc, xmp (default)\n");
printf(" -mt .................... use multi-threading if available\n");
printf("\n");
printf(" -version ............... print version number and exit\n");
printf(" -v ..................... verbose\n");
printf(" -quiet ................. don't print anything\n");
printf("\n");
}
//------------------------------------------------------------------------------
int main(int argc, const char *argv[]) {
int verbose = 0;
int gif_error = GIF_ERROR;
WebPMuxError err = WEBP_MUX_OK;
int ok = 0;
const char *in_file = NULL, *out_file = NULL;
FILE* out = NULL;
GifFileType* gif = NULL;
WebPConfig config;
WebPPicture frame;
WebPMuxFrameInfo info;
WebPMuxAnimParams anim = { WHITE_COLOR, 0 };
WebPFrameCache* cache = NULL;
int is_first_frame = 1; // Whether we are processing the first frame.
int done;
int c;
int quiet = 0;
WebPMux* mux = NULL;
WebPData webp_data = { NULL, 0 };
int keep_metadata = METADATA_XMP; // ICC not output by default.
int stored_icc = 0; // Whether we have already stored an ICC profile.
int stored_xmp = 0;
int default_kmin = 1; // Whether to use default kmin value.
int default_kmax = 1;
size_t kmin = 0;
size_t kmax = 0;
int allow_mixed = 0; // If true, each frame can be lossy or lossless.
ResetFrameInfo(&info);
if (!WebPConfigInit(&config) || !WebPPictureInit(&frame)) {
fprintf(stderr, "Error! Version mismatch!\n");
return -1;
}
config.lossless = 1; // Use lossless compression by default.
config.image_hint = WEBP_HINT_GRAPH; // always low-color
if (argc == 1) {
Help();
return 0;
}
for (c = 1; c < argc; ++c) {
int parse_error = 0;
if (!strcmp(argv[c], "-h") || !strcmp(argv[c], "-help")) {
Help();
return 0;
} else if (!strcmp(argv[c], "-o") && c < argc - 1) {
out_file = argv[++c];
} else if (!strcmp(argv[c], "-lossy")) {
config.lossless = 0;
} else if (!strcmp(argv[c], "-mixed")) {
allow_mixed = 1;
config.lossless = 0;
} else if (!strcmp(argv[c], "-q") && c < argc - 1) {
config.quality = ExUtilGetFloat(argv[++c], &parse_error);
} else if (!strcmp(argv[c], "-m") && c < argc - 1) {
config.method = ExUtilGetInt(argv[++c], 0, &parse_error);
} else if (!strcmp(argv[c], "-kmax") && c < argc - 1) {
kmax = ExUtilGetUInt(argv[++c], 0, &parse_error);
default_kmax = 0;
} else if (!strcmp(argv[c], "-kmin") && c < argc - 1) {
kmin = ExUtilGetUInt(argv[++c], 0, &parse_error);
default_kmin = 0;
} else if (!strcmp(argv[c], "-f") && c < argc - 1) {
config.filter_strength = ExUtilGetInt(argv[++c], 0, &parse_error);
} else if (!strcmp(argv[c], "-metadata") && c < argc - 1) {
static const struct {
const char* option;
int flag;
} kTokens[] = {
{ "all", METADATA_ALL },
{ "none", 0 },
{ "icc", METADATA_ICC },
{ "xmp", METADATA_XMP },
};
const size_t kNumTokens = sizeof(kTokens) / sizeof(*kTokens);
const char* start = argv[++c];
const char* const end = start + strlen(start);
keep_metadata = 0;
while (start < end) {
size_t i;
const char* token = strchr(start, ',');
if (token == NULL) token = end;
for (i = 0; i < kNumTokens; ++i) {
if ((size_t)(token - start) == strlen(kTokens[i].option) &&
!strncmp(start, kTokens[i].option, strlen(kTokens[i].option))) {
if (kTokens[i].flag != 0) {
keep_metadata |= kTokens[i].flag;
} else {
keep_metadata = 0;
}
break;
}
}
if (i == kNumTokens) {
fprintf(stderr, "Error! Unknown metadata type '%.*s'\n",
(int)(token - start), start);
Help();
return -1;
}
start = token + 1;
}
} else if (!strcmp(argv[c], "-mt")) {
++config.thread_level;
} else if (!strcmp(argv[c], "-version")) {
const int enc_version = WebPGetEncoderVersion();
const int mux_version = WebPGetMuxVersion();
printf("WebP Encoder version: %d.%d.%d\nWebP Mux version: %d.%d.%d\n",
(enc_version >> 16) & 0xff, (enc_version >> 8) & 0xff,
enc_version & 0xff, (mux_version >> 16) & 0xff,
(mux_version >> 8) & 0xff, mux_version & 0xff);
return 0;
} else if (!strcmp(argv[c], "-quiet")) {
quiet = 1;
} else if (!strcmp(argv[c], "-v")) {
verbose = 1;
} else if (!strcmp(argv[c], "--")) {
if (c < argc - 1) in_file = argv[++c];
break;
} else if (argv[c][0] == '-') {
fprintf(stderr, "Error! Unknown option '%s'\n", argv[c]);
Help();
return -1;
} else {
in_file = argv[c];
}
if (parse_error) {
Help();
return -1;
}
}
// Appropriate default kmin, kmax values for lossy and lossless.
if (default_kmin) {
kmin = config.lossless ? 9 : 3;
}
if (default_kmax) {
kmax = config.lossless ? 17 : 5;
}
SanitizeKeyFrameIntervals(&kmin, &kmax);
if (!WebPValidateConfig(&config)) {
fprintf(stderr, "Error! Invalid configuration.\n");
goto End;
}
if (in_file == NULL) {
fprintf(stderr, "No input file specified!\n");
Help();
goto End;
}
// Start the decoder object
#if LOCAL_GIF_PREREQ(5,0)
gif = DGifOpenFileName(in_file, &gif_error);
#else
gif = DGifOpenFileName(in_file);
#endif
if (gif == NULL) goto End;
mux = WebPMuxNew();
if (mux == NULL) {
fprintf(stderr, "ERROR: could not create a mux object.\n");
goto End;
}
// Loop over GIF images
done = 0;
do {
GifRecordType type;
if (DGifGetRecordType(gif, &type) == GIF_ERROR) goto End;
switch (type) {
case IMAGE_DESC_RECORD_TYPE: {
WebPFrameRect gif_rect;
GifImageDesc* const image_desc = &gif->Image;
if (!DGifGetImageDesc(gif)) goto End;
// Fix some broken GIF global headers that report
// 0 x 0 screen dimension.
if (is_first_frame) {
if (verbose) {
printf("Canvas screen: %d x %d\n", gif->SWidth, gif->SHeight);
}
if (gif->SWidth == 0 || gif->SHeight == 0) {
image_desc->Left = 0;
image_desc->Top = 0;
gif->SWidth = image_desc->Width;
gif->SHeight = image_desc->Height;
if (gif->SWidth <= 0 || gif->SHeight <= 0) {
goto End;
}
if (verbose) {
printf("Fixed canvas screen dimension to: %d x %d\n",
gif->SWidth, gif->SHeight);
}
}
#if WEBP_MUX_ABI_VERSION > 0x0101
// Set definitive canvas size.
err = WebPMuxSetCanvasSize(mux, gif->SWidth, gif->SHeight);
if (err != WEBP_MUX_OK) {
fprintf(stderr, "Invalid canvas size %d x %d\n",
gif->SWidth, gif->SHeight);
goto End;
}
#endif
// Allocate current buffer.
frame.width = gif->SWidth;
frame.height = gif->SHeight;
frame.use_argb = 1;
if (!WebPPictureAlloc(&frame)) goto End;
WebPUtilClearPic(&frame, NULL);
// Initialize cache.
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) {
image_desc->Width = gif->SWidth;
image_desc->Height = gif->SHeight;
}
if (!ReadFrame(gif, &gif_rect, &frame)) {
goto End;
}
if (!WebPFrameCacheAddFrame(cache, &config, &gif_rect, &frame, &info)) {
fprintf(stderr, "Error! Cannot encode frame as WebP\n");
fprintf(stderr, "Error code: %d\n", frame.error_code);
}
err = WebPFrameCacheFlush(cache, verbose, mux);
if (err != WEBP_MUX_OK) {
fprintf(stderr, "ERROR (%s): Could not add animation frame.\n",
ErrorString(err));
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: {
int extension;
GifByteType *data = NULL;
if (DGifGetExtension(gif, &extension, &data) == GIF_ERROR) {
goto End;
}
switch (extension) {
case COMMENT_EXT_FUNC_CODE: {
break; // Do nothing for now.
}
case GRAPHICS_EXT_FUNC_CODE: {
const int flags = data[1];
const int dispose = (flags >> GIF_DISPOSE_SHIFT) & GIF_DISPOSE_MASK;
const int delay = data[2] | (data[3] << 8); // In 10 ms units.
if (data[0] != 4) goto End;
info.duration = delay * 10; // Duration is in 1 ms units for WebP.
if (dispose == 3) {
static int warning_printed = 0;
if (!warning_printed) {
fprintf(stderr, "WARNING: GIF_DISPOSE_RESTORE unsupported.\n");
warning_printed = 1;
}
// failsafe. TODO(urvang): emulate the correct behaviour by
// recoding the whole frame.
info.dispose_method = WEBP_MUX_DISPOSE_BACKGROUND;
} else {
info.dispose_method =
(dispose == 2) ? WEBP_MUX_DISPOSE_BACKGROUND
: WEBP_MUX_DISPOSE_NONE;
}
transparent_index = (flags & GIF_TRANSPARENT_MASK) ? data[4] : -1;
break;
}
case PLAINTEXT_EXT_FUNC_CODE: {
break;
}
case APPLICATION_EXT_FUNC_CODE: {
if (data[0] != 11) break; // Chunk is too short
if (!memcmp(data + 1, "NETSCAPE2.0", 11) ||
!memcmp(data + 1, "ANIMEXTS1.0", 11)) {
// Recognize and parse Netscape2.0 NAB extension for loop count.
if (DGifGetExtensionNext(gif, &data) == GIF_ERROR) goto End;
if (data == NULL) goto End; // Loop count sub-block missing.
if (data[0] < 3 || data[1] != 1) break; // wrong size/marker
anim.loop_count = data[2] | (data[3] << 8);
if (verbose) {
fprintf(stderr, "Loop count: %d\n", anim.loop_count);
}
} else { // An extension containing metadata.
// We only store the first encountered chunk of each type, and
// only if requested by the user.
const int is_xmp = (keep_metadata & METADATA_XMP) &&
!stored_xmp &&
!memcmp(data + 1, "XMP DataXMP", 11);
const int is_icc = (keep_metadata & METADATA_ICC) &&
!stored_icc &&
!memcmp(data + 1, "ICCRGBG1012", 11);
if (is_xmp || is_icc) {
const char* const fourccs[2] = { "XMP " , "ICCP" };
const char* const features[2] = { "XMP" , "ICC" };
WebPData metadata = { NULL, 0 };
// Construct metadata from sub-blocks.
// Usual case (including ICC profile): In each sub-block, the
// first byte specifies its size in bytes (0 to 255) and the
// rest of the bytes contain the data.
// Special case for XMP data: In each sub-block, the first byte
// is also part of the XMP payload. XMP in GIF also has a 257
// byte padding data. See the XMP specification for details.
while (1) {
WebPData prev_metadata = metadata;
WebPData subblock;
if (DGifGetExtensionNext(gif, &data) == GIF_ERROR) {
WebPDataClear(&metadata);
goto End;
}
if (data == NULL) break; // Finished.
subblock.size = is_xmp ? data[0] + 1 : data[0];
assert(subblock.size > 0);
subblock.bytes = is_xmp ? data : data + 1;
metadata.bytes =
(uint8_t*)realloc((void*)metadata.bytes,
prev_metadata.size + subblock.size);
if (metadata.bytes == NULL) {
WebPDataClear(&prev_metadata);
goto End;
}
metadata.size += subblock.size;
memcpy((void*)(metadata.bytes + prev_metadata.size),
subblock.bytes, subblock.size);
}
if (is_xmp) {
// XMP padding data is 0x01, 0xff, 0xfe ... 0x01, 0x00.
const size_t xmp_pading_size = 257;
if (metadata.size > xmp_pading_size) {
metadata.size -= xmp_pading_size;
}
}
// Add metadata chunk.
err = WebPMuxSetChunk(mux, fourccs[is_icc], &metadata, 1);
if (verbose) {
fprintf(stderr, "%s size: %d\n",
features[is_icc], (int)metadata.size);
}
WebPDataClear(&metadata);
if (err != WEBP_MUX_OK) {
fprintf(stderr, "ERROR (%s): Could not set %s chunk.\n",
ErrorString(err), features[is_icc]);
goto End;
}
if (is_icc) {
stored_icc = 1;
} else if (is_xmp) {
stored_xmp = 1;
}
}
}
break;
}
default: {
break; // skip
}
}
while (data != NULL) {
if (DGifGetExtensionNext(gif, &data) == GIF_ERROR) goto End;
}
break;
}
case TERMINATE_RECORD_TYPE: {
done = 1;
break;
}
default: {
if (verbose) {
fprintf(stderr, "Skipping over unknown record type %d\n", type);
}
break;
}
}
} while (!done);
// Flush any pending frames.
err = WebPFrameCacheFlushAll(cache, verbose, mux);
if (err != WEBP_MUX_OK) {
fprintf(stderr, "ERROR (%s): Could not add animation frame.\n",
ErrorString(err));
goto End;
}
// Finish muxing
err = WebPMuxSetAnimationParams(mux, &anim);
if (err != WEBP_MUX_OK) {
fprintf(stderr, "ERROR (%s): Could not set animation parameters.\n",
ErrorString(err));
goto End;
}
err = WebPMuxAssemble(mux, &webp_data);
if (err != WEBP_MUX_OK) {
fprintf(stderr, "ERROR (%s) assembling the WebP file.\n", ErrorString(err));
goto End;
}
if (out_file != NULL) {
if (!ExUtilWriteFile(out_file, webp_data.bytes, webp_data.size)) {
fprintf(stderr, "Error writing output file: %s\n", out_file);
goto End;
}
if (!quiet) {
fprintf(stderr, "Saved output file: %s\n", out_file);
}
} else {
if (!quiet) {
fprintf(stderr, "Nothing written; use -o flag to save the result.\n");
}
}
// All OK.
ok = 1;
gif_error = GIF_OK;
End:
WebPDataClear(&webp_data);
WebPMuxDelete(mux);
WebPPictureFree(&frame);
WebPFrameCacheDelete(cache);
if (out != NULL && out_file != NULL) fclose(out);
if (gif_error != GIF_OK) {
DisplayGifError(gif, gif_error);
}
if (gif != NULL) {
#if LOCAL_GIF_PREREQ(5,1)
DGifCloseFile(gif, &gif_error);
#else
DGifCloseFile(gif);
#endif
}
return !ok;
}
#else // !WEBP_HAVE_GIF
int main(int argc, const char *argv[]) {
fprintf(stderr, "GIF support not enabled in %s.\n", argv[0]);
(void)argc;
return 0;
}
#endif
//------------------------------------------------------------------------------

708
examples/gif2webp_util.c Normal file
View File

@ -0,0 +1,708 @@
// Copyright 2013 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.
// -----------------------------------------------------------------------------
//
// Helper structs and methods for gif2webp tool.
//
#include <assert.h>
#include <stdio.h>
#include "webp/encode.h"
#include "./gif2webp_util.h"
#define DELTA_INFINITY 1ULL << 32
#define KEYFRAME_NONE -1
//------------------------------------------------------------------------------
// Helper utilities.
static void ClearRectangle(WebPPicture* const picture,
int left, int top, int width, int height) {
int j;
for (j = top; j < top + height; ++j) {
uint32_t* const dst = picture->argb + j * picture->argb_stride;
int i;
for (i = left; i < left + width; ++i) {
dst[i] = WEBP_UTIL_TRANSPARENT_COLOR;
}
}
}
void WebPUtilClearPic(WebPPicture* const picture,
const WebPFrameRect* const rect) {
if (rect != NULL) {
ClearRectangle(picture, rect->x_offset, rect->y_offset,
rect->width, rect->height);
} else {
ClearRectangle(picture, 0, 0, picture->width, picture->height);
}
}
// TODO: Also used in picture.c. Move to a common location?
// Copy width x height pixels from 'src' to 'dst' honoring the strides.
static void CopyPlane(const uint8_t* src, int src_stride,
uint8_t* dst, int dst_stride, int width, int height) {
while (height-- > 0) {
memcpy(dst, src, width);
src += src_stride;
dst += dst_stride;
}
}
// Copy pixels from 'src' to 'dst' honoring strides. 'src' and 'dst' are assumed
// to be already allocated.
static void CopyPixels(const WebPPicture* const src, WebPPicture* const dst) {
assert(src->width == dst->width && src->height == dst->height);
CopyPlane((uint8_t*)src->argb, 4 * src->argb_stride, (uint8_t*)dst->argb,
4 * dst->argb_stride, 4 * src->width, src->height);
}
// Given 'src' picture and its frame rectangle 'rect', blend it into 'dst'.
static void BlendPixels(const WebPPicture* const src,
const WebPFrameRect* const rect,
WebPPicture* const dst) {
int j;
assert(src->width == dst->width && src->height == dst->height);
for (j = rect->y_offset; j < rect->y_offset + rect->height; ++j) {
int i;
for (i = rect->x_offset; i < rect->x_offset + rect->width; ++i) {
const uint32_t src_pixel = src->argb[j * src->argb_stride + i];
const int src_alpha = src_pixel >> 24;
if (src_alpha != 0) {
dst->argb[j * dst->argb_stride + i] = src_pixel;
}
}
}
}
// Replace transparent pixels within 'dst_rect' of 'dst' by those in the 'src'.
static void ReduceTransparency(const WebPPicture* const src,
const WebPFrameRect* const rect,
WebPPicture* const dst) {
int i, j;
assert(src != NULL && dst != NULL && rect != NULL);
assert(src->width == dst->width && src->height == dst->height);
for (j = rect->y_offset; j < rect->y_offset + rect->height; ++j) {
for (i = rect->x_offset; i < rect->x_offset + rect->width; ++i) {
const uint32_t src_pixel = src->argb[j * src->argb_stride + i];
const int src_alpha = src_pixel >> 24;
const uint32_t dst_pixel = dst->argb[j * dst->argb_stride + i];
const int dst_alpha = dst_pixel >> 24;
if (dst_alpha == 0 && src_alpha == 0xff) {
dst->argb[j * dst->argb_stride + i] = src_pixel;
}
}
}
}
// Replace similar blocks of pixels by a 'see-through' transparent block
// with uniform average color.
static void FlattenSimilarBlocks(const WebPPicture* const src,
const WebPFrameRect* const rect,
WebPPicture* const dst) {
int i, j;
const int block_size = 8;
const int y_start = (rect->y_offset + block_size) & ~(block_size - 1);
const int y_end = (rect->y_offset + rect->height) & ~(block_size - 1);
const int x_start = (rect->x_offset + block_size) & ~(block_size - 1);
const int x_end = (rect->x_offset + rect->width) & ~(block_size - 1);
assert(src != NULL && dst != NULL && rect != NULL);
assert(src->width == dst->width && src->height == dst->height);
assert((block_size & (block_size - 1)) == 0); // must be a power of 2
// Iterate over each block and count similar pixels.
for (j = y_start; j < y_end; j += block_size) {
for (i = x_start; i < x_end; i += block_size) {
int cnt = 0;
int avg_r = 0, avg_g = 0, avg_b = 0;
int x, y;
const uint32_t* const psrc = src->argb + j * src->argb_stride + i;
uint32_t* const pdst = dst->argb + j * dst->argb_stride + i;
for (y = 0; y < block_size; ++y) {
for (x = 0; x < block_size; ++x) {
const uint32_t src_pixel = psrc[x + y * src->argb_stride];
const int alpha = src_pixel >> 24;
if (alpha == 0xff &&
src_pixel == pdst[x + y * dst->argb_stride]) {
++cnt;
avg_r += (src_pixel >> 16) & 0xff;
avg_g += (src_pixel >> 8) & 0xff;
avg_b += (src_pixel >> 0) & 0xff;
}
}
}
// If we have a fully similar block, we replace it with an
// average transparent block. This compresses better in lossy mode.
if (cnt == block_size * block_size) {
const uint32_t color = (0x00 << 24) |
((avg_r / cnt) << 16) |
((avg_g / cnt) << 8) |
((avg_b / cnt) << 0);
for (y = 0; y < block_size; ++y) {
for (x = 0; x < block_size; ++x) {
pdst[x + y * dst->argb_stride] = color;
}
}
}
}
}
}
//------------------------------------------------------------------------------
// Key frame related utilities.
// Returns true if 'curr' frame with frame rectangle 'curr_rect' is a key frame,
// that is, it can be decoded independently of 'prev' canvas.
static int IsKeyFrame(const WebPPicture* const curr,
const WebPFrameRect* const curr_rect,
const WebPPicture* const prev) {
int i, j;
int is_key_frame = 1;
// If previous canvas (with previous frame disposed) is all transparent,
// current frame is a key frame.
for (j = 0; j < prev->height; ++j) {
const uint32_t* const row = &prev->argb[j * prev->argb_stride];
for (i = 0; i < prev->width; ++i) {
if (row[i] & 0xff000000u) { // has alpha?
is_key_frame = 0;
break;
}
}
if (!is_key_frame) break;
}
if (is_key_frame) return 1;
// If current frame covers the whole canvas and does not contain any
// transparent pixels that depend on previous canvas, then current frame is
// a key frame.
if (curr_rect->width == curr->width && curr_rect->height == curr->height) {
assert(curr_rect->x_offset == 0 && curr_rect->y_offset == 0);
is_key_frame = 1;
for (j = 0; j < prev->height; ++j) {
for (i = 0; i < prev->width; ++i) {
const uint32_t prev_alpha =
(prev->argb[j * prev->argb_stride + i]) >> 24;
const uint32_t curr_alpha =
(curr->argb[j * curr->argb_stride + i]) >> 24;
if (curr_alpha != 0xff && prev_alpha != 0) {
is_key_frame = 0;
break;
}
}
if (!is_key_frame) break;
}
if (is_key_frame) return 1;
}
return 0;
}
// Given 'prev' frame and current frame rectangle 'rect', convert 'curr' frame
// to a key frame.
static void ConvertToKeyFrame(const WebPPicture* const prev,
WebPFrameRect* const rect,
WebPPicture* const curr) {
int j;
assert(curr->width == prev->width && curr->height == prev->height);
// Replace transparent pixels of current canvas with those from previous
// canvas (with previous frame disposed).
for (j = 0; j < curr->height; ++j) {
int i;
for (i = 0; i < curr->width; ++i) {
uint32_t* const curr_pixel = curr->argb + j * curr->argb_stride + i;
const int curr_alpha = *curr_pixel >> 24;
if (curr_alpha == 0) {
*curr_pixel = prev->argb[j * prev->argb_stride + i];
}
}
}
// Frame rectangle now covers the whole canvas.
rect->x_offset = 0;
rect->y_offset = 0;
rect->width = curr->width;
rect->height = curr->height;
}
//------------------------------------------------------------------------------
// Encoded frame.
// Used to store two candidates of encoded data for an animation frame. One of
// the two will be chosen later.
typedef struct {
WebPMuxFrameInfo sub_frame; // Encoded frame rectangle.
WebPMuxFrameInfo key_frame; // Encoded frame if it was converted to keyframe.
} EncodedFrame;
// Release the data contained by 'encoded_frame'.
static void FrameRelease(EncodedFrame* const encoded_frame) {
if (encoded_frame != NULL) {
WebPDataClear(&encoded_frame->sub_frame.bitstream);
WebPDataClear(&encoded_frame->key_frame.bitstream);
memset(encoded_frame, 0, sizeof(*encoded_frame));
}
}
//------------------------------------------------------------------------------
// Frame cache.
// Used to store encoded frames that haven't been output yet.
struct WebPFrameCache {
EncodedFrame* encoded_frames; // Array of encoded frames.
size_t size; // Number of allocated data elements.
size_t start; // Start index.
size_t count; // Number of valid data elements.
int flush_count; // If >0, flush_count frames starting from
// 'start' are ready to be added to mux.
int64_t best_delta; // min(canvas size - frame size) over the frames.
// Can be negative in certain cases due to
// transparent pixels in a frame.
int keyframe; // Index of selected keyframe relative to 'start'.
size_t kmin; // Min distance between key frames.
size_t kmax; // Max distance between key frames.
size_t count_since_key_frame; // Frames seen since the last key frame.
int allow_mixed; // If true, each frame can be lossy or lossless.
WebPPicture prev_canvas; // Previous canvas (properly disposed).
WebPPicture curr_canvas; // Current canvas (temporary buffer).
int is_first_frame; // True if no frames have been added to the cache
// since WebPFrameCacheNew().
};
// Reset the counters in the cache struct. Doesn't touch 'cache->encoded_frames'
// and 'cache->size'.
static void CacheReset(WebPFrameCache* const cache) {
cache->start = 0;
cache->count = 0;
cache->flush_count = 0;
cache->best_delta = DELTA_INFINITY;
cache->keyframe = KEYFRAME_NONE;
}
WebPFrameCache* WebPFrameCacheNew(int width, int height,
size_t kmin, size_t kmax, int allow_mixed) {
WebPFrameCache* cache = (WebPFrameCache*)malloc(sizeof(*cache));
if (cache == NULL) return NULL;
CacheReset(cache);
// sanity init, so we can call WebPFrameCacheDelete():
cache->encoded_frames = NULL;
cache->is_first_frame = 1;
// Picture buffers.
if (!WebPPictureInit(&cache->prev_canvas) ||
!WebPPictureInit(&cache->curr_canvas)) {
return NULL;
}
cache->prev_canvas.width = width;
cache->prev_canvas.height = height;
cache->prev_canvas.use_argb = 1;
if (!WebPPictureAlloc(&cache->prev_canvas) ||
!WebPPictureCopy(&cache->prev_canvas, &cache->curr_canvas)) {
goto Err;
}
WebPUtilClearPic(&cache->prev_canvas, NULL);
// Cache data.
cache->allow_mixed = allow_mixed;
cache->kmin = kmin;
cache->kmax = kmax;
cache->count_since_key_frame = 0;
assert(kmax > kmin);
cache->size = kmax - kmin;
cache->encoded_frames =
(EncodedFrame*)calloc(cache->size, sizeof(*cache->encoded_frames));
if (cache->encoded_frames == NULL) goto Err;
return cache; // All OK.
Err:
WebPFrameCacheDelete(cache);
return NULL;
}
void WebPFrameCacheDelete(WebPFrameCache* const cache) {
if (cache != NULL) {
if (cache->encoded_frames != NULL) {
size_t i;
for (i = 0; i < cache->size; ++i) {
FrameRelease(&cache->encoded_frames[i]);
}
free(cache->encoded_frames);
}
WebPPictureFree(&cache->prev_canvas);
WebPPictureFree(&cache->curr_canvas);
free(cache);
}
}
static int EncodeFrame(const WebPConfig* const config, WebPPicture* const pic,
WebPMemoryWriter* const memory) {
pic->use_argb = 1;
pic->writer = WebPMemoryWrite;
pic->custom_ptr = memory;
if (!WebPEncode(config, pic)) {
return 0;
}
return 1;
}
static void GetEncodedData(const WebPMemoryWriter* const memory,
WebPData* const encoded_data) {
encoded_data->bytes = memory->mem;
encoded_data->size = memory->size;
}
#define MIN_COLORS_LOSSY 31 // Don't try lossy below this threshold.
#define MAX_COLORS_LOSSLESS 194 // Don't try lossless above this threshold.
#define MAX_COLOR_COUNT 256 // Power of 2 greater than MAX_COLORS_LOSSLESS.
#define HASH_SIZE (MAX_COLOR_COUNT * 4)
#define HASH_RIGHT_SHIFT 22 // 32 - log2(HASH_SIZE).
// TODO(urvang): Also used in enc/vp8l.c. Move to utils.
// If the number of colors in the 'pic' is at least MAX_COLOR_COUNT, return
// MAX_COLOR_COUNT. Otherwise, return the exact number of colors in the 'pic'.
static int GetColorCount(const WebPPicture* const pic) {
int x, y;
int num_colors = 0;
uint8_t in_use[HASH_SIZE] = { 0 };
uint32_t colors[HASH_SIZE];
static const uint32_t kHashMul = 0x1e35a7bd;
const uint32_t* argb = pic->argb;
const int width = pic->width;
const int height = pic->height;
uint32_t last_pix = ~argb[0]; // so we're sure that last_pix != argb[0]
for (y = 0; y < height; ++y) {
for (x = 0; x < width; ++x) {
int key;
if (argb[x] == last_pix) {
continue;
}
last_pix = argb[x];
key = (kHashMul * last_pix) >> HASH_RIGHT_SHIFT;
while (1) {
if (!in_use[key]) {
colors[key] = last_pix;
in_use[key] = 1;
++num_colors;
if (num_colors >= MAX_COLOR_COUNT) {
return MAX_COLOR_COUNT; // Exact count not needed.
}
break;
} else if (colors[key] == last_pix) {
break; // The color is already there.
} else {
// Some other color sits here, so do linear conflict resolution.
++key;
key &= (HASH_SIZE - 1); // Key mask.
}
}
}
argb += pic->argb_stride;
}
return num_colors;
}
#undef MAX_COLOR_COUNT
#undef HASH_SIZE
#undef HASH_RIGHT_SHIFT
static WebPEncodingError SetFrame(const WebPConfig* const config,
int allow_mixed, int is_key_frame,
const WebPPicture* const prev_canvas,
WebPPicture* const frame,
const WebPFrameRect* const rect,
const WebPMuxFrameInfo* const info,
WebPPicture* const sub_frame,
EncodedFrame* encoded_frame) {
WebPEncodingError error_code = VP8_ENC_OK;
int try_lossless;
int try_lossy;
int try_both;
WebPMemoryWriter mem1, mem2;
WebPData* encoded_data;
WebPMuxFrameInfo* const dst =
is_key_frame ? &encoded_frame->key_frame : &encoded_frame->sub_frame;
*dst = *info;
encoded_data = &dst->bitstream;
WebPMemoryWriterInit(&mem1);
WebPMemoryWriterInit(&mem2);
if (!allow_mixed) {
try_lossless = config->lossless;
try_lossy = !try_lossless;
} else { // Use a heuristic for trying lossless and/or lossy compression.
const int num_colors = GetColorCount(sub_frame);
try_lossless = (num_colors < MAX_COLORS_LOSSLESS);
try_lossy = (num_colors >= MIN_COLORS_LOSSY);
}
try_both = try_lossless && try_lossy;
if (try_lossless) {
WebPConfig config_ll = *config;
config_ll.lossless = 1;
if (!EncodeFrame(&config_ll, sub_frame, &mem1)) {
error_code = sub_frame->error_code;
goto Err;
}
}
if (try_lossy) {
WebPConfig config_lossy = *config;
config_lossy.lossless = 0;
if (!is_key_frame) {
// For lossy compression of a frame, it's better to replace transparent
// pixels of 'curr' with actual RGB values, whenever possible.
ReduceTransparency(prev_canvas, rect, frame);
// TODO(later): Investigate if this helps lossless compression as well.
FlattenSimilarBlocks(prev_canvas, rect, frame);
}
if (!EncodeFrame(&config_lossy, sub_frame, &mem2)) {
error_code = sub_frame->error_code;
goto Err;
}
}
if (try_both) { // Pick the encoding with smallest size.
// 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 > 0x0203
WebPMemoryWriterClear(&mem2);
#else
free(mem2.mem);
memset(&mem2, 0, sizeof(mem2));
#endif
GetEncodedData(&mem1, encoded_data);
} else {
#if WEBP_ENCODER_ABI_VERSION > 0x0203
WebPMemoryWriterClear(&mem1);
#else
free(mem1.mem);
memset(&mem1, 0, sizeof(mem1));
#endif
GetEncodedData(&mem2, encoded_data);
}
} else {
GetEncodedData(try_lossless ? &mem1 : &mem2, encoded_data);
}
return error_code;
Err:
#if WEBP_ENCODER_ABI_VERSION > 0x0203
WebPMemoryWriterClear(&mem1);
WebPMemoryWriterClear(&mem2);
#else
free(mem1.mem);
free(mem2.mem);
#endif
return error_code;
}
#undef MIN_COLORS_LOSSY
#undef MAX_COLORS_LOSSLESS
// Returns cached frame at given 'position' index.
static EncodedFrame* CacheGetFrame(const WebPFrameCache* const cache,
size_t position) {
assert(cache->start + position < cache->size);
return &cache->encoded_frames[cache->start + position];
}
// Calculate the penalty incurred if we encode given frame as a key frame
// instead of a sub-frame.
static int64_t KeyFramePenalty(const EncodedFrame* const encoded_frame) {
return ((int64_t)encoded_frame->key_frame.bitstream.size -
encoded_frame->sub_frame.bitstream.size);
}
static void DisposeFrame(WebPMuxAnimDispose dispose_method,
const WebPFrameRect* const gif_rect,
WebPPicture* const frame, WebPPicture* const canvas) {
if (dispose_method == WEBP_MUX_DISPOSE_BACKGROUND) {
WebPUtilClearPic(frame, NULL);
WebPUtilClearPic(canvas, gif_rect);
}
}
int WebPFrameCacheAddFrame(WebPFrameCache* const cache,
const WebPConfig* const config,
const WebPFrameRect* const orig_rect_ptr,
WebPPicture* const frame,
WebPMuxFrameInfo* const info) {
int ok = 0;
WebPEncodingError error_code = VP8_ENC_OK;
WebPFrameRect rect;
WebPPicture sub_image; // View extracted from 'frame' with rectangle 'rect'.
WebPPicture* const prev_canvas = &cache->prev_canvas;
const size_t position = cache->count;
const int allow_mixed = cache->allow_mixed;
EncodedFrame* const encoded_frame = CacheGetFrame(cache, position);
WebPFrameRect orig_rect;
assert(position < cache->size);
if (frame == NULL || info == NULL) {
return 0;
}
if (orig_rect_ptr == NULL) {
orig_rect.width = frame->width;
orig_rect.height = frame->height;
orig_rect.x_offset = 0;
orig_rect.y_offset = 0;
} else {
orig_rect = *orig_rect_ptr;
}
// Snap to even offsets (and adjust dimensions if needed).
rect = orig_rect;
rect.width += (rect.x_offset & 1);
rect.height += (rect.y_offset & 1);
rect.x_offset &= ~1;
rect.y_offset &= ~1;
if (!WebPPictureView(frame, rect.x_offset, rect.y_offset,
rect.width, rect.height, &sub_image)) {
return 0;
}
info->x_offset = rect.x_offset;
info->y_offset = rect.y_offset;
++cache->count;
if (cache->is_first_frame || IsKeyFrame(frame, &rect, prev_canvas)) {
// Add this as a key frame.
error_code = SetFrame(config, allow_mixed, 1, NULL, NULL, NULL,
info, &sub_image, encoded_frame);
if (error_code != VP8_ENC_OK) {
goto End;
}
cache->keyframe = position;
cache->flush_count = cache->count;
cache->count_since_key_frame = 0;
// Update prev_canvas by simply copying from 'curr'.
CopyPixels(frame, prev_canvas);
} else {
++cache->count_since_key_frame;
if (cache->count_since_key_frame <= cache->kmin) {
// Add this as a frame rectangle.
error_code = SetFrame(config, allow_mixed, 0, prev_canvas, frame,
&rect, info, &sub_image, encoded_frame);
if (error_code != VP8_ENC_OK) {
goto End;
}
cache->flush_count = cache->count;
// Update prev_canvas by blending 'curr' into it.
BlendPixels(frame, &orig_rect, prev_canvas);
} else {
WebPPicture full_image;
WebPMuxFrameInfo full_image_info;
int64_t curr_delta;
// Add frame rectangle to cache.
error_code = SetFrame(config, allow_mixed, 0, prev_canvas, frame, &rect,
info, &sub_image, encoded_frame);
if (error_code != VP8_ENC_OK) {
goto End;
}
// Convert to a key frame.
CopyPixels(frame, &cache->curr_canvas);
ConvertToKeyFrame(prev_canvas, &rect, &cache->curr_canvas);
if (!WebPPictureView(&cache->curr_canvas, rect.x_offset, rect.y_offset,
rect.width, rect.height, &full_image)) {
goto End;
}
full_image_info = *info;
full_image_info.x_offset = rect.x_offset;
full_image_info.y_offset = rect.y_offset;
// Add key frame to cache, too.
error_code = SetFrame(config, allow_mixed, 1, NULL, NULL, NULL,
&full_image_info, &full_image, encoded_frame);
WebPPictureFree(&full_image);
if (error_code != VP8_ENC_OK) goto End;
// Analyze size difference of the two variants.
curr_delta = KeyFramePenalty(encoded_frame);
if (curr_delta <= cache->best_delta) { // Pick this as keyframe.
cache->keyframe = position;
cache->best_delta = curr_delta;
cache->flush_count = cache->count - 1; // We can flush previous frames.
}
if (cache->count_since_key_frame == cache->kmax) {
cache->flush_count = cache->count;
cache->count_since_key_frame = 0;
}
// Update prev_canvas by simply copying from 'curr_canvas'.
CopyPixels(&cache->curr_canvas, prev_canvas);
}
}
DisposeFrame(info->dispose_method, &orig_rect, frame, prev_canvas);
cache->is_first_frame = 0;
ok = 1;
End:
WebPPictureFree(&sub_image);
if (!ok) {
FrameRelease(encoded_frame);
--cache->count; // We reset the count, as the frame addition failed.
}
frame->error_code = error_code; // report error_code
assert(ok || error_code != VP8_ENC_OK);
return ok;
}
WebPMuxError WebPFrameCacheFlush(WebPFrameCache* const cache, int verbose,
WebPMux* const mux) {
while (cache->flush_count > 0) {
WebPMuxFrameInfo* info;
WebPMuxError err;
EncodedFrame* const curr = CacheGetFrame(cache, 0);
// Pick frame or full canvas.
if (cache->keyframe == 0) {
info = &curr->key_frame;
info->blend_method = WEBP_MUX_NO_BLEND;
cache->keyframe = KEYFRAME_NONE;
cache->best_delta = DELTA_INFINITY;
} else {
info = &curr->sub_frame;
info->blend_method = WEBP_MUX_BLEND;
}
// Add to mux.
err = WebPMuxPushFrame(mux, info, 1);
if (err != WEBP_MUX_OK) return err;
if (verbose) {
printf("Added frame. offset:%d,%d duration:%d dispose:%d blend:%d\n",
info->x_offset, info->y_offset, info->duration,
info->dispose_method, info->blend_method);
}
FrameRelease(curr);
++cache->start;
--cache->flush_count;
--cache->count;
if (cache->keyframe != KEYFRAME_NONE) --cache->keyframe;
}
if (cache->count == 0) CacheReset(cache);
return WEBP_MUX_OK;
}
WebPMuxError WebPFrameCacheFlushAll(WebPFrameCache* const cache, int verbose,
WebPMux* const mux) {
cache->flush_count = cache->count; // Force flushing of all frames.
return WebPFrameCacheFlush(cache, verbose, mux);
}
//------------------------------------------------------------------------------

81
examples/gif2webp_util.h Normal file
View File

@ -0,0 +1,81 @@
// Copyright 2013 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.
// -----------------------------------------------------------------------------
//
// Helper structs and methods for gif2webp tool.
//
// Author: Urvang (urvang@google.com)
#ifndef WEBP_EXAMPLES_GIF2WEBP_UTIL_H_
#define WEBP_EXAMPLES_GIF2WEBP_UTIL_H_
#include <stdlib.h>
#include "webp/mux.h"
#ifdef __cplusplus
extern "C" {
#endif
//------------------------------------------------------------------------------
// Helper utilities.
#define WEBP_UTIL_TRANSPARENT_COLOR 0x00ffffff
struct WebPPicture;
typedef struct {
int x_offset, y_offset, width, height;
} WebPFrameRect;
// Clear pixels in 'picture' within given 'rect' to transparent color.
void WebPUtilClearPic(struct WebPPicture* const picture,
const WebPFrameRect* const rect);
//------------------------------------------------------------------------------
// Frame cache.
typedef struct WebPFrameCache WebPFrameCache;
// Given the minimum distance between key frames 'kmin' and maximum distance
// between key frames 'kmax', returns an appropriately allocated cache object.
// If 'allow_mixed' is true, the subsequent calls to WebPFrameCacheAddFrame()
// will heuristically pick lossy or lossless compression for each frame.
// Use WebPFrameCacheDelete() to deallocate the 'cache'.
WebPFrameCache* WebPFrameCacheNew(int width, int height,
size_t kmin, size_t kmax, int allow_mixed);
// Release all the frame data from 'cache' and free 'cache'.
void WebPFrameCacheDelete(WebPFrameCache* const cache);
// Given an image described by 'frame', 'info' and 'orig_rect', optimize it for
// WebP, encode it and add it to 'cache'. 'orig_rect' can be NULL.
// This takes care of frame disposal too, according to 'info->dispose_method'.
// Returns false in case of error (and sets frame->error_code accordingly).
int WebPFrameCacheAddFrame(WebPFrameCache* const cache,
const WebPConfig* const config,
const WebPFrameRect* const orig_rect,
WebPPicture* const frame,
WebPMuxFrameInfo* const info);
// Flush the *ready* frames from cache and add them to 'mux'. If 'verbose' is
// true, prints the information about these frames.
WebPMuxError WebPFrameCacheFlush(WebPFrameCache* const cache, int verbose,
WebPMux* const mux);
// Similar to 'WebPFrameCacheFlushFrames()', but flushes *all* the frames.
WebPMuxError WebPFrameCacheFlushAll(WebPFrameCache* const cache, int verbose,
WebPMux* const mux);
//------------------------------------------------------------------------------
#ifdef __cplusplus
} // extern "C"
#endif
#endif // WEBP_EXAMPLES_GIF2WEBP_UTIL_H_

295
examples/jpegdec.c Normal file
View File

@ -0,0 +1,295 @@
// Copyright 2012 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.
// -----------------------------------------------------------------------------
//
// JPEG decode.
#include "./jpegdec.h"
#ifdef HAVE_CONFIG_H
#include "webp/config.h"
#endif
#include <stdio.h>
#ifdef WEBP_HAVE_JPEG
#include <jpeglib.h>
#include <setjmp.h>
#include <stdlib.h>
#include <string.h>
#include "webp/encode.h"
#include "./metadata.h"
// -----------------------------------------------------------------------------
// Metadata processing
#ifndef JPEG_APP1
# define JPEG_APP1 (JPEG_APP0 + 1)
#endif
#ifndef JPEG_APP2
# define JPEG_APP2 (JPEG_APP0 + 2)
#endif
typedef struct {
const uint8_t* data;
size_t data_length;
int seq; // this segment's sequence number [1, 255] for use in reassembly.
} ICCPSegment;
static void SaveMetadataMarkers(j_decompress_ptr dinfo) {
const unsigned int max_marker_length = 0xffff;
jpeg_save_markers(dinfo, JPEG_APP1, max_marker_length); // Exif/XMP
jpeg_save_markers(dinfo, JPEG_APP2, max_marker_length); // ICC profile
}
static int CompareICCPSegments(const void* a, const void* b) {
const ICCPSegment* s1 = (const ICCPSegment*)a;
const ICCPSegment* s2 = (const ICCPSegment*)b;
return s1->seq - s2->seq;
}
// Extract ICC profile segments from the marker list in 'dinfo', reassembling
// and storing them in 'iccp'.
// Returns true on success and false for memory errors and corrupt profiles.
static int StoreICCP(j_decompress_ptr dinfo, MetadataPayload* const iccp) {
// ICC.1:2010-12 (4.3.0.0) Annex B.4 Embedding ICC Profiles in JPEG files
static const char kICCPSignature[] = "ICC_PROFILE";
static const size_t kICCPSignatureLength = 12; // signature includes '\0'
static const size_t kICCPSkipLength = 14; // signature + seq & count
int expected_count = 0;
int actual_count = 0;
int seq_max = 0;
size_t total_size = 0;
ICCPSegment iccp_segments[255];
jpeg_saved_marker_ptr marker;
memset(iccp_segments, 0, sizeof(iccp_segments));
for (marker = dinfo->marker_list; marker != NULL; marker = marker->next) {
if (marker->marker == JPEG_APP2 &&
marker->data_length > kICCPSkipLength &&
!memcmp(marker->data, kICCPSignature, kICCPSignatureLength)) {
// ICC_PROFILE\0<seq><count>; 'seq' starts at 1.
const int seq = marker->data[kICCPSignatureLength];
const int count = marker->data[kICCPSignatureLength + 1];
const size_t segment_size = marker->data_length - kICCPSkipLength;
ICCPSegment* segment;
if (segment_size == 0 || count == 0 || seq == 0) {
fprintf(stderr, "[ICCP] size (%d) / count (%d) / sequence number (%d)"
" cannot be 0!\n",
(int)segment_size, seq, count);
return 0;
}
if (expected_count == 0) {
expected_count = count;
} else if (expected_count != count) {
fprintf(stderr, "[ICCP] Inconsistent segment count (%d / %d)!\n",
expected_count, count);
return 0;
}
segment = iccp_segments + seq - 1;
if (segment->data_length != 0) {
fprintf(stderr, "[ICCP] Duplicate segment number (%d)!\n" , seq);
return 0;
}
segment->data = marker->data + kICCPSkipLength;
segment->data_length = segment_size;
segment->seq = seq;
total_size += segment_size;
if (seq > seq_max) seq_max = seq;
++actual_count;
}
}
if (actual_count == 0) return 1;
if (seq_max != actual_count) {
fprintf(stderr, "[ICCP] Discontinuous segments, expected: %d actual: %d!\n",
actual_count, seq_max);
return 0;
}
if (expected_count != actual_count) {
fprintf(stderr, "[ICCP] Segment count: %d does not match expected: %d!\n",
actual_count, expected_count);
return 0;
}
// The segments may appear out of order in the file, sort them based on
// sequence number before assembling the payload.
qsort(iccp_segments, actual_count, sizeof(*iccp_segments),
CompareICCPSegments);
iccp->bytes = (uint8_t*)malloc(total_size);
if (iccp->bytes == NULL) return 0;
iccp->size = total_size;
{
int i;
size_t offset = 0;
for (i = 0; i < seq_max; ++i) {
memcpy(iccp->bytes + offset,
iccp_segments[i].data, iccp_segments[i].data_length);
offset += iccp_segments[i].data_length;
}
}
return 1;
}
// Returns true on success and false for memory errors and corrupt profiles.
// The caller must use MetadataFree() on 'metadata' in all cases.
static int ExtractMetadataFromJPEG(j_decompress_ptr dinfo,
Metadata* const metadata) {
static const struct {
int marker;
const char* signature;
size_t signature_length;
size_t storage_offset;
} kJPEGMetadataMap[] = {
// Exif 2.2 Section 4.7.2 Interoperability Structure of APP1 ...
{ JPEG_APP1, "Exif\0", 6, METADATA_OFFSET(exif) },
// XMP Specification Part 3 Section 3 Embedding XMP Metadata ... #JPEG
// TODO(jzern) Add support for 'ExtendedXMP'
{ JPEG_APP1, "http://ns.adobe.com/xap/1.0/", 29, METADATA_OFFSET(xmp) },
{ 0, NULL, 0, 0 },
};
jpeg_saved_marker_ptr marker;
// Treat ICC profiles separately as they may be segmented and out of order.
if (!StoreICCP(dinfo, &metadata->iccp)) return 0;
for (marker = dinfo->marker_list; marker != NULL; marker = marker->next) {
int i;
for (i = 0; kJPEGMetadataMap[i].marker != 0; ++i) {
if (marker->marker == kJPEGMetadataMap[i].marker &&
marker->data_length > kJPEGMetadataMap[i].signature_length &&
!memcmp(marker->data, kJPEGMetadataMap[i].signature,
kJPEGMetadataMap[i].signature_length)) {
MetadataPayload* const payload =
(MetadataPayload*)((uint8_t*)metadata +
kJPEGMetadataMap[i].storage_offset);
if (payload->bytes == NULL) {
const char* marker_data = (const char*)marker->data +
kJPEGMetadataMap[i].signature_length;
const size_t marker_data_length =
marker->data_length - kJPEGMetadataMap[i].signature_length;
if (!MetadataCopy(marker_data, marker_data_length, payload)) return 0;
} else {
fprintf(stderr, "Ignoring additional '%s' marker\n",
kJPEGMetadataMap[i].signature);
}
}
}
}
return 1;
}
#undef JPEG_APP1
#undef JPEG_APP2
// -----------------------------------------------------------------------------
// JPEG decoding
struct my_error_mgr {
struct jpeg_error_mgr pub;
jmp_buf setjmp_buffer;
};
static void my_error_exit(j_common_ptr dinfo) {
struct my_error_mgr* myerr = (struct my_error_mgr*)dinfo->err;
dinfo->err->output_message(dinfo);
longjmp(myerr->setjmp_buffer, 1);
}
int ReadJPEG(FILE* in_file, WebPPicture* const pic, Metadata* const metadata) {
int ok = 0;
int stride, width, height;
volatile struct jpeg_decompress_struct dinfo;
struct my_error_mgr jerr;
uint8_t* volatile rgb = NULL;
JSAMPROW buffer[1];
memset((j_decompress_ptr)&dinfo, 0, sizeof(dinfo)); // for setjmp sanity
dinfo.err = jpeg_std_error(&jerr.pub);
jerr.pub.error_exit = my_error_exit;
if (setjmp(jerr.setjmp_buffer)) {
Error:
MetadataFree(metadata);
jpeg_destroy_decompress((j_decompress_ptr)&dinfo);
goto End;
}
jpeg_create_decompress((j_decompress_ptr)&dinfo);
jpeg_stdio_src((j_decompress_ptr)&dinfo, in_file);
if (metadata != NULL) SaveMetadataMarkers((j_decompress_ptr)&dinfo);
jpeg_read_header((j_decompress_ptr)&dinfo, TRUE);
dinfo.out_color_space = JCS_RGB;
dinfo.do_fancy_upsampling = TRUE;
jpeg_start_decompress((j_decompress_ptr)&dinfo);
if (dinfo.output_components != 3) {
goto Error;
}
width = dinfo.output_width;
height = dinfo.output_height;
stride = dinfo.output_width * dinfo.output_components * sizeof(*rgb);
rgb = (uint8_t*)malloc(stride * height);
if (rgb == NULL) {
goto End;
}
buffer[0] = (JSAMPLE*)rgb;
while (dinfo.output_scanline < dinfo.output_height) {
if (jpeg_read_scanlines((j_decompress_ptr)&dinfo, buffer, 1) != 1) {
goto End;
}
buffer[0] += stride;
}
if (metadata != NULL) {
ok = ExtractMetadataFromJPEG((j_decompress_ptr)&dinfo, metadata);
if (!ok) {
fprintf(stderr, "Error extracting JPEG metadata!\n");
goto Error;
}
}
jpeg_finish_decompress((j_decompress_ptr)&dinfo);
jpeg_destroy_decompress((j_decompress_ptr)&dinfo);
// WebP conversion.
pic->width = width;
pic->height = height;
pic->use_argb = 1; // store raw RGB samples
ok = WebPPictureImportRGB(pic, rgb, stride);
if (!ok) goto Error;
End:
free(rgb);
return ok;
}
#else // !WEBP_HAVE_JPEG
int ReadJPEG(FILE* in_file, struct WebPPicture* const pic,
struct Metadata* const metadata) {
(void)in_file;
(void)pic;
(void)metadata;
fprintf(stderr, "JPEG support not compiled. Please install the libjpeg "
"development package before building.\n");
return 0;
}
#endif // WEBP_HAVE_JPEG
// -----------------------------------------------------------------------------

35
examples/jpegdec.h Normal file
View File

@ -0,0 +1,35 @@
// Copyright 2012 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.
// -----------------------------------------------------------------------------
//
// JPEG decode.
#ifndef WEBP_EXAMPLES_JPEGDEC_H_
#define WEBP_EXAMPLES_JPEGDEC_H_
#include <stdio.h>
#include "webp/types.h"
#ifdef __cplusplus
extern "C" {
#endif
struct Metadata;
struct WebPPicture;
// Reads a JPEG from 'in_file', returning the decoded output in 'pic'.
// The output is RGB.
// Returns true on success.
int ReadJPEG(FILE* in_file, struct WebPPicture* const pic,
struct Metadata* const metadata);
#ifdef __cplusplus
} // extern "C"
#endif
#endif // WEBP_EXAMPLES_JPEGDEC_H_

49
examples/metadata.c Normal file
View File

@ -0,0 +1,49 @@
// Copyright 2012 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.
// -----------------------------------------------------------------------------
//
// Metadata types and functions.
//
#include "./metadata.h"
#include <stdlib.h>
#include <string.h>
#include "webp/types.h"
void MetadataInit(Metadata* const metadata) {
if (metadata == NULL) return;
memset(metadata, 0, sizeof(*metadata));
}
void MetadataPayloadDelete(MetadataPayload* const payload) {
if (payload == NULL) return;
free(payload->bytes);
payload->bytes = NULL;
payload->size = 0;
}
void MetadataFree(Metadata* const metadata) {
if (metadata == NULL) return;
MetadataPayloadDelete(&metadata->exif);
MetadataPayloadDelete(&metadata->iccp);
MetadataPayloadDelete(&metadata->xmp);
}
int MetadataCopy(const char* metadata, size_t metadata_len,
MetadataPayload* const payload) {
if (metadata == NULL || metadata_len == 0 || payload == NULL) return 0;
payload->bytes = (uint8_t*)malloc(metadata_len);
if (payload->bytes == NULL) return 0;
payload->size = metadata_len;
memcpy(payload->bytes, metadata, metadata_len);
return 1;
}
// -----------------------------------------------------------------------------

47
examples/metadata.h Normal file
View File

@ -0,0 +1,47 @@
// Copyright 2012 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.
// -----------------------------------------------------------------------------
//
// Metadata types and functions.
//
#ifndef WEBP_EXAMPLES_METADATA_H_
#define WEBP_EXAMPLES_METADATA_H_
#include "webp/types.h"
#ifdef __cplusplus
extern "C" {
#endif
typedef struct MetadataPayload {
uint8_t* bytes;
size_t size;
} MetadataPayload;
typedef struct Metadata {
MetadataPayload exif;
MetadataPayload iccp;
MetadataPayload xmp;
} Metadata;
#define METADATA_OFFSET(x) offsetof(Metadata, x)
void MetadataInit(Metadata* const metadata);
void MetadataPayloadDelete(MetadataPayload* const payload);
void MetadataFree(Metadata* const metadata);
// Stores 'metadata' to 'payload->bytes', returns false on allocation error.
int MetadataCopy(const char* metadata, size_t metadata_len,
MetadataPayload* const payload);
#ifdef __cplusplus
} // extern "C"
#endif
#endif // WEBP_EXAMPLES_METADATA_H_

302
examples/pngdec.c Normal file
View File

@ -0,0 +1,302 @@
// Copyright 2012 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.
// -----------------------------------------------------------------------------
//
// PNG decode.
#include "./pngdec.h"
#ifdef HAVE_CONFIG_H
#include "webp/config.h"
#endif
#include <stdio.h>
#ifdef WEBP_HAVE_PNG
#include <png.h>
#include <setjmp.h> // note: this must be included *after* png.h
#include <stdlib.h>
#include <string.h>
#include "webp/encode.h"
#include "./metadata.h"
static void PNGAPI error_function(png_structp png, png_const_charp error) {
if (error != NULL) fprintf(stderr, "libpng error: %s\n", error);
longjmp(png_jmpbuf(png), 1);
}
// Converts the NULL terminated 'hexstring' which contains 2-byte character
// representations of hex values to raw data.
// 'hexstring' may contain values consisting of [A-F][a-f][0-9] in pairs,
// e.g., 7af2..., separated by any number of newlines.
// 'expected_length' is the anticipated processed size.
// On success the raw buffer is returned with its length equivalent to
// 'expected_length'. NULL is returned if the processed length is less than
// 'expected_length' or any character aside from those above is encountered.
// The returned buffer must be freed by the caller.
static uint8_t* HexStringToBytes(const char* hexstring,
size_t expected_length) {
const char* src = hexstring;
size_t actual_length = 0;
uint8_t* const raw_data = (uint8_t*)malloc(expected_length);
uint8_t* dst;
if (raw_data == NULL) return NULL;
for (dst = raw_data; actual_length < expected_length && *src != '\0'; ++src) {
char* end;
char val[3];
if (*src == '\n') continue;
val[0] = *src++;
val[1] = *src;
val[2] = '\0';
*dst++ = (uint8_t)strtol(val, &end, 16);
if (end != val + 2) break;
++actual_length;
}
if (actual_length != expected_length) {
free(raw_data);
return NULL;
}
return raw_data;
}
static int ProcessRawProfile(const char* profile, size_t profile_len,
MetadataPayload* const payload) {
const char* src = profile;
char* end;
int expected_length;
if (profile == NULL || profile_len == 0) return 0;
// ImageMagick formats 'raw profiles' as
// '\n<name>\n<length>(%8lu)\n<hex payload>\n'.
if (*src != '\n') {
fprintf(stderr, "Malformed raw profile, expected '\\n' got '\\x%.2X'\n",
*src);
return 0;
}
++src;
// skip the profile name and extract the length.
while (*src != '\0' && *src++ != '\n') {}
expected_length = (int)strtol(src, &end, 10);
if (*end != '\n') {
fprintf(stderr, "Malformed raw profile, expected '\\n' got '\\x%.2X'\n",
*end);
return 0;
}
++end;
// 'end' now points to the profile payload.
payload->bytes = HexStringToBytes(end, expected_length);
if (payload->bytes == NULL) return 0;
payload->size = expected_length;
return 1;
}
static const struct {
const char* name;
int (*process)(const char* profile, size_t profile_len,
MetadataPayload* const payload);
size_t storage_offset;
} kPNGMetadataMap[] = {
// http://www.sno.phy.queensu.ca/~phil/exiftool/TagNames/PNG.html#TextualData
// See also: ExifTool on CPAN.
{ "Raw profile type exif", ProcessRawProfile, METADATA_OFFSET(exif) },
{ "Raw profile type xmp", ProcessRawProfile, METADATA_OFFSET(xmp) },
// Exiftool puts exif data in APP1 chunk, too.
{ "Raw profile type APP1", ProcessRawProfile, METADATA_OFFSET(exif) },
// XMP Specification Part 3, Section 3 #PNG
{ "XML:com.adobe.xmp", MetadataCopy, METADATA_OFFSET(xmp) },
{ NULL, NULL, 0 },
};
// Looks for metadata at both the beginning and end of the PNG file, giving
// preference to the head.
// Returns true on success. The caller must use MetadataFree() on 'metadata' in
// all cases.
static int ExtractMetadataFromPNG(png_structp png,
png_infop const head_info,
png_infop const end_info,
Metadata* const metadata) {
int p;
for (p = 0; p < 2; ++p) {
png_infop const info = (p == 0) ? head_info : end_info;
png_textp text = NULL;
const int num = png_get_text(png, info, &text, NULL);
int i;
// Look for EXIF / XMP metadata.
for (i = 0; i < num; ++i, ++text) {
int j;
for (j = 0; kPNGMetadataMap[j].name != NULL; ++j) {
if (!strcmp(text->key, kPNGMetadataMap[j].name)) {
MetadataPayload* const payload =
(MetadataPayload*)((uint8_t*)metadata +
kPNGMetadataMap[j].storage_offset);
png_size_t text_length;
switch (text->compression) {
#ifdef PNG_iTXt_SUPPORTED
case PNG_ITXT_COMPRESSION_NONE:
case PNG_ITXT_COMPRESSION_zTXt:
text_length = text->itxt_length;
break;
#endif
case PNG_TEXT_COMPRESSION_NONE:
case PNG_TEXT_COMPRESSION_zTXt:
default:
text_length = text->text_length;
break;
}
if (payload->bytes != NULL) {
fprintf(stderr, "Ignoring additional '%s'\n", text->key);
} else if (!kPNGMetadataMap[j].process(text->text, text_length,
payload)) {
fprintf(stderr, "Failed to process: '%s'\n", text->key);
return 0;
}
break;
}
}
}
// Look for an ICC profile.
{
png_charp name;
int comp_type;
#if ((PNG_LIBPNG_VER_MAJOR << 8) | PNG_LIBPNG_VER_MINOR << 0) < \
((1 << 8) | (5 << 0))
png_charp profile;
#else // >= libpng 1.5.0
png_bytep profile;
#endif
png_uint_32 len;
if (png_get_iCCP(png, info,
&name, &comp_type, &profile, &len) == PNG_INFO_iCCP) {
if (!MetadataCopy((const char*)profile, len, &metadata->iccp)) return 0;
}
}
}
return 1;
}
int ReadPNG(FILE* in_file, WebPPicture* const pic, int keep_alpha,
Metadata* const metadata) {
volatile png_structp png;
volatile png_infop info = NULL;
volatile png_infop end_info = NULL;
int color_type, bit_depth, interlaced;
int has_alpha;
int num_passes;
int p;
int ok = 0;
png_uint_32 width, height, y;
int stride;
uint8_t* volatile rgb = NULL;
png = png_create_read_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0);
if (png == NULL) {
goto End;
}
png_set_error_fn(png, 0, error_function, NULL);
if (setjmp(png_jmpbuf(png))) {
Error:
MetadataFree(metadata);
goto End;
}
info = png_create_info_struct(png);
if (info == NULL) goto Error;
end_info = png_create_info_struct(png);
if (end_info == NULL) goto Error;
png_init_io(png, in_file);
png_read_info(png, info);
if (!png_get_IHDR(png, info,
&width, &height, &bit_depth, &color_type, &interlaced,
NULL, NULL)) goto Error;
png_set_strip_16(png);
png_set_packing(png);
if (color_type == PNG_COLOR_TYPE_PALETTE) {
png_set_palette_to_rgb(png);
}
if (color_type == PNG_COLOR_TYPE_GRAY ||
color_type == PNG_COLOR_TYPE_GRAY_ALPHA) {
if (bit_depth < 8) {
png_set_expand_gray_1_2_4_to_8(png);
}
png_set_gray_to_rgb(png);
}
if (png_get_valid(png, info, PNG_INFO_tRNS)) {
png_set_tRNS_to_alpha(png);
has_alpha = 1;
} else {
has_alpha = !!(color_type & PNG_COLOR_MASK_ALPHA);
}
if (!keep_alpha) {
png_set_strip_alpha(png);
has_alpha = 0;
}
num_passes = png_set_interlace_handling(png);
png_read_update_info(png, info);
stride = (has_alpha ? 4 : 3) * width * sizeof(*rgb);
rgb = (uint8_t*)malloc(stride * height);
if (rgb == NULL) goto Error;
for (p = 0; p < num_passes; ++p) {
for (y = 0; y < height; ++y) {
png_bytep row = (png_bytep)(rgb + y * stride);
png_read_rows(png, &row, NULL, 1);
}
}
png_read_end(png, end_info);
if (metadata != NULL &&
!ExtractMetadataFromPNG(png, info, end_info, metadata)) {
fprintf(stderr, "Error extracting PNG metadata!\n");
goto Error;
}
pic->width = width;
pic->height = height;
pic->use_argb = 1;
ok = has_alpha ? WebPPictureImportRGBA(pic, rgb, stride)
: WebPPictureImportRGB(pic, rgb, stride);
if (!ok) {
goto Error;
}
End:
if (png != NULL) {
png_destroy_read_struct((png_structpp)&png,
(png_infopp)&info, (png_infopp)&end_info);
}
free(rgb);
return ok;
}
#else // !WEBP_HAVE_PNG
int ReadPNG(FILE* in_file, struct WebPPicture* const pic, int keep_alpha,
struct Metadata* const metadata) {
(void)in_file;
(void)pic;
(void)keep_alpha;
(void)metadata;
fprintf(stderr, "PNG support not compiled. Please install the libpng "
"development package before building.\n");
return 0;
}
#endif // WEBP_HAVE_PNG
// -----------------------------------------------------------------------------

35
examples/pngdec.h Normal file
View File

@ -0,0 +1,35 @@
// Copyright 2012 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.
// -----------------------------------------------------------------------------
//
// PNG decode.
#ifndef WEBP_EXAMPLES_PNGDEC_H_
#define WEBP_EXAMPLES_PNGDEC_H_
#include <stdio.h>
#ifdef __cplusplus
extern "C" {
#endif
struct Metadata;
struct WebPPicture;
// Reads a PNG from 'in_file', returning the decoded output in 'pic'.
// If 'keep_alpha' is true and the PNG has an alpha channel, the output is RGBA
// otherwise it will be RGB.
// Returns true on success.
int ReadPNG(FILE* in_file, struct WebPPicture* const pic, int keep_alpha,
struct Metadata* const metadata);
#ifdef __cplusplus
} // extern "C"
#endif
#endif // WEBP_EXAMPLES_PNGDEC_H_

View File

@ -1,8 +1,10 @@
// Copyright 2011 Google Inc.
// Copyright 2011 Google Inc. All Rights Reserved.
//
// This code is licensed under the same terms as WebM:
// Software License Agreement: http://www.webmproject.org/license/software/
// Additional IP Rights Grant: http://www.webmproject.org/license/additional/
// 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.
// -----------------------------------------------------------------------------
//
// Helper functions to measure elapsed time.
@ -12,12 +14,16 @@
#ifndef WEBP_EXAMPLES_STOPWATCH_H_
#define WEBP_EXAMPLES_STOPWATCH_H_
#ifdef _WIN32
#if defined _WIN32 && !defined __GNUC__
#include <windows.h>
typedef LARGE_INTEGER Stopwatch;
static inline double StopwatchReadAndReset(Stopwatch* watch) {
static WEBP_INLINE void StopwatchReset(Stopwatch* watch) {
QueryPerformanceCounter(watch);
}
static WEBP_INLINE double StopwatchReadAndReset(Stopwatch* watch) {
const LARGE_INTEGER old_value = *watch;
LARGE_INTEGER freq;
if (!QueryPerformanceCounter(watch))
@ -30,18 +36,25 @@ static inline double StopwatchReadAndReset(Stopwatch* watch) {
}
#else // !_WIN32
#else /* !_WIN32 */
#include <sys/time.h>
typedef struct timeval Stopwatch;
static inline double StopwatchReadAndReset(Stopwatch* watch) {
const struct timeval old_value = *watch;
static WEBP_INLINE void StopwatchReset(Stopwatch* watch) {
gettimeofday(watch, NULL);
return watch->tv_sec - old_value.tv_sec +
(watch->tv_usec - old_value.tv_usec) / 1000000.0;
}
#endif // !_WIN32
static WEBP_INLINE double StopwatchReadAndReset(Stopwatch* watch) {
struct timeval old_value;
double delta_sec, delta_usec;
memcpy(&old_value, watch, sizeof(old_value));
gettimeofday(watch, NULL);
delta_sec = (double)watch->tv_sec - old_value.tv_sec;
delta_usec = (double)watch->tv_usec - old_value.tv_usec;
return delta_sec + delta_usec / 1000000.0;
}
#endif // WEBP_EXAMPLES_STOPWATCH_H_
#endif /* _WIN32 */
#endif /* WEBP_EXAMPLES_STOPWATCH_H_ */

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.8 KiB

After

Width:  |  Height:  |  Size: 4.8 KiB

141
examples/tiffdec.c Normal file
View File

@ -0,0 +1,141 @@
// Copyright 2012 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.
// -----------------------------------------------------------------------------
//
// TIFF decode.
#include "./tiffdec.h"
#ifdef HAVE_CONFIG_H
#include "webp/config.h"
#endif
#include <stdio.h>
#ifdef WEBP_HAVE_TIFF
#include <tiffio.h>
#include "webp/encode.h"
#include "./metadata.h"
static const struct {
ttag_t tag;
size_t storage_offset;
} kTIFFMetadataMap[] = {
{ TIFFTAG_ICCPROFILE, METADATA_OFFSET(iccp) },
{ TIFFTAG_XMLPACKET, METADATA_OFFSET(xmp) },
{ 0, 0 },
};
// Returns true on success. The caller must use MetadataFree() on 'metadata' in
// all cases.
static int ExtractMetadataFromTIFF(TIFF* const tif, Metadata* const metadata) {
int i;
toff_t exif_ifd_offset;
for (i = 0; kTIFFMetadataMap[i].tag != 0; ++i) {
MetadataPayload* const payload =
(MetadataPayload*)((uint8_t*)metadata +
kTIFFMetadataMap[i].storage_offset);
void* tag_data;
uint32 tag_data_len;
if (TIFFGetField(tif, kTIFFMetadataMap[i].tag, &tag_data_len, &tag_data) &&
!MetadataCopy((const char*)tag_data, tag_data_len, payload)) {
return 0;
}
}
// TODO(jzern): To extract the raw EXIF directory some parsing of it would be
// necessary to determine the overall size. In addition, value offsets in
// individual directory entries may need to be updated as, depending on the
// type, they are file based.
// Exif 2.2 Section 4.6.2 Tag Structure
// TIFF Revision 6.0 Part 1 Section 2 TIFF Structure #Image File Directory
if (TIFFGetField(tif, TIFFTAG_EXIFIFD, &exif_ifd_offset)) {
fprintf(stderr, "Warning: EXIF extraction from TIFF is unsupported.\n");
}
return 1;
}
int ReadTIFF(const char* const filename,
WebPPicture* const pic, int keep_alpha,
Metadata* const metadata) {
TIFF* const tif = TIFFOpen(filename, "r");
uint32 width, height;
uint32* raster;
int ok = 0;
tdir_t dircount;
if (tif == NULL) {
fprintf(stderr, "Error! Cannot open TIFF file '%s'\n", filename);
return 0;
}
dircount = TIFFNumberOfDirectories(tif);
if (dircount > 1) {
fprintf(stderr, "Warning: multi-directory TIFF files are not supported.\n"
"Only the first will be used, %d will be ignored.\n",
dircount - 1);
}
if (!(TIFFGetField(tif, TIFFTAG_IMAGEWIDTH, &width) &&
TIFFGetField(tif, TIFFTAG_IMAGELENGTH, &height))) {
fprintf(stderr, "Error! Cannot retrieve TIFF image dimensions.\n");
return 0;
}
raster = (uint32*)_TIFFmalloc(width * height * sizeof(*raster));
if (raster != NULL) {
if (TIFFReadRGBAImageOriented(tif, width, height, raster,
ORIENTATION_TOPLEFT, 1)) {
const int stride = width * sizeof(*raster);
pic->width = width;
pic->height = height;
// TIFF data is ABGR
#ifdef WORDS_BIGENDIAN
TIFFSwabArrayOfLong(raster, width * height);
#endif
pic->use_argb = 1;
ok = keep_alpha
? WebPPictureImportRGBA(pic, (const uint8_t*)raster, stride)
: WebPPictureImportRGBX(pic, (const uint8_t*)raster, stride);
}
_TIFFfree(raster);
} else {
fprintf(stderr, "Error allocating TIFF RGBA memory!\n");
}
if (ok) {
if (metadata != NULL) {
ok = ExtractMetadataFromTIFF(tif, metadata);
if (!ok) {
fprintf(stderr, "Error extracting TIFF metadata!\n");
MetadataFree(metadata);
WebPPictureFree(pic);
}
}
}
TIFFClose(tif);
return ok;
}
#else // !WEBP_HAVE_TIFF
int ReadTIFF(const char* const filename,
struct WebPPicture* const pic, int keep_alpha,
struct Metadata* const metadata) {
(void)filename;
(void)pic;
(void)keep_alpha;
(void)metadata;
fprintf(stderr, "TIFF support not compiled. Please install the libtiff "
"development package before building.\n");
return 0;
}
#endif // WEBP_HAVE_TIFF
// -----------------------------------------------------------------------------

34
examples/tiffdec.h Normal file
View File

@ -0,0 +1,34 @@
// Copyright 2012 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.
// -----------------------------------------------------------------------------
//
// TIFF decode.
#ifndef WEBP_EXAMPLES_TIFFDEC_H_
#define WEBP_EXAMPLES_TIFFDEC_H_
#ifdef __cplusplus
extern "C" {
#endif
struct Metadata;
struct WebPPicture;
// Reads a TIFF from 'filename', returning the decoded output in 'pic'.
// If 'keep_alpha' is true and the TIFF has an alpha channel, the output is RGBA
// otherwise it will be RGB.
// Returns true on success.
int ReadTIFF(const char* const filename,
struct WebPPicture* const pic, int keep_alpha,
struct Metadata* const metadata);
#ifdef __cplusplus
} // extern "C"
#endif
#endif // WEBP_EXAMPLES_TIFFDEC_H_

553
examples/vwebp.c Normal file
View File

@ -0,0 +1,553 @@
// Copyright 2011 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.
// -----------------------------------------------------------------------------
//
// Simple OpenGL-based WebP file viewer.
//
// Author: Skal (pascal.massimino@gmail.com)
#ifdef HAVE_CONFIG_H
#include "webp/config.h"
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#if defined(WEBP_HAVE_GL)
#if defined(HAVE_GLUT_GLUT_H)
#include <GLUT/glut.h>
#else
#include <GL/glut.h>
#ifdef FREEGLUT
#include <GL/freeglut.h>
#endif
#endif
#ifdef WEBP_HAVE_QCMS
#include <qcms.h>
#endif
#include "webp/decode.h"
#include "webp/demux.h"
#include "./example_util.h"
#ifdef _MSC_VER
#define snprintf _snprintf
#endif
static void Help(void);
// Unfortunate global variables. Gathered into a struct for comfort.
static struct {
int has_animation;
int has_color_profile;
int done;
int decoding_error;
int print_info;
int use_color_profile;
int canvas_width, canvas_height;
int loop_count;
uint32_t bg_color;
const char* file_name;
WebPData data;
WebPDecoderConfig config;
const WebPDecBuffer* pic;
WebPDemuxer* dmux;
WebPIterator curr_frame;
WebPIterator prev_frame;
WebPChunkIterator iccp;
} kParams;
static void ClearPreviousPic(void) {
WebPFreeDecBuffer((WebPDecBuffer*)kParams.pic);
kParams.pic = NULL;
}
static void ClearParams(void) {
ClearPreviousPic();
WebPDataClear(&kParams.data);
WebPDemuxReleaseIterator(&kParams.curr_frame);
WebPDemuxReleaseIterator(&kParams.prev_frame);
WebPDemuxReleaseChunkIterator(&kParams.iccp);
WebPDemuxDelete(kParams.dmux);
kParams.dmux = NULL;
}
// -----------------------------------------------------------------------------
// Color profile handling
static int ApplyColorProfile(const WebPData* const profile,
WebPDecBuffer* const rgba) {
#ifdef WEBP_HAVE_QCMS
int i, ok = 0;
uint8_t* line;
uint8_t major_revision;
qcms_profile* input_profile = NULL;
qcms_profile* output_profile = NULL;
qcms_transform* transform = NULL;
const qcms_data_type input_type = QCMS_DATA_RGBA_8;
const qcms_data_type output_type = QCMS_DATA_RGBA_8;
const qcms_intent intent = QCMS_INTENT_DEFAULT;
if (profile == NULL || rgba == NULL) return 0;
if (profile->bytes == NULL || profile->size < 10) return 1;
major_revision = profile->bytes[8];
qcms_enable_iccv4();
input_profile = qcms_profile_from_memory(profile->bytes, profile->size);
// qcms_profile_is_bogus() is broken with ICCv4.
if (input_profile == NULL ||
(major_revision < 4 && qcms_profile_is_bogus(input_profile))) {
fprintf(stderr, "Color profile is bogus!\n");
goto Error;
}
output_profile = qcms_profile_sRGB();
if (output_profile == NULL) {
fprintf(stderr, "Error creating output color profile!\n");
goto Error;
}
qcms_profile_precache_output_transform(output_profile);
transform = qcms_transform_create(input_profile, input_type,
output_profile, output_type,
intent);
if (transform == NULL) {
fprintf(stderr, "Error creating color transform!\n");
goto Error;
}
line = rgba->u.RGBA.rgba;
for (i = 0; i < rgba->height; ++i, line += rgba->u.RGBA.stride) {
qcms_transform_data(transform, line, line, rgba->width);
}
ok = 1;
Error:
if (input_profile != NULL) qcms_profile_release(input_profile);
if (output_profile != NULL) qcms_profile_release(output_profile);
if (transform != NULL) qcms_transform_release(transform);
return ok;
#else
(void)profile;
(void)rgba;
return 1;
#endif // WEBP_HAVE_QCMS
}
//------------------------------------------------------------------------------
// File decoding
static int Decode(void) { // Fills kParams.curr_frame
const WebPIterator* const curr = &kParams.curr_frame;
WebPDecoderConfig* const config = &kParams.config;
WebPDecBuffer* const output_buffer = &config->output;
int ok = 0;
ClearPreviousPic();
output_buffer->colorspace = MODE_RGBA;
ok = (WebPDecode(curr->fragment.bytes, curr->fragment.size,
config) == VP8_STATUS_OK);
if (!ok) {
fprintf(stderr, "Decoding of frame #%d failed!\n", curr->frame_num);
} else {
kParams.pic = output_buffer;
if (kParams.use_color_profile) {
ok = ApplyColorProfile(&kParams.iccp.chunk, output_buffer);
if (!ok) {
fprintf(stderr, "Applying color profile to frame #%d failed!\n",
curr->frame_num);
}
}
}
return ok;
}
static void decode_callback(int what) {
if (what == 0 && !kParams.done) {
int duration = 0;
if (kParams.dmux != NULL) {
WebPIterator* const curr = &kParams.curr_frame;
if (!WebPDemuxNextFrame(curr)) {
WebPDemuxReleaseIterator(curr);
if (WebPDemuxGetFrame(kParams.dmux, 1, curr)) {
--kParams.loop_count;
kParams.done = (kParams.loop_count == 0);
} else {
kParams.decoding_error = 1;
kParams.done = 1;
return;
}
}
duration = curr->duration;
}
if (!Decode()) {
kParams.decoding_error = 1;
kParams.done = 1;
} else {
glutPostRedisplay();
glutTimerFunc(duration, decode_callback, what);
}
}
}
//------------------------------------------------------------------------------
// Callbacks
static void HandleKey(unsigned char key, int pos_x, int pos_y) {
(void)pos_x;
(void)pos_y;
if (key == 'q' || key == 'Q' || key == 27 /* Esc */) {
#ifdef FREEGLUT
glutLeaveMainLoop();
#else
ClearParams();
exit(0);
#endif
} else if (key == 'c') {
if (kParams.has_color_profile && !kParams.decoding_error) {
kParams.use_color_profile = 1 - kParams.use_color_profile;
if (kParams.has_animation) {
// Restart the completed animation to pickup the color profile change.
if (kParams.done && kParams.loop_count == 0) {
kParams.loop_count =
(int)WebPDemuxGetI(kParams.dmux, WEBP_FF_LOOP_COUNT) + 1;
kParams.done = 0;
// Start the decode loop immediately.
glutTimerFunc(0, decode_callback, 0);
}
} else {
Decode();
glutPostRedisplay();
}
}
} else if (key == 'i') {
kParams.print_info = 1 - kParams.print_info;
glutPostRedisplay();
}
}
static void HandleReshape(int width, int height) {
// TODO(skal): proper handling of resize, esp. for large pictures.
// + key control of the zoom.
glViewport(0, 0, width, height);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
static void PrintString(const char* const text) {
void* const font = GLUT_BITMAP_9_BY_15;
int i;
for (i = 0; text[i]; ++i) {
glutBitmapCharacter(font, text[i]);
}
}
static float GetColorf(uint32_t color, int shift) {
return (color >> shift) / 255.f;
}
static void DrawCheckerBoard(void) {
const int square_size = 8; // must be a power of 2
int x, y;
GLint viewport[4]; // x, y, width, height
glPushMatrix();
glGetIntegerv(GL_VIEWPORT, viewport);
// shift to integer coordinates with (0,0) being top-left.
glOrtho(0, viewport[2], viewport[3], 0, -1, 1);
for (y = 0; y < viewport[3]; y += square_size) {
for (x = 0; x < viewport[2]; x += square_size) {
const GLubyte color = 128 + 64 * (!((x + y) & square_size));
glColor3ub(color, color, color);
glRecti(x, y, x + square_size, y + square_size);
}
}
glPopMatrix();
}
static void HandleDisplay(void) {
const WebPDecBuffer* const pic = kParams.pic;
const WebPIterator* const curr = &kParams.curr_frame;
WebPIterator* const prev = &kParams.prev_frame;
GLfloat xoff, yoff;
if (pic == NULL) return;
glPushMatrix();
glPixelZoom(1, -1);
xoff = (GLfloat)(2. * curr->x_offset / kParams.canvas_width);
yoff = (GLfloat)(2. * curr->y_offset / kParams.canvas_height);
glRasterPos2f(-1.f + xoff, 1.f - yoff);
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
glPixelStorei(GL_UNPACK_ROW_LENGTH, pic->u.RGBA.stride / 4);
if (prev->dispose_method == WEBP_MUX_DISPOSE_BACKGROUND ||
curr->blend_method == WEBP_MUX_NO_BLEND) {
// TODO(later): these offsets and those above should factor in window size.
// they will be incorrect if the window is resized.
// glScissor() takes window coordinates (0,0 at bottom left).
int window_x, window_y;
if (prev->dispose_method == WEBP_MUX_DISPOSE_BACKGROUND) {
// Clear the previous frame rectangle.
window_x = prev->x_offset;
window_y = kParams.canvas_height - prev->y_offset - prev->height;
} else { // curr->blend_method == WEBP_MUX_NO_BLEND.
// We simulate no-blending behavior by first clearing the current frame
// rectangle (to a checker-board) and then alpha-blending against it.
window_x = curr->x_offset;
window_y = kParams.canvas_height - curr->y_offset - curr->height;
}
glEnable(GL_SCISSOR_TEST);
// Only update the requested area, not the whole canvas.
glScissor(window_x, window_y, prev->width, prev->height);
glClear(GL_COLOR_BUFFER_BIT); // use clear color
DrawCheckerBoard();
glDisable(GL_SCISSOR_TEST);
}
*prev = *curr;
glDrawPixels(pic->width, pic->height,
GL_RGBA, GL_UNSIGNED_BYTE,
(GLvoid*)pic->u.RGBA.rgba);
if (kParams.print_info) {
char tmp[32];
glColor4f(0.90f, 0.0f, 0.90f, 1.0f);
glRasterPos2f(-0.95f, 0.90f);
PrintString(kParams.file_name);
snprintf(tmp, sizeof(tmp), "Dimension:%d x %d", pic->width, pic->height);
glColor4f(0.90f, 0.0f, 0.90f, 1.0f);
glRasterPos2f(-0.95f, 0.80f);
PrintString(tmp);
if (curr->x_offset != 0 || curr->y_offset != 0) {
snprintf(tmp, sizeof(tmp), " (offset:%d,%d)",
curr->x_offset, curr->y_offset);
glRasterPos2f(-0.95f, 0.70f);
PrintString(tmp);
}
}
glPopMatrix();
glFlush();
}
static void StartDisplay(void) {
const int width = kParams.canvas_width;
const int height = kParams.canvas_height;
glutInitDisplayMode(GLUT_RGBA);
glutInitWindowSize(width, height);
glutCreateWindow("WebP viewer");
glutDisplayFunc(HandleDisplay);
glutIdleFunc(NULL);
glutKeyboardFunc(HandleKey);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_BLEND);
glClearColor(GetColorf(kParams.bg_color, 0),
GetColorf(kParams.bg_color, 8),
GetColorf(kParams.bg_color, 16),
GetColorf(kParams.bg_color, 24));
HandleReshape(width, height);
glClear(GL_COLOR_BUFFER_BIT);
DrawCheckerBoard();
}
//------------------------------------------------------------------------------
// Main
static void Help(void) {
printf("Usage: vwebp in_file [options]\n\n"
"Decodes the WebP image file and visualize it using OpenGL\n"
"Options are:\n"
" -version .... print version number and exit\n"
" -noicc ....... don't use the icc profile if present\n"
" -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 > 0x0204
" -noalphadither disable alpha plane dithering\n"
#endif
" -mt .......... use multi-threading\n"
" -info ........ print info\n"
" -h ....... this help message\n"
"\n"
"Keyboard shortcuts:\n"
" 'c' ................ toggle use of color profile\n"
" 'i' ................ overlay file information\n"
" 'q' / 'Q' / ESC .... quit\n"
);
}
int main(int argc, char *argv[]) {
int c;
WebPDecoderConfig* const config = &kParams.config;
WebPIterator* const curr = &kParams.curr_frame;
WebPIterator* const prev = &kParams.prev_frame;
if (!WebPInitDecoderConfig(config)) {
fprintf(stderr, "Library version mismatch!\n");
return -1;
}
config->options.dithering_strength = 50;
#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;
} else if (!strcmp(argv[c], "-noicc")) {
kParams.use_color_profile = 0;
} else if (!strcmp(argv[c], "-nofancy")) {
config->options.no_fancy_upsampling = 1;
} else if (!strcmp(argv[c], "-nofilter")) {
config->options.bypass_filtering = 1;
#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 =
ExUtilGetInt(argv[++c], 0, &parse_error);
} else if (!strcmp(argv[c], "-info")) {
kParams.print_info = 1;
} else if (!strcmp(argv[c], "-version")) {
const int dec_version = WebPGetDecoderVersion();
const int dmux_version = WebPGetDemuxVersion();
printf("WebP Decoder version: %d.%d.%d\nWebP Demux version: %d.%d.%d\n",
(dec_version >> 16) & 0xff, (dec_version >> 8) & 0xff,
dec_version & 0xff, (dmux_version >> 16) & 0xff,
(dmux_version >> 8) & 0xff, dmux_version & 0xff);
return 0;
} else if (!strcmp(argv[c], "-mt")) {
config->options.use_threads = 1;
} else if (!strcmp(argv[c], "--")) {
if (c < argc - 1) kParams.file_name = argv[++c];
break;
} else if (argv[c][0] == '-') {
printf("Unknown option '%s'\n", argv[c]);
Help();
return -1;
} else {
kParams.file_name = argv[c];
}
if (parse_error) {
Help();
return -1;
}
}
if (kParams.file_name == NULL) {
printf("missing input file!!\n");
Help();
return 0;
}
if (!ExUtilReadFile(kParams.file_name,
&kParams.data.bytes, &kParams.data.size)) {
goto Error;
}
if (!WebPGetInfo(kParams.data.bytes, kParams.data.size, NULL, NULL)) {
fprintf(stderr, "Input file doesn't appear to be WebP format.\n");
goto Error;
}
kParams.dmux = WebPDemux(&kParams.data);
if (kParams.dmux == NULL) {
fprintf(stderr, "Could not create demuxing object!\n");
goto Error;
}
if (WebPDemuxGetI(kParams.dmux, WEBP_FF_FORMAT_FLAGS) & FRAGMENTS_FLAG) {
fprintf(stderr, "Image fragments are not supported for now!\n");
goto Error;
}
kParams.canvas_width = WebPDemuxGetI(kParams.dmux, WEBP_FF_CANVAS_WIDTH);
kParams.canvas_height = WebPDemuxGetI(kParams.dmux, WEBP_FF_CANVAS_HEIGHT);
if (kParams.print_info) {
printf("Canvas: %d x %d\n", kParams.canvas_width, kParams.canvas_height);
}
prev->width = kParams.canvas_width;
prev->height = kParams.canvas_height;
prev->x_offset = prev->y_offset = 0;
prev->dispose_method = WEBP_MUX_DISPOSE_BACKGROUND;
memset(&kParams.iccp, 0, sizeof(kParams.iccp));
kParams.has_color_profile =
!!(WebPDemuxGetI(kParams.dmux, WEBP_FF_FORMAT_FLAGS) & ICCP_FLAG);
if (kParams.has_color_profile) {
#ifdef WEBP_HAVE_QCMS
if (!WebPDemuxGetChunk(kParams.dmux, "ICCP", 1, &kParams.iccp)) goto Error;
printf("VP8X: Found color profile\n");
#else
fprintf(stderr, "Warning: color profile present, but qcms is unavailable!\n"
"Build libqcms from Mozilla or Chromium and define WEBP_HAVE_QCMS "
"before building.\n");
#endif
}
if (!WebPDemuxGetFrame(kParams.dmux, 1, curr)) goto Error;
kParams.has_animation = (curr->num_frames > 1);
kParams.loop_count = (int)WebPDemuxGetI(kParams.dmux, WEBP_FF_LOOP_COUNT);
kParams.bg_color = WebPDemuxGetI(kParams.dmux, WEBP_FF_BACKGROUND_COLOR);
printf("VP8X: Found %d images in file (loop count = %d)\n",
curr->num_frames, kParams.loop_count);
// Decode first frame
if (!Decode()) goto Error;
// Position iterator to last frame. Next call to HandleDisplay will wrap over.
// We take this into account by bumping up loop_count.
WebPDemuxGetFrame(kParams.dmux, 0, curr);
if (kParams.loop_count) ++kParams.loop_count;
// Start display (and timer)
glutInit(&argc, argv);
#ifdef FREEGLUT
glutSetOption(GLUT_ACTION_ON_WINDOW_CLOSE, GLUT_ACTION_CONTINUE_EXECUTION);
#endif
StartDisplay();
if (kParams.has_animation) glutTimerFunc(0, decode_callback, 0);
glutMainLoop();
// Should only be reached when using FREEGLUT:
ClearParams();
return 0;
Error:
ClearParams();
return -1;
}
#else // !WEBP_HAVE_GL
int main(int argc, const char *argv[]) {
fprintf(stderr, "OpenGL support not enabled in %s.\n", argv[0]);
(void)argc;
return 0;
}
#endif
//------------------------------------------------------------------------------

67
examples/webpdec.c Normal file
View File

@ -0,0 +1,67 @@
// 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.
// -----------------------------------------------------------------------------
//
// WebP decode.
#include "./webpdec.h"
#include <stdio.h>
#include <stdlib.h>
#include "webp/decode.h"
#include "webp/encode.h"
#include "./example_util.h"
#include "./metadata.h"
int ReadWebP(const char* const in_file, WebPPicture* const pic,
int keep_alpha, Metadata* const metadata) {
int ok = 0;
size_t data_size = 0;
const uint8_t* data = NULL;
VP8StatusCode status = VP8_STATUS_OK;
WebPDecoderConfig config;
WebPDecBuffer* const output_buffer = &config.output;
WebPBitstreamFeatures* const bitstream = &config.input;
// TODO(jzern): add Exif/XMP/ICC extraction.
if (metadata != NULL) {
fprintf(stderr, "Warning: metadata extraction from WebP is unsupported.\n");
}
if (!WebPInitDecoderConfig(&config)) {
fprintf(stderr, "Library version mismatch!\n");
return 0;
}
if (ExUtilLoadWebP(in_file, &data, &data_size, bitstream)) {
const int has_alpha = keep_alpha && bitstream->has_alpha;
output_buffer->colorspace = has_alpha ? MODE_RGBA : MODE_RGB;
status = ExUtilDecodeWebP(data, data_size, 0, &config);
if (status == VP8_STATUS_OK) {
const uint8_t* const rgba = output_buffer->u.RGBA.rgba;
const int stride = output_buffer->u.RGBA.stride;
pic->width = output_buffer->width;
pic->height = output_buffer->height;
pic->use_argb = 1;
ok = has_alpha ? WebPPictureImportRGBA(pic, rgba, stride)
: WebPPictureImportRGB(pic, rgba, stride);
}
}
if (status != VP8_STATUS_OK) {
ExUtilPrintWebPError(in_file, status);
}
free((void*)data);
WebPFreeDecBuffer(output_buffer);
return ok;
}
// -----------------------------------------------------------------------------

33
examples/webpdec.h Normal file
View File

@ -0,0 +1,33 @@
// 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.
// -----------------------------------------------------------------------------
//
// WebP decode.
#ifndef WEBP_EXAMPLES_WEBPDEC_H_
#define WEBP_EXAMPLES_WEBPDEC_H_
#ifdef __cplusplus
extern "C" {
#endif
struct Metadata;
struct WebPPicture;
// Reads a WebP from 'in_file', returning the decoded output in 'pic'.
// If 'keep_alpha' is true and the WebP has an alpha channel, the output is
// RGBA otherwise it will be RGB.
// Returns true on success.
int ReadWebP(const char* const in_file, struct WebPPicture* const pic,
int keep_alpha, struct Metadata* const metadata);
#ifdef __cplusplus
} // extern "C"
#endif
#endif // WEBP_EXAMPLES_WEBPDEC_H_

1083
examples/webpmux.c Normal file

File diff suppressed because it is too large Load Diff

349
examples/wicdec.c Normal file
View File

@ -0,0 +1,349 @@
// Copyright 2013 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.
// -----------------------------------------------------------------------------
//
// Windows Imaging Component (WIC) decode.
#include "./wicdec.h"
#ifdef HAVE_CONFIG_H
#include "webp/config.h"
#endif
#include <stdio.h>
#ifdef HAVE_WINCODEC_H
#ifdef __MINGW32__
#define INITGUID // Without this GUIDs are declared extern and fail to link
#endif
#define CINTERFACE
#define COBJMACROS
#define _WIN32_IE 0x500 // Workaround bug in shlwapi.h when compiling C++
// code with COBJMACROS.
#include <shlwapi.h>
#include <windows.h>
#include <wincodec.h>
#include "webp/encode.h"
#include "./metadata.h"
#define IFS(fn) \
do { \
if (SUCCEEDED(hr)) { \
hr = (fn); \
if (FAILED(hr)) fprintf(stderr, #fn " failed %08lx\n", hr); \
} \
} while (0)
// modified version of DEFINE_GUID from guiddef.h.
#define WEBP_DEFINE_GUID(name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) \
static const GUID name = \
{ l, w1, w2, { b1, b2, b3, b4, b5, b6, b7, b8 } }
#ifdef __cplusplus
#define MAKE_REFGUID(x) (x)
#else
#define MAKE_REFGUID(x) &(x)
#endif
typedef struct WICFormatImporter {
const GUID* pixel_format;
int bytes_per_pixel;
int (*import)(WebPPicture* const, const uint8_t* const, int);
} WICFormatImporter;
// From Microsoft SDK 7.0a -- wincodec.h
// Create local copies for compatibility when building against earlier
// versions of the SDK.
WEBP_DEFINE_GUID(GUID_WICPixelFormat24bppBGR_,
0x6fddc324, 0x4e03, 0x4bfe,
0xb1, 0x85, 0x3d, 0x77, 0x76, 0x8d, 0xc9, 0x0c);
WEBP_DEFINE_GUID(GUID_WICPixelFormat24bppRGB_,
0x6fddc324, 0x4e03, 0x4bfe,
0xb1, 0x85, 0x3d, 0x77, 0x76, 0x8d, 0xc9, 0x0d);
WEBP_DEFINE_GUID(GUID_WICPixelFormat32bppBGRA_,
0x6fddc324, 0x4e03, 0x4bfe,
0xb1, 0x85, 0x3d, 0x77, 0x76, 0x8d, 0xc9, 0x0f);
WEBP_DEFINE_GUID(GUID_WICPixelFormat32bppRGBA_,
0xf5c7ad2d, 0x6a8d, 0x43dd,
0xa7, 0xa8, 0xa2, 0x99, 0x35, 0x26, 0x1a, 0xe9);
static HRESULT OpenInputStream(const char* filename, IStream** stream) {
HRESULT hr = S_OK;
IFS(SHCreateStreamOnFileA(filename, STGM_READ, stream));
if (FAILED(hr)) {
fprintf(stderr, "Error opening input file %s (%08lx)\n", filename, hr);
}
return hr;
}
// -----------------------------------------------------------------------------
// Metadata processing
// Stores the first non-zero sized color profile from 'frame' to 'iccp'.
// Returns an HRESULT to indicate success or failure. The caller is responsible
// for freeing 'iccp->bytes' in either case.
static HRESULT ExtractICCP(IWICImagingFactory* const factory,
IWICBitmapFrameDecode* const frame,
MetadataPayload* const iccp) {
HRESULT hr = S_OK;
UINT i, count;
IWICColorContext** color_contexts;
IFS(IWICBitmapFrameDecode_GetColorContexts(frame, 0, NULL, &count));
if (FAILED(hr) || count == 0) return hr;
color_contexts = (IWICColorContext**)calloc(count, sizeof(*color_contexts));
if (color_contexts == NULL) return E_OUTOFMEMORY;
for (i = 0; SUCCEEDED(hr) && i < count; ++i) {
IFS(IWICImagingFactory_CreateColorContext(factory, &color_contexts[i]));
}
if (SUCCEEDED(hr)) {
UINT num_color_contexts;
IFS(IWICBitmapFrameDecode_GetColorContexts(frame,
count, color_contexts,
&num_color_contexts));
for (i = 0; SUCCEEDED(hr) && i < num_color_contexts; ++i) {
WICColorContextType type;
IFS(IWICColorContext_GetType(color_contexts[i], &type));
if (SUCCEEDED(hr) && type == WICColorContextProfile) {
UINT size;
IFS(IWICColorContext_GetProfileBytes(color_contexts[i],
0, NULL, &size));
if (size > 0) {
iccp->bytes = (uint8_t*)malloc(size);
if (iccp->bytes == NULL) {
hr = E_OUTOFMEMORY;
break;
}
iccp->size = size;
IFS(IWICColorContext_GetProfileBytes(color_contexts[i],
(UINT)iccp->size, iccp->bytes,
&size));
if (SUCCEEDED(hr) && size != iccp->size) {
fprintf(stderr, "Warning! ICC profile size (%u) != expected (%u)\n",
size, (uint32_t)iccp->size);
iccp->size = size;
}
break;
}
}
}
}
for (i = 0; i < count; ++i) {
if (color_contexts[i] != NULL) IUnknown_Release(color_contexts[i]);
}
free(color_contexts);
return hr;
}
static HRESULT ExtractMetadata(IWICImagingFactory* const factory,
IWICBitmapFrameDecode* const frame,
Metadata* const metadata) {
// TODO(jzern): add XMP/EXIF extraction.
const HRESULT hr = ExtractICCP(factory, frame, &metadata->iccp);
if (FAILED(hr)) MetadataFree(metadata);
return hr;
}
// -----------------------------------------------------------------------------
static int HasPalette(GUID pixel_format) {
return (IsEqualGUID(MAKE_REFGUID(pixel_format),
MAKE_REFGUID(GUID_WICPixelFormat1bppIndexed)) ||
IsEqualGUID(MAKE_REFGUID(pixel_format),
MAKE_REFGUID(GUID_WICPixelFormat2bppIndexed)) ||
IsEqualGUID(MAKE_REFGUID(pixel_format),
MAKE_REFGUID(GUID_WICPixelFormat4bppIndexed)) ||
IsEqualGUID(MAKE_REFGUID(pixel_format),
MAKE_REFGUID(GUID_WICPixelFormat8bppIndexed)));
}
static int HasAlpha(IWICImagingFactory* const factory,
IWICBitmapDecoder* const decoder,
IWICBitmapFrameDecode* const frame,
GUID pixel_format) {
int has_alpha;
if (HasPalette(pixel_format)) {
IWICPalette* frame_palette = NULL;
IWICPalette* global_palette = NULL;
BOOL frame_palette_has_alpha = FALSE;
BOOL global_palette_has_alpha = FALSE;
// A palette may exist at the frame or container level,
// check IWICPalette::HasAlpha() for both if present.
if (SUCCEEDED(IWICImagingFactory_CreatePalette(factory, &frame_palette)) &&
SUCCEEDED(IWICBitmapFrameDecode_CopyPalette(frame, frame_palette))) {
IWICPalette_HasAlpha(frame_palette, &frame_palette_has_alpha);
}
if (SUCCEEDED(IWICImagingFactory_CreatePalette(factory, &global_palette)) &&
SUCCEEDED(IWICBitmapDecoder_CopyPalette(decoder, global_palette))) {
IWICPalette_HasAlpha(global_palette, &global_palette_has_alpha);
}
has_alpha = frame_palette_has_alpha || global_palette_has_alpha;
if (frame_palette != NULL) IUnknown_Release(frame_palette);
if (global_palette != NULL) IUnknown_Release(global_palette);
} else {
has_alpha = IsEqualGUID(MAKE_REFGUID(pixel_format),
MAKE_REFGUID(GUID_WICPixelFormat32bppRGBA_)) ||
IsEqualGUID(MAKE_REFGUID(pixel_format),
MAKE_REFGUID(GUID_WICPixelFormat32bppBGRA_));
}
return has_alpha;
}
int ReadPictureWithWIC(const char* const filename,
WebPPicture* const pic, int keep_alpha,
Metadata* const metadata) {
// From Microsoft SDK 6.0a -- ks.h
// Define a local copy to avoid link errors under mingw.
WEBP_DEFINE_GUID(GUID_NULL_, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
static const WICFormatImporter kAlphaFormatImporters[] = {
{ &GUID_WICPixelFormat32bppBGRA_, 4, WebPPictureImportBGRA },
{ &GUID_WICPixelFormat32bppRGBA_, 4, WebPPictureImportRGBA },
{ NULL, 0, NULL },
};
static const WICFormatImporter kNonAlphaFormatImporters[] = {
{ &GUID_WICPixelFormat24bppBGR_, 3, WebPPictureImportBGR },
{ &GUID_WICPixelFormat24bppRGB_, 3, WebPPictureImportRGB },
{ NULL, 0, NULL },
};
HRESULT hr = S_OK;
IWICBitmapFrameDecode* frame = NULL;
IWICFormatConverter* converter = NULL;
IWICImagingFactory* factory = NULL;
IWICBitmapDecoder* decoder = NULL;
IStream* stream = NULL;
UINT frame_count = 0;
UINT width = 0, height = 0;
BYTE* rgb = NULL;
WICPixelFormatGUID src_pixel_format = GUID_WICPixelFormatUndefined;
const WICFormatImporter* importer = NULL;
GUID src_container_format = GUID_NULL_;
static const GUID* kAlphaContainers[] = {
&GUID_ContainerFormatBmp,
&GUID_ContainerFormatPng,
&GUID_ContainerFormatTiff,
NULL
};
int has_alpha = 0;
int stride;
IFS(CoInitialize(NULL));
IFS(CoCreateInstance(MAKE_REFGUID(CLSID_WICImagingFactory), NULL,
CLSCTX_INPROC_SERVER,
MAKE_REFGUID(IID_IWICImagingFactory),
(LPVOID*)&factory));
if (hr == REGDB_E_CLASSNOTREG) {
fprintf(stderr,
"Couldn't access Windows Imaging Component (are you running "
"Windows XP SP3 or newer?). Most formats not available. "
"Use -s for the available YUV input.\n");
}
// Prepare for image decoding.
IFS(OpenInputStream(filename, &stream));
IFS(IWICImagingFactory_CreateDecoderFromStream(
factory, stream, NULL,
WICDecodeMetadataCacheOnDemand, &decoder));
IFS(IWICBitmapDecoder_GetFrameCount(decoder, &frame_count));
if (SUCCEEDED(hr) && frame_count == 0) {
fprintf(stderr, "No frame found in input file.\n");
hr = E_FAIL;
}
IFS(IWICBitmapDecoder_GetFrame(decoder, 0, &frame));
IFS(IWICBitmapFrameDecode_GetPixelFormat(frame, &src_pixel_format));
IFS(IWICBitmapDecoder_GetContainerFormat(decoder, &src_container_format));
if (keep_alpha) {
const GUID** guid;
for (guid = kAlphaContainers; *guid != NULL; ++guid) {
if (IsEqualGUID(MAKE_REFGUID(src_container_format),
MAKE_REFGUID(**guid))) {
has_alpha = HasAlpha(factory, decoder, frame, src_pixel_format);
break;
}
}
}
// Prepare for pixel format conversion (if necessary).
IFS(IWICImagingFactory_CreateFormatConverter(factory, &converter));
for (importer = has_alpha ? kAlphaFormatImporters : kNonAlphaFormatImporters;
hr == S_OK && importer->import != NULL; ++importer) {
BOOL can_convert;
const HRESULT cchr = IWICFormatConverter_CanConvert(
converter,
MAKE_REFGUID(src_pixel_format),
MAKE_REFGUID(*importer->pixel_format),
&can_convert);
if (SUCCEEDED(cchr) && can_convert) break;
}
if (importer->import == NULL) hr = E_FAIL;
IFS(IWICFormatConverter_Initialize(converter, (IWICBitmapSource*)frame,
importer->pixel_format,
WICBitmapDitherTypeNone,
NULL, 0.0, WICBitmapPaletteTypeCustom));
// Decode.
IFS(IWICFormatConverter_GetSize(converter, &width, &height));
stride = importer->bytes_per_pixel * width * sizeof(*rgb);
if (SUCCEEDED(hr)) {
rgb = (BYTE*)malloc(stride * height);
if (rgb == NULL)
hr = E_OUTOFMEMORY;
}
IFS(IWICFormatConverter_CopyPixels(converter, NULL,
stride, stride * height, rgb));
// WebP conversion.
if (SUCCEEDED(hr)) {
int ok;
pic->width = width;
pic->height = height;
pic->use_argb = 1;
ok = importer->import(pic, rgb, stride);
if (!ok) hr = E_FAIL;
}
if (SUCCEEDED(hr)) {
if (metadata != NULL) {
hr = ExtractMetadata(factory, frame, metadata);
if (FAILED(hr)) {
fprintf(stderr, "Error extracting image metadata using WIC!\n");
}
}
}
// Cleanup.
if (converter != NULL) IUnknown_Release(converter);
if (frame != NULL) IUnknown_Release(frame);
if (decoder != NULL) IUnknown_Release(decoder);
if (factory != NULL) IUnknown_Release(factory);
if (stream != NULL) IUnknown_Release(stream);
free(rgb);
return SUCCEEDED(hr);
}
#else // !HAVE_WINCODEC_H
int ReadPictureWithWIC(const char* const filename,
struct WebPPicture* const pic, int keep_alpha,
struct Metadata* const metadata) {
(void)filename;
(void)pic;
(void)keep_alpha;
(void)metadata;
fprintf(stderr, "Windows Imaging Component (WIC) support not compiled. "
"Visual Studio and mingw-w64 builds support WIC. Make sure "
"wincodec.h detection is working correctly if using autoconf "
"and HAVE_WINCODEC_H is defined before building.\n");
return 0;
}
#endif // HAVE_WINCODEC_H
// -----------------------------------------------------------------------------

34
examples/wicdec.h Normal file
View File

@ -0,0 +1,34 @@
// Copyright 2013 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.
// -----------------------------------------------------------------------------
//
// Windows Imaging Component (WIC) decode.
#ifndef WEBP_EXAMPLES_WICDEC_H_
#define WEBP_EXAMPLES_WICDEC_H_
#ifdef __cplusplus
extern "C" {
#endif
struct Metadata;
struct WebPPicture;
// Reads an image from 'filename', returning the decoded output in 'pic'.
// If 'keep_alpha' is true and the image has an alpha channel, the output is
// RGBA otherwise it will be RGB.
// Returns true on success.
int ReadPictureWithWIC(const char* const filename,
struct WebPPicture* const pic, int keep_alpha,
struct Metadata* const metadata);
#ifdef __cplusplus
} // extern "C"
#endif
#endif // WEBP_EXAMPLES_WICDEC_H_

117
iosbuild.sh Executable file
View File

@ -0,0 +1,117 @@
#!/bin/bash
#
# This script generates 'WebP.framework'. An iOS app can decode WebP images
# by including 'WebP.framework'.
#
# Run ./iosbuild.sh to generate 'WebP.framework' under the current directory
# (previous build will be erased if it exists).
#
# This script is inspired by the build script written by Carson McDonald.
# (http://www.ioncannon.net/programming/1483/using-webp-to-reduce-native-ios-app-size/).
set -e
# Extract the latest SDK version from the final field of the form: iphoneosX.Y
readonly SDK=$(xcodebuild -showsdks \
| grep iphoneos | sort | tail -n 1 | awk '{print substr($NF, 9)}'
)
# Extract Xcode version.
readonly XCODE=$(xcodebuild -version | grep Xcode | cut -d " " -f2)
if [[ -z "${XCODE}" ]]; then
echo "Xcode not available"
exit 1
fi
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.
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} < 6.0 ]]; then
echo "You need iOS SDK version 6.0 or above"
exit 1
else
echo "iOS SDK Version ${SDK}"
fi
rm -rf ${BUILDDIR}
rm -rf ${TARGETDIR}
mkdir -p ${BUILDDIR}
mkdir -p ${TARGETDIR}/Headers/
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=""
if [[ "${PLATFORM}" == "iPhoneOS-V7-arm64" ]]; then
PLATFORM="iPhoneOS"
ARCH="aarch64"
ARCH2="arm64"
elif [[ "${PLATFORM}" == "iPhoneOS-V7s" ]]; then
PLATFORM="iPhoneOS"
ARCH="armv7s"
elif [[ "${PLATFORM}" == "iPhoneOS-V7" ]]; then
PLATFORM="iPhoneOS"
ARCH="armv7"
elif [[ "${PLATFORM}" == "iPhoneOS-V6" ]]; then
PLATFORM="iPhoneOS"
ARCH="armv6"
else
ARCH="i386"
fi
ROOTDIR="${BUILDDIR}/${PLATFORM}-${SDK}-${ARCH}"
mkdir -p "${ROOTDIR}"
DEVROOT="${DEVELOPER}/Toolchains/XcodeDefault.xctoolchain"
SDKROOT="${PLATFORMSROOT}/"
SDKROOT+="${PLATFORM}.platform/Developer/SDKs/${PLATFORM}${SDK}.sdk/"
CFLAGS="-arch ${ARCH2:-${ARCH}} -pipe -isysroot ${SDKROOT} -O3 -DNDEBUG"
CFLAGS+=" -miphoneos-version-min=6.0"
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 \
CFLAGS="${CFLAGS}"
set +x
# run make only in the src/ directory to create libwebpdecoder.a
cd src/
make V=0
make install
LIBLIST+=" ${ROOTDIR}/lib/libwebpdecoder.a"
make clean
cd ..
export PATH=${OLDPATH}
done
cp -a ${SRCDIR}/src/webp/*.h ${TARGETDIR}/Headers/
${LIPO} -create ${LIBLIST} -output ${TARGETDIR}/WebP

332
m4/ax_pthread.m4 Normal file
View File

@ -0,0 +1,332 @@
# ===========================================================================
# http://www.gnu.org/software/autoconf-archive/ax_pthread.html
# ===========================================================================
#
# SYNOPSIS
#
# AX_PTHREAD([ACTION-IF-FOUND[, ACTION-IF-NOT-FOUND]])
#
# DESCRIPTION
#
# This macro figures out how to build C programs using POSIX threads. It
# sets the PTHREAD_LIBS output variable to the threads library and linker
# flags, and the PTHREAD_CFLAGS output variable to any special C compiler
# flags that are needed. (The user can also force certain compiler
# flags/libs to be tested by setting these environment variables.)
#
# Also sets PTHREAD_CC to any special C compiler that is needed for
# multi-threaded programs (defaults to the value of CC otherwise). (This
# is necessary on AIX to use the special cc_r compiler alias.)
#
# NOTE: You are assumed to not only compile your program with these flags,
# but also link it with them as well. e.g. you should link with
# $PTHREAD_CC $CFLAGS $PTHREAD_CFLAGS $LDFLAGS ... $PTHREAD_LIBS $LIBS
#
# If you are only building threads programs, you may wish to use these
# variables in your default LIBS, CFLAGS, and CC:
#
# LIBS="$PTHREAD_LIBS $LIBS"
# CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
# CC="$PTHREAD_CC"
#
# In addition, if the PTHREAD_CREATE_JOINABLE thread-attribute constant
# has a nonstandard name, defines PTHREAD_CREATE_JOINABLE to that name
# (e.g. PTHREAD_CREATE_UNDETACHED on AIX).
#
# Also HAVE_PTHREAD_PRIO_INHERIT is defined if pthread is found and the
# PTHREAD_PRIO_INHERIT symbol is defined when compiling with
# PTHREAD_CFLAGS.
#
# ACTION-IF-FOUND is a list of shell commands to run if a threads library
# is found, and ACTION-IF-NOT-FOUND is a list of commands to run it if it
# is not found. If ACTION-IF-FOUND is not specified, the default action
# will define HAVE_PTHREAD.
#
# Please let the authors know if this macro fails on any platform, or if
# you have any other suggestions or comments. This macro was based on work
# by SGJ on autoconf scripts for FFTW (http://www.fftw.org/) (with help
# from M. Frigo), as well as ac_pthread and hb_pthread macros posted by
# Alejandro Forero Cuervo to the autoconf macro repository. We are also
# grateful for the helpful feedback of numerous users.
#
# Updated for Autoconf 2.68 by Daniel Richard G.
#
# LICENSE
#
# Copyright (c) 2008 Steven G. Johnson <stevenj@alum.mit.edu>
# Copyright (c) 2011 Daniel Richard G. <skunk@iSKUNK.ORG>
#
# This program is free software: you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by the
# Free Software Foundation, either version 3 of the License, or (at your
# option) any later version.
#
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
# Public License for more details.
#
# You should have received a copy of the GNU General Public License along
# with this program. If not, see <http://www.gnu.org/licenses/>.
#
# As a special exception, the respective Autoconf Macro's copyright owner
# gives unlimited permission to copy, distribute and modify the configure
# scripts that are the output of Autoconf when processing the Macro. You
# need not follow the terms of the GNU General Public License when using
# or distributing such scripts, even though portions of the text of the
# Macro appear in them. The GNU General Public License (GPL) does govern
# all other use of the material that constitutes the Autoconf Macro.
#
# This special exception to the GPL applies to versions of the Autoconf
# Macro released by the Autoconf Archive. When you make and distribute a
# modified version of the Autoconf Macro, you may extend this special
# exception to the GPL to apply to your modified version as well.
#serial 21
AU_ALIAS([ACX_PTHREAD], [AX_PTHREAD])
AC_DEFUN([AX_PTHREAD], [
AC_REQUIRE([AC_CANONICAL_HOST])
AC_LANG_PUSH([C])
ax_pthread_ok=no
# We used to check for pthread.h first, but this fails if pthread.h
# requires special compiler flags (e.g. on True64 or Sequent).
# It gets checked for in the link test anyway.
# First of all, check if the user has set any of the PTHREAD_LIBS,
# etcetera environment variables, and if threads linking works using
# them:
if test x"$PTHREAD_LIBS$PTHREAD_CFLAGS" != x; then
save_CFLAGS="$CFLAGS"
CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
save_LIBS="$LIBS"
LIBS="$PTHREAD_LIBS $LIBS"
AC_MSG_CHECKING([for pthread_join in LIBS=$PTHREAD_LIBS with CFLAGS=$PTHREAD_CFLAGS])
AC_TRY_LINK_FUNC([pthread_join], [ax_pthread_ok=yes])
AC_MSG_RESULT([$ax_pthread_ok])
if test x"$ax_pthread_ok" = xno; then
PTHREAD_LIBS=""
PTHREAD_CFLAGS=""
fi
LIBS="$save_LIBS"
CFLAGS="$save_CFLAGS"
fi
# We must check for the threads library under a number of different
# names; the ordering is very important because some systems
# (e.g. DEC) have both -lpthread and -lpthreads, where one of the
# libraries is broken (non-POSIX).
# Create a list of thread flags to try. Items starting with a "-" are
# C compiler flags, and other items are library names, except for "none"
# which indicates that we try without any flags at all, and "pthread-config"
# which is a program returning the flags for the Pth emulation library.
ax_pthread_flags="pthreads none -Kthread -kthread lthread -pthread -pthreads -mthreads pthread --thread-safe -mt pthread-config"
# The ordering *is* (sometimes) important. Some notes on the
# individual items follow:
# pthreads: AIX (must check this before -lpthread)
# none: in case threads are in libc; should be tried before -Kthread and
# other compiler flags to prevent continual compiler warnings
# -Kthread: Sequent (threads in libc, but -Kthread needed for pthread.h)
# -kthread: FreeBSD kernel threads (preferred to -pthread since SMP-able)
# lthread: LinuxThreads port on FreeBSD (also preferred to -pthread)
# -pthread: Linux/gcc (kernel threads), BSD/gcc (userland threads)
# -pthreads: Solaris/gcc
# -mthreads: Mingw32/gcc, Lynx/gcc
# -mt: Sun Workshop C (may only link SunOS threads [-lthread], but it
# doesn't hurt to check since this sometimes defines pthreads too;
# also defines -D_REENTRANT)
# ... -mt is also the pthreads flag for HP/aCC
# pthread: Linux, etcetera
# --thread-safe: KAI C++
# pthread-config: use pthread-config program (for GNU Pth library)
case ${host_os} in
solaris*)
# On Solaris (at least, for some versions), libc contains stubbed
# (non-functional) versions of the pthreads routines, so link-based
# tests will erroneously succeed. (We need to link with -pthreads/-mt/
# -lpthread.) (The stubs are missing pthread_cleanup_push, or rather
# a function called by this macro, so we could check for that, but
# who knows whether they'll stub that too in a future libc.) So,
# we'll just look for -pthreads and -lpthread first:
ax_pthread_flags="-pthreads pthread -mt -pthread $ax_pthread_flags"
;;
darwin*)
ax_pthread_flags="-pthread $ax_pthread_flags"
;;
esac
# Clang doesn't consider unrecognized options an error unless we specify
# -Werror. We throw in some extra Clang-specific options to ensure that
# this doesn't happen for GCC, which also accepts -Werror.
AC_MSG_CHECKING([if compiler needs -Werror to reject unknown flags])
save_CFLAGS="$CFLAGS"
ax_pthread_extra_flags="-Werror"
CFLAGS="$CFLAGS $ax_pthread_extra_flags -Wunknown-warning-option -Wsizeof-array-argument"
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([int foo(void);],[foo()])],
[AC_MSG_RESULT([yes])],
[ax_pthread_extra_flags=
AC_MSG_RESULT([no])])
CFLAGS="$save_CFLAGS"
if test x"$ax_pthread_ok" = xno; then
for flag in $ax_pthread_flags; do
case $flag in
none)
AC_MSG_CHECKING([whether pthreads work without any flags])
;;
-*)
AC_MSG_CHECKING([whether pthreads work with $flag])
PTHREAD_CFLAGS="$flag"
;;
pthread-config)
AC_CHECK_PROG([ax_pthread_config], [pthread-config], [yes], [no])
if test x"$ax_pthread_config" = xno; then continue; fi
PTHREAD_CFLAGS="`pthread-config --cflags`"
PTHREAD_LIBS="`pthread-config --ldflags` `pthread-config --libs`"
;;
*)
AC_MSG_CHECKING([for the pthreads library -l$flag])
PTHREAD_LIBS="-l$flag"
;;
esac
save_LIBS="$LIBS"
save_CFLAGS="$CFLAGS"
LIBS="$PTHREAD_LIBS $LIBS"
CFLAGS="$CFLAGS $PTHREAD_CFLAGS $ax_pthread_extra_flags"
# Check for various functions. We must include pthread.h,
# since some functions may be macros. (On the Sequent, we
# need a special flag -Kthread to make this header compile.)
# We check for pthread_join because it is in -lpthread on IRIX
# while pthread_create is in libc. We check for pthread_attr_init
# due to DEC craziness with -lpthreads. We check for
# pthread_cleanup_push because it is one of the few pthread
# functions on Solaris that doesn't have a non-functional libc stub.
# We try pthread_create on general principles.
AC_LINK_IFELSE([AC_LANG_PROGRAM([#include <pthread.h>
static void routine(void *a) { a = 0; }
static void *start_routine(void *a) { return a; }],
[pthread_t th; pthread_attr_t attr;
pthread_create(&th, 0, start_routine, 0);
pthread_join(th, 0);
pthread_attr_init(&attr);
pthread_cleanup_push(routine, 0);
pthread_cleanup_pop(0) /* ; */])],
[ax_pthread_ok=yes],
[])
LIBS="$save_LIBS"
CFLAGS="$save_CFLAGS"
AC_MSG_RESULT([$ax_pthread_ok])
if test "x$ax_pthread_ok" = xyes; then
break;
fi
PTHREAD_LIBS=""
PTHREAD_CFLAGS=""
done
fi
# Various other checks:
if test "x$ax_pthread_ok" = xyes; then
save_LIBS="$LIBS"
LIBS="$PTHREAD_LIBS $LIBS"
save_CFLAGS="$CFLAGS"
CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
# Detect AIX lossage: JOINABLE attribute is called UNDETACHED.
AC_MSG_CHECKING([for joinable pthread attribute])
attr_name=unknown
for attr in PTHREAD_CREATE_JOINABLE PTHREAD_CREATE_UNDETACHED; do
AC_LINK_IFELSE([AC_LANG_PROGRAM([#include <pthread.h>],
[int attr = $attr; return attr /* ; */])],
[attr_name=$attr; break],
[])
done
AC_MSG_RESULT([$attr_name])
if test "$attr_name" != PTHREAD_CREATE_JOINABLE; then
AC_DEFINE_UNQUOTED([PTHREAD_CREATE_JOINABLE], [$attr_name],
[Define to necessary symbol if this constant
uses a non-standard name on your system.])
fi
AC_MSG_CHECKING([if more special flags are required for pthreads])
flag=no
case ${host_os} in
aix* | freebsd* | darwin*) flag="-D_THREAD_SAFE";;
osf* | hpux*) flag="-D_REENTRANT";;
solaris*)
if test "$GCC" = "yes"; then
flag="-D_REENTRANT"
else
# TODO: What about Clang on Solaris?
flag="-mt -D_REENTRANT"
fi
;;
esac
AC_MSG_RESULT([$flag])
if test "x$flag" != xno; then
PTHREAD_CFLAGS="$flag $PTHREAD_CFLAGS"
fi
AC_CACHE_CHECK([for PTHREAD_PRIO_INHERIT],
[ax_cv_PTHREAD_PRIO_INHERIT], [
AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include <pthread.h>]],
[[int i = PTHREAD_PRIO_INHERIT;]])],
[ax_cv_PTHREAD_PRIO_INHERIT=yes],
[ax_cv_PTHREAD_PRIO_INHERIT=no])
])
AS_IF([test "x$ax_cv_PTHREAD_PRIO_INHERIT" = "xyes"],
[AC_DEFINE([HAVE_PTHREAD_PRIO_INHERIT], [1], [Have PTHREAD_PRIO_INHERIT.])])
LIBS="$save_LIBS"
CFLAGS="$save_CFLAGS"
# More AIX lossage: compile with *_r variant
if test "x$GCC" != xyes; then
case $host_os in
aix*)
AS_CASE(["x/$CC"],
[x*/c89|x*/c89_128|x*/c99|x*/c99_128|x*/cc|x*/cc128|x*/xlc|x*/xlc_v6|x*/xlc128|x*/xlc128_v6],
[#handle absolute path differently from PATH based program lookup
AS_CASE(["x$CC"],
[x/*],
[AS_IF([AS_EXECUTABLE_P([${CC}_r])],[PTHREAD_CC="${CC}_r"])],
[AC_CHECK_PROGS([PTHREAD_CC],[${CC}_r],[$CC])])])
;;
esac
fi
fi
test -n "$PTHREAD_CC" || PTHREAD_CC="$CC"
AC_SUBST([PTHREAD_LIBS])
AC_SUBST([PTHREAD_CFLAGS])
AC_SUBST([PTHREAD_CC])
# Finally, execute ACTION-IF-FOUND/ACTION-IF-NOT-FOUND:
if test x"$ax_pthread_ok" = xyes; then
ifelse([$1],,[AC_DEFINE([HAVE_PTHREAD],[1],[Define if you have POSIX threads libraries and header files.])],[$1])
:
else
ax_pthread_ok=no
$2
fi
AC_LANG_POP
])dnl AX_PTHREAD

View File

@ -2,7 +2,8 @@
# system, for simple local building of the libraries and tools.
# It will not install the libraries system-wide, but just create the 'cwebp'
# and 'dwebp' tools in the examples/ directory, along with the static
# library 'src/libwebp.a'.
# libraries 'src/libwebp.a', 'src/libwebpdecoder.a', 'src/mux/libwebpmux.a' and
# 'src/demux/libwebpdemux.a'.
#
# To build the library and examples, use:
# make -f makefile.unix
@ -10,79 +11,334 @@
#### Customizable part ####
# These flag assume you have libpng and libjpeg installed. If not, either
# follow below install instructions or just comment out the next lines.
EXTRA_FLAGS= -DWEBP_HAVE_PNG -DWEBP_HAVE_JPEG
EXTRA_LIBS= -lpng -ljpeg
ifeq ("$(HOSTTYPE)", "intel-mac")
# These flags assume you have libpng, libjpeg, libtiff and libgif installed. If
# not, either follow the install instructions below or just comment out the next
# four lines.
EXTRA_FLAGS= -DWEBP_HAVE_PNG -DWEBP_HAVE_JPEG -DWEBP_HAVE_TIFF
DWEBP_LIBS= -lpng -lz
CWEBP_LIBS= $(DWEBP_LIBS) -ljpeg -ltiff
GIF_LIBS = -lgif
ifeq ($(strip $(shell uname)), Darwin)
# Work around a problem linking tables marked as common symbols,
# cf., src/enc/yuv.[hc]
# Failure observed with: gcc 4.2.1 and 4.0.1.
EXTRA_FLAGS += -fno-common
EXTRA_FLAGS += -DHAVE_GLUT_GLUT_H
EXTRA_FLAGS += -I/opt/local/include
EXTRA_LIBS += -L/opt/local/lib
GL_LIBS = -framework GLUT -framework OpenGL
else
GL_LIBS = -lglut -lGL
endif
# To install libraries on Mac OS X:
# 1. Install MacPorts (http://www.macports.org/install.php)
# 2. Run "sudo port install jpeg"
# 3. Run "sudo port install libpng"
# 4. Run "sudo port install tiff"
# 5. Run "sudo port install giflib"
# To install libraries on Linux:
# 1. Run "sudo apt-get install libjpeg62-dev"
# 2. Run "sudo apt-get install libpng12-dev"
# 3. Run "sudo apt-get install libtiff4-dev"
# 4. Run "sudo apt-get install libgif-dev"
# Uncomment for build for 32bit platform
# Alternatively, you can just use the command
# 'make -f makefile.unix EXTRA_FLAGS=-m32' to that effect.
# EXTRA_FLAGS += -m32
# Extra flags to enable experimental features and code
# EXTRA_FLAGS += -DWEBP_EXPERIMENTAL_FEATURES
# Extra flags to enable byte swap for 16 bit colorspaces.
# EXTRA_FLAGS += -DWEBP_SWAP_16BIT_CSP
# Extra flags to enable multi-threading
EXTRA_FLAGS += -DWEBP_USE_THREAD
EXTRA_LIBS += -lpthread
# Extra flags to emulate C89 strictness with the full ANSI
EXTRA_FLAGS += -Wextra -Wold-style-definition
EXTRA_FLAGS += -Wmissing-prototypes
EXTRA_FLAGS += -Wmissing-declarations
EXTRA_FLAGS += -Wdeclaration-after-statement
EXTRA_FLAGS += -Wshadow
# EXTRA_FLAGS += -Wvla
# AVX2-specific flags:
ifeq ($(HAVE_AVX2), 1)
EXTRA_FLAGS += -DWEBP_HAVE_AVX2
src/dsp/%_avx2.o: EXTRA_FLAGS += -mavx2
endif
# NEON-specific flags:
# EXTRA_FLAGS += -march=armv7-a -mfloat-abi=hard -mfpu=neon -mtune=cortex-a8
# -> seems to make the overall lib slower: -fno-split-wide-types
#### Nothing should normally be changed below this line ####
CC = gcc -Isrc/ -Iexamples/ -Wall
AR = ar
ARFLAGS = r
CC = gcc
CPPFLAGS = -Isrc/ -Wall
CFLAGS = -O3 -DNDEBUG $(EXTRA_FLAGS)
LDFLAGS = src/libwebp.a $(EXTRA_LIBS) -lm
INSTALL = install
GROFF = /usr/bin/groff
COL = /usr/bin/col
LDFLAGS = $(EXTRA_LIBS) $(EXTRA_FLAGS) -lm
OBJS = src/enc/webpenc.o src/enc/bit_writer.o src/enc/syntax.o \
src/enc/dsp.o src/enc/tree.o src/enc/config.o src/enc/frame.o \
src/enc/quant.o src/enc/iterator.o src/enc/analysis.o \
src/enc/cost.o src/enc/picture.o src/enc/filter.o \
src/dec/bits.o src/dec/dsp.o src/dec/frame.o src/dec/webp.o \
src/dec/quant.o src/dec/tree.o src/dec/vp8.o src/dec/yuv.o \
src/dec/idec.o
HDRS = src/webp/encode.h src/enc/vp8enci.h src/enc/bit_writer.h \
src/enc/cost.h src/dec/bits.h src/dec/vp8i.h src/dec/yuv.h
OUTPUT = examples/cwebp examples/dwebp src/libwebp.a
DEC_OBJS = \
src/dec/alpha.o \
src/dec/buffer.o \
src/dec/frame.o \
src/dec/idec.o \
src/dec/io.o \
src/dec/quant.o \
src/dec/tree.o \
src/dec/vp8.o \
src/dec/vp8l.o \
src/dec/webp.o \
all:ex
DEMUX_OBJS = \
src/demux/demux.o \
.c.o: $(HDRS)
$(CC) $(CFLAGS) -c $< -o $@
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 \
src/dsp/dec_mips32.o \
src/dsp/dec_neon.o \
src/dsp/dec_sse2.o \
src/dsp/lossless.o \
src/dsp/lossless_mips32.o \
src/dsp/lossless_neon.o \
src/dsp/lossless_sse2.o \
src/dsp/upsampling.o \
src/dsp/upsampling_neon.o \
src/dsp/upsampling_sse2.o \
src/dsp/yuv.o \
src/dsp/yuv_mips32.o \
src/dsp/yuv_sse2.o \
libwebp.a: $(OBJS) $(HDRS)
ar r src/libwebp.a $(OBJS)
DSP_ENC_OBJS = \
src/dsp/enc.o \
src/dsp/enc_avx2.o \
src/dsp/enc_mips32.o \
src/dsp/enc_neon.o \
src/dsp/enc_sse2.o \
ex: examples/cwebp.o examples/dwebp.o libwebp.a
$(CC) -o examples/cwebp examples/cwebp.o $(LDFLAGS)
$(CC) -o examples/dwebp examples/dwebp.o $(LDFLAGS)
ENC_OBJS = \
src/enc/alpha.o \
src/enc/analysis.o \
src/enc/backward_references.o \
src/enc/config.o \
src/enc/cost.o \
src/enc/filter.o \
src/enc/frame.o \
src/enc/histogram.o \
src/enc/iterator.o \
src/enc/picture.o \
src/enc/picture_csp.o \
src/enc/picture_psnr.o \
src/enc/picture_rescale.o \
src/enc/picture_tools.o \
src/enc/quant.o \
src/enc/syntax.o \
src/enc/token.o \
src/enc/tree.o \
src/enc/vp8l.o \
src/enc/webpenc.o \
EX_FORMAT_DEC_OBJS = \
examples/jpegdec.o \
examples/metadata.o \
examples/pngdec.o \
examples/tiffdec.o \
examples/webpdec.o \
EX_UTIL_OBJS = \
examples/example_util.o \
GIF2WEBP_UTIL_OBJS = \
examples/gif2webp_util.o \
MUX_OBJS = \
src/mux/muxedit.o \
src/mux/muxinternal.o \
src/mux/muxread.o \
UTILS_DEC_OBJS = \
src/utils/bit_reader.o \
src/utils/color_cache.o \
src/utils/filters.o \
src/utils/huffman.o \
src/utils/quant_levels_dec.o \
src/utils/random.o \
src/utils/rescaler.o \
src/utils/thread.o \
src/utils/utils.o \
UTILS_ENC_OBJS = \
src/utils/bit_writer.o \
src/utils/huffman_encode.o \
src/utils/quant_levels.o \
LIBWEBPDECODER_OBJS = $(DEC_OBJS) $(DSP_DEC_OBJS) $(UTILS_DEC_OBJS)
LIBWEBP_OBJS = $(LIBWEBPDECODER_OBJS) $(ENC_OBJS) $(DSP_ENC_OBJS) \
$(UTILS_ENC_OBJS)
LIBWEBPMUX_OBJS = $(MUX_OBJS)
LIBWEBPDEMUX_OBJS = $(DEMUX_OBJS)
HDRS_INSTALLED = \
src/webp/decode.h \
src/webp/demux.h \
src/webp/encode.h \
src/webp/mux.h \
src/webp/mux_types.h \
src/webp/types.h \
HDRS = \
src/dec/alphai.h \
src/dec/decode_vp8.h \
src/dec/vp8i.h \
src/dec/vp8li.h \
src/dec/webpi.h \
src/dsp/dsp.h \
src/dsp/lossless.h \
src/dsp/neon.h \
src/dsp/yuv.h \
src/dsp/yuv_tables_sse2.h \
src/enc/backward_references.h \
src/enc/cost.h \
src/enc/histogram.h \
src/enc/vp8enci.h \
src/enc/vp8li.h \
src/mux/muxi.h \
src/utils/bit_reader.h \
src/utils/bit_writer.h \
src/utils/color_cache.h \
src/utils/filters.h \
src/utils/huffman.h \
src/utils/huffman_encode.h \
src/utils/quant_levels.h \
src/utils/quant_levels_dec.h \
src/utils/random.h \
src/utils/rescaler.h \
src/utils/thread.h \
src/utils/utils.h \
src/webp/format_constants.h \
$(HDRS_INSTALLED) \
OUT_LIBS = examples/libexample_util.a src/libwebpdecoder.a src/libwebp.a
OUT_EXAMPLES = examples/cwebp examples/dwebp
EXTRA_EXAMPLES = examples/gif2webp examples/vwebp examples/webpmux
OUTPUT = $(OUT_LIBS) $(OUT_EXAMPLES)
ifeq ($(MAKECMDGOALS),clean)
OUTPUT += $(EXTRA_EXAMPLES)
OUTPUT += src/demux/libwebpdemux.a src/mux/libwebpmux.a
OUTPUT += examples/libgif2webp_util.a
endif
ex: $(OUT_EXAMPLES)
all: ex $(EXTRA_EXAMPLES)
$(EX_FORMAT_DEC_OBJS): %.o: %.h
# special dependencies:
# tree.c/vp8.c/bit_reader.c <-> bit_reader_inl.h, endian_inl.h
# bit_writer.c <-> endian_inl.h
src/dec/tree.o: src/utils/bit_reader_inl.h src/utils/endian_inl.h
src/dec/vp8.o: src/utils/bit_reader_inl.h src/utils/endian_inl.h
src/utils/bit_reader.o: src/utils/bit_reader_inl.h src/utils/endian_inl.h
src/utils/bit_writer.o: src/utils/endian_inl.h
%.o: %.c $(HDRS)
$(CC) $(CFLAGS) $(CPPFLAGS) -c $< -o $@
examples/libexample_util.a: $(EX_UTIL_OBJS)
examples/libgif2webp_util.a: $(GIF2WEBP_UTIL_OBJS)
src/libwebpdecoder.a: $(LIBWEBPDECODER_OBJS)
src/libwebp.a: $(LIBWEBP_OBJS)
src/mux/libwebpmux.a: $(LIBWEBPMUX_OBJS)
src/demux/libwebpdemux.a: $(LIBWEBPDEMUX_OBJS)
%.a:
$(AR) $(ARFLAGS) $@ $^
examples/cwebp: examples/cwebp.o $(EX_FORMAT_DEC_OBJS)
examples/dwebp: examples/dwebp.o
examples/gif2webp: examples/gif2webp.o
examples/vwebp: examples/vwebp.o
examples/webpmux: examples/webpmux.o
examples/cwebp: examples/libexample_util.a src/libwebp.a
examples/cwebp: EXTRA_LIBS += $(CWEBP_LIBS)
examples/dwebp: examples/libexample_util.a src/libwebpdecoder.a
examples/dwebp: EXTRA_LIBS += $(DWEBP_LIBS)
examples/gif2webp: examples/libexample_util.a examples/libgif2webp_util.a
examples/gif2webp: src/mux/libwebpmux.a src/libwebp.a
examples/gif2webp: EXTRA_LIBS += $(GIF_LIBS)
examples/gif2webp: EXTRA_FLAGS += -DWEBP_HAVE_GIF
examples/vwebp: examples/libexample_util.a src/demux/libwebpdemux.a
examples/vwebp: src/libwebp.a
examples/vwebp: EXTRA_LIBS += $(GL_LIBS)
examples/vwebp: EXTRA_FLAGS += -DWEBP_HAVE_GL
examples/webpmux: examples/libexample_util.a src/mux/libwebpmux.a
examples/webpmux: src/libwebpdecoder.a
$(OUT_EXAMPLES) $(EXTRA_EXAMPLES):
$(CC) -o $@ $^ $(LDFLAGS)
dist: DESTDIR := dist
dist: OUT_EXAMPLES += $(EXTRA_EXAMPLES)
dist: all
$(INSTALL) -m755 -d $(DESTDIR)/include/webp \
$(DESTDIR)/bin $(DESTDIR)/doc $(DESTDIR)/lib
$(INSTALL) -m755 -s $(OUT_EXAMPLES) $(DESTDIR)/bin
$(INSTALL) -m644 $(HDRS_INSTALLED) $(DESTDIR)/include/webp
$(INSTALL) -m644 src/libwebp.a $(DESTDIR)/lib
$(INSTALL) -m644 src/demux/libwebpdemux.a $(DESTDIR)/lib
$(INSTALL) -m644 src/mux/libwebpmux.a $(DESTDIR)/lib
umask 022; \
for m in man/[cdv]webp.1 man/gif2webp.1 man/webpmux.1; do \
basenam=$$(basename $$m .1); \
$(GROFF) -t -e -man -T utf8 $$m \
| $(COL) -bx >$(DESTDIR)/doc/$${basenam}.txt; \
$(GROFF) -t -e -man -T html $$m \
| $(COL) -bx >$(DESTDIR)/doc/$${basenam}.html; \
done
clean:
rm -f ${OUTPUT} *~ \
src/enc/*.o src/enc/*~ \
$(RM) $(OUTPUT) *~ \
examples/*.o examples/*~ \
src/dec/*.o src/dec/*~ \
examples/*.o examples/*~
src/demux/*.o src/demux/*~ \
src/dsp/*.o src/dsp/*~ \
src/enc/*.o src/enc/*~ \
src/mux/*.o src/mux/*~ \
src/utils/*.o src/utils/*~ \
src/webp/*~ man/*~ doc/*~ swig/*~ \
superclean: clean
rm -rf .git *.log *.cache *~
rm -rf .deps */.deps */*/.deps
rm -rf .libs */.libs */*/.libs
rm -f */*.lo */*/*.lo
rm -f */*.la */*/*.la
rm -f Makefile */Makefile */*/Makefile
rm -f Makefile.in */Makefile.in */*/Makefile.in
rm -f config.log autom4te.cache libtool config.h stamp-h1
rm -f aclocal.m4 compile config.guess config.h.in config.sub config.status
rm -f configure depcomp install-sh ltmain.sh missing src/libwebp.pc
rm -f m4/*
$(RM) -r .git *.log *.cache *~
$(RM) -r .deps */.deps */*/.deps
$(RM) -r .libs */.libs */*/.libs
$(RM) */*.lo */*/*.lo
$(RM) */*.la */*/*.la
$(RM) Makefile */Makefile */*/Makefile
$(RM) Makefile.in */Makefile.in */*/Makefile.in
$(RM) config.log autom4te.cache libtool config.h stamp-h1
$(RM) aclocal.m4 compile
$(RM) config.guess config.h.in config.sub config.status
$(RM) configure depcomp install-sh ltmain.sh missing src/libwebp.pc
$(RM) m4/*
.PHONY: all clean dist ex superclean
.SUFFIXES:

View File

@ -1,2 +1,11 @@
man_MANS = cwebp.1 dwebp.1
if WANT_MUX
man_MANS += webpmux.1
endif
if BUILD_GIF2WEBP
man_MANS += gif2webp.1
endif
if BUILD_VWEBP
man_MANS += vwebp.1
endif
EXTRA_DIST = $(man_MANS)

View File

@ -1,26 +1,30 @@
.\" Hey, EMACS: -*- nroff -*-
.TH CWEBP 1 "March 28, 2011"
.TH CWEBP 1 "Oct 13, 2014"
.SH NAME
cwebp \- compress an image file to a WebP file
.SH SYNOPSIS
.B cwebp
.RI [ options ] " input_file -o output_file.webp
.RI [ options ] " input_file \-o output_file.webp
.br
.SH DESCRIPTION
This manual page documents the
.B cwebp
command.
.PP
\fBcwebp\fP compresses image using the WebP format.
Input format can be either PNG, JPEG, or raw Y'CbCr samples.
When using PNG, the transparency information (alpha channel) is currently
discarded.
\fBcwebp\fP compresses an image using the WebP format.
Input format can be either PNG, JPEG, TIFF, WebP or raw Y'CbCr samples.
.SH OPTIONS
The basic options are:
.TP
.B \-o string
.BI \-o " string
Specify the name of the output WebP file. If omitted, \fBcwebp\fP will
perform compression but only report statistics.
Using "\-" as output name will direct output to 'stdout'.
.TP
.BI \-\- " string
Explicitly specify the input file. This option is useful if the input
file starts with an '\-' for instance. This option must appear \fBlast\fP.
Any other options afterward will be ignored.
.TP
.B \-h, \-help
A short usage summary.
@ -31,41 +35,80 @@ A summary of all the possible options.
.B \-version
Print the version number (as major.minor.revision) and exit.
.TP
.B \-q float
Specify the compression factor between 0 and 100. Small factor
produce smaller file with lower quality. Best quality is achieved
using a value of 100. The default is 75.
.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
.\" Switch on \fBlossless\fP compression mode with the specified level between 0
.\" and 9, with level 0 being the fastest, 9 being the slowest. Fast mode
.\" produces larger file size than slower ones. A good default is \-z 6.
.\" 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.
.TP
.B \-f int
.BI \-alpha_q " int
Specify the compression factor for alpha compression between 0 and 100.
Lossless compression of alpha is achieved using a value of 100, while the lower
values result in a lossy compression. The default is 100.
.TP
.BI \-f " int
Specify the strength of the deblocking filter, between 0 (no filtering)
and 100 (maximum filtering). A value of 0 will turn off any filtering.
Higher value will increase the strength of the filtering process applied
after decoding the picture. The higher the smoother the picture will
after decoding the picture. The higher the value the smoother the picture will
appear. Typical values are usually in the range of 20 to 50.
.TP
.B \-preset string
.BI \-preset " string
Specify a set of pre-defined parameters to suit a particular type of
source material. Possible values are: \fBdefault\fP, \fBphoto\fP,
\fBpicture\fP, \fBdrawing\fP, \fBicon\fP, \fBtext\fP. Since
\fB\-preset\fP overwrites the other parameter's values (except the
\fB\-preset\fP overwrites the other parameters' values (except the
\fB\-q\fP one), this option should preferably appear first in the
order of the arguments.
.TP
.B \-sns int
.BI \-sns " int
Specify the amplitude of the spatial noise shaping. Spatial noise shaping
(or \fBsns\fP for short) refers to a general collection of built-in algorithms
used to decide which area of the picture should use relatively less bits,
and where else to better transfer these bits. The possible range goes from
0 (algorithm is off) to 100 (the maximal effect). The default value is 80.
.TP
.B \-m int
.BI \-m " int
Specify the compression method to use. This parameter controls the
tradeoff between encoding speed and the compressed file size and quality.
trade off between encoding speed and the compressed file size and quality.
Possible values range from 0 to 6. Default value is 4.
When higher values are used, the encoder will spend more time inspecting
additional encoding possibilities and decide on the quality gain.
Lower value can result is faster processing time at the expense of
larger filesize and lower compression quality.
Lower value can result in faster processing time at the expense of
larger file size and lower compression quality.
.TP
.B \-jpeg_like
Change the internal parameter mapping to better match the expected size
of JPEG compression. This flag will generally produce an output file of
similar size to its JPEG equivalent (for the same \fB\-q\fP setting), but
with less visual distortion.
.TP
.B \-mt
Use multi-threading for encoding, if possible. This option is only effective
when using lossy compression on a source with a transparency channel.
.TP
.B \-low_memory
Reduce memory usage of lossy encoding by saving four times the compressed
size (typically). This will make the encoding slower and the output slightly
different in size and distortion. This flag is only effective for methods
3 and up, and is off by default. Note that leaving this flag off will have
some side effects on the bitstream: it forces certain bitstream features
like number of partitions (forced to 1). Note that a more detailed report
of bitstream size is printed by \fBcwebp\fP when using this option.
.TP
.B \-af
Turns auto-filter on. This algorithm will spend additional time optimizing
@ -74,73 +117,173 @@ the filtering strength to reach a well-balanced quality.
.SH ADDITIONAL OPTIONS
More advanced options are:
.TP
.B \-sharpness int
.BI \-sharpness " int
Specify the sharpness of the filtering (if used).
Range is 0 (sharpest) to 7 (least sharp). Default is 0.
.TP
.B \-strong
Use a stronger filtering than the default one (if filtering is being
used thanks to the \fB\-f\fP option). Strong filtering is off by default.
Use strong filtering (if filtering is being used thanks to the
\fB\-f\fP option). Strong filtering is on by default.
.TP
.B \-segments int
.B \-nostrong
Disable strong filtering (if filtering is being used thanks to the
\fB\-f\fP option) and use simple filtering instead.
.TP
.BI \-segments " int
Change the number of partitions to use during the segmentation of the
sns algorithm. Segments should be in range 1 to 4. Default value is 4.
This option has no effect for methods 3 and up, unless \fB\-low_memory\fP
is used.
.TP
.B \-size int
.BI \-partition_limit " int
Degrade quality by limiting the number of bits used by some macroblocks.
Range is 0 (no degradation, the default) to 100 (full degradation).
Useful values are usually around 30-70 for moderately large images.
In the VP8 format, the so-called control partition has a limit of 512k and
is used to store the following information: whether the macroblock is skipped,
which segment it belongs to, whether it is coded as intra 4x4 or intra 16x16
mode, and finally the prediction modes to use for each of the sub-blocks.
For a very large image, 512k only leaves room to few bits per 16x16 macroblock.
The absolute minimum is 4 bits per macroblock. Skip, segment, and mode
information can use up almost all these 4 bits (although the case is unlikely),
which is problematic for very large images. The partition_limit factor controls
how frequently the most bit-costly mode (intra 4x4) will be used. This is
useful in case the 512k limit is reached and the following message is displayed:
\fIError code: 6 (PARTITION0_OVERFLOW: Partition #0 is too big to fit 512k)\fP.
If using \fB-partition_limit\fP is not enough to meet the 512k constraint, one
should use less segments in order to save more header bits per macroblock.
See the \fB-segments\fP option.
.TP
.BI \-size " int
Specify a target size (in bytes) to try and reach for the compressed output.
Compressor will make several pass of partial encoding in order to get as
close as possible to this target.
.TP
.B \-psnr float
.BI \-psnr " float
Specify a target PSNR (in dB) to try and reach for the compressed output.
Compressor will make several pass of partial encoding in order to get as
close as possible to this target.
.TP
.B \-pass int
Set a maximum number of pass to use during the dichotomy used by
.BI \-pass " int
Set a maximum number of passes to use during the dichotomy used by
options \fB\-size\fP or \fB\-psnr\fP. Maximum value is 10.
.TP
.B \-crop x_position y_position width height
.BI \-resize " width height
Resize the source to a rectangle with size \fBwidth\fP x \fBheight\fP.
If either (but not both) of the \fBwidth\fP or \fBheight\fP parameters is 0,
the value will be calculated preserving the aspect-ratio.
.TP
.BI \-crop " x_position y_position width height
Crop the source to a rectangle with top-left corner at coordinates
(x_position, y_position) and size width x height. This cropping area must
be fully contained within the source rectangle.
.B \-s width height
(\fBx_position\fP, \fBy_position\fP) and size \fBwidth\fP x \fBheight\fP.
This cropping area must be fully contained within the source rectangle.
.TP
.BI \-s " width height
Specify that the input file actually consists of raw Y'CbCr samples following
the ITU-R BT.601 recommendation, in 4:2:0 linear format.
The luma plane has size \fBwidth\fP x \fBheight\fP.
.TP
.B \-map int
.BI \-map " int
Output additional ASCII-map of encoding information. Possible map values
range from 1 to 6. This is only meant to help debugging.
.TP
.B \-pre int
Specify a pre-processing filter. This option is a placeholder
and has currently no effect.
.BI \-pre " int
Specify some pre-processing steps. Using a value of '2' will trigger
quality-dependent pseudo-random dithering during RGBA->YUVA conversion
(lossy compression only).
.TP
.BI \-alpha_filter " string
Specify the predictive filtering method for the alpha plane. One of 'none',
\&'fast' or 'best', in increasing complexity and slowness order. Default is
\&'fast'. Internally, alpha filtering is performed using four possible
predictions (none, horizontal, vertical, gradient). The 'best' mode will try
each mode in turn and pick the one which gives the smaller size. The 'fast'
mode will just try to form an a-priori guess without testing all modes.
.TP
.BI \-alpha_method " int
Specify the algorithm used for alpha compression: 0 or 1. Algorithm 0 denotes
no compression, 1 uses WebP lossless format for compression. The default is 1.
.TP
.B \-alpha_cleanup
Modify unseen RGB values under fully transparent area, to help compressibility.
The default is off.
.TP
.BI \-blend_alpha " int
This option blends the alpha channel (if present) with the source using the
background color specified in hexadecimal as 0xrrggbb. The alpha channel is
afterward reset to the opaque value 255.
.TP
.B \-noalpha
Using this option will discard the alpha channel.
.TP
.B \-lossless
Encode the image without any loss.
.TP
.BI \-hint " string
Specify the hint about input image type. Possible values are:
\fBphoto\fP, \fBpicture\fP or \fBgraph\fP.
.TP
.BI \-metadata " string
A comma separated list of metadata to copy from the input to the output if
present.
Valid values: \fBall\fP, \fBnone\fP, \fBexif\fP, \fBicc\fP, \fBxmp\fP.
The default is \fBnone\fP.
Note: each input format may not support all combinations.
.TP
.B \-noasm
Disable all assembly optimizations.
.TP
.B \-v
Print extra information (encoding time in particular).
.TP
.B \-print_psnr
Compute and report average PSNR (Peak-Signal-To-Noise ratio).
.TP
.B \-print_ssim
Compute and report average SSIM (structural similarity
metric, see http://en.wikipedia.org/wiki/SSIM for additional details).
.TP
.B \-print_lsim
Compute and report local similarity metric (sum of lowest error amongst the
collocated pixel neighbors).
.TP
.B \-progress
Report encoding progress in percent.
.TP
.B \-quiet
Do not print anything.
.TP
.B \-short
Only print brief information (output file size and PSNR) for testing purpose.
.SH Examples:
cwebp -q 70 picture.png -o picture.webp
.SH BUGS
Please report all bugs to our issue tracker:
http://code.google.com/p/webp/issues
.br
cwebp -sns 70 -f 50 -strong -af -size 60000 picture.png -o picture.webp
Patches welcome! See this page to get started:
http://www.webmproject.org/code/contribute/submitting-patches/
.SH
.SH SEE ALSO
.BR dwebp (1).
.SH EXAMPLES
cwebp \-q 50 -lossless picture.png \-o picture_lossless.webp
.br
Please refer to http://code.google.com/speed/webp/ for additional
information.
.SH AUTHOR
cwebp \-q 70 picture_with_alpha.png \-o picture_with_alpha.webp
.br
cwebp \-sns 70 \-f 50 \-size 60000 picture.png \-o picture.webp
.br
cwebp \-o picture.webp \-\- \-\-\-picture.png
.SH AUTHORS
\fBcwebp\fP was written by the WebP team.
.br
The latest source tree is available at http://www.webmproject.org/code
.PP
This manual page was written by Pascal Massimino <pascal.massimino@gmail.com>,
for the Debian project (and may be used by others).
.SH SEE ALSO
.BR dwebp (1),
.BR gif2webp (1)
.br
Please refer to http://developers.google.com/speed/webp/ for additional
information.

View File

@ -1,7 +1,7 @@
.\" Hey, EMACS: -*- nroff -*-
.TH DWEBP 1 "March 28, 2011"
.TH DWEBP 1 "July 22, 2014"
.SH NAME
dwebp \- compress a WebP file to an image file
dwebp \- decompress a WebP file to an image file
.SH SYNOPSIS
.B dwebp
.RI [ options ] " input_file.webp
@ -11,7 +11,7 @@ This manual page documents the
.B dwebp
command.
.PP
\fBdwebp\fP decompresses WebP files into PNG or PPM images.
\fBdwebp\fP decompresses WebP files into PNG, PAM, PPM or PGM images.
.SH OPTIONS
The basic options are:
.TP
@ -21,35 +21,125 @@ Print usage summary.
.B \-version
Print the version number (as major.minor.revision) and exit.
.TP
.B \-o string
.BI \-o " string
Specify the name of the output file (as PNG format by default).
Using "-" as output name will direct output to 'stdout'.
.TP
.BI \-\- " string
Explicitly specify the input file. This option is useful if the input
file starts with an '\-' for instance. This option must appear \fBlast\fP.
Any other options afterward will be ignored. If the input file is "\-",
the data will be read from \fIstdin\fP instead of a file.
.TP
.B \-bmp
Change the output format to uncompressed BMP.
.TP
.B \-tiff
Change the output format to uncompressed TIFF.
.TP
.B \-pam
Change the output format to PAM (retains alpha).
.TP
.B \-ppm
Change the output format to PPM.
Change the output format to PPM (discards alpha).
.TP
.B \-pgm
Change the output format to PGM. The output consist of luma/chroma
samples instead of RGB, using the ICM4 layout. This option is mainly
for verification and debugging purpose.
Change the output format to PGM. The output consists of luma/chroma
samples instead of RGB, using the IMC4 layout. This option is mainly
for verification and debugging purposes.
.TP
.B \-yuv
Change the output format to raw YUV. The output consists of
luma/chroma-U/chroma-V samples instead of RGB, saved sequentially as
individual planes. This option is mainly for verification and debugging
purposes.
.TP
.B \-nofancy
Don't use the fancy upscaler for YUV420. This may lead to jaggy
edges (especially the red ones), but should be faster.
.TP
.B \-nofilter
Don't use the in-loop filtering process even if it is required by
the bitstream. This may produce visible blocks on the non-compliant output,
but it will make the decoding faster.
.TP
.BI \-dither " strength
Specify a dithering \fBstrength\fP between 0 and 100. Dithering is a
post-processing effect applied to chroma components in lossy compression.
It helps by smoothing gradients and avoiding banding artifacts.
.\" TODO(jzern): restore post-v0.4.1
.\" .TP
.\" .BI \-alpha_dither
.\" If the compressed file contains a transparency plane that was quantized
.\" during compression, this flag will allow dithering the reconstructed plane
.\" in order to generate smoother transparency gradients.
.TP
.B \-nodither
Disable all dithering (default).
.TP
.B \-mt
Use multi-threading for decoding, if possible.
.TP
.BI \-crop " x_position y_position width height
Crop the decoded picture to a rectangle with top-left corner at coordinates
(\fBx_position\fP, \fBy_position\fP) and size \fBwidth\fP x \fBheight\fP.
This cropping area must be fully contained within the source rectangle.
The top-left corner will be snapped to even coordinates if needed.
This option is meant to reduce the memory needed for cropping large images.
Note: the cropping is applied \fIbefore\fP any scaling.
.\" TODO(jzern): restore post-v0.4.1
.\" .TP
.\" .B \-flip
.\" Flip decoded image vertically (can be useful for OpenGL textures for instance).
.TP
.BI \-scale " width height
Rescale the decoded picture to dimension \fBwidth\fP x \fBheight\fP. This
option is mostly intended to reducing the memory needed to decode large images,
when only a small version is needed (thumbnail, preview, etc.). Note: scaling
is applied \fIafter\fP cropping.
.TP
.B \-v
Print extra information (decoding time in particular).
.TP
.B \-noasm
Disable all assembly optimizations.
.SH Examples:
dwebp picture.webp -o output.png
.SH BUGS
Please report all bugs to our issue tracker:
http://code.google.com/p/webp/issues
.br
dwebp picture.webp -ppm -o output.ppm
Patches welcome! See this page to get started:
http://www.webmproject.org/code/contribute/submitting-patches/
.SH
.SH SEE ALSO
.BR cwebp (1).
.SH EXAMPLES
dwebp picture.webp \-o output.png
.br
Please refer to http://code.google.com/speed/webp/ for additional
information.
.SH AUTHOR
dwebp picture.webp \-ppm \-o output.ppm
.br
dwebp \-o output.ppm \-\- \-\-\-picture.webp
.br
cat picture.webp | dwebp \-o \- \-\- \- > output.ppm
.SH AUTHORS
\fBdwebp\fP was written by the WebP team.
.br
The latest source tree is available at http://www.webmproject.org/code
.PP
This manual page was written by Pascal Massimino <pascal.massimino@gmail.com>,
for the Debian project (and may be used by others).
.SH SEE ALSO
.BR cwebp (1),
.BR gif2webp (1),
.BR webpmux (1)
.br
Please refer to http://developers.google.com/speed/webp/ for additional
information.
.SS Output file format details
PAM: http://netpbm.sourceforge.net/doc/pam.html
.br
PGM: http://netpbm.sourceforge.net/doc/pgm.html
.br
PPM: http://netpbm.sourceforge.net/doc/ppm.html
.br
PNG: http://www.libpng.org/pub/png/png-sitemap.html#info

144
man/gif2webp.1 Normal file
View File

@ -0,0 +1,144 @@
.\" Hey, EMACS: -*- nroff -*-
.TH GIF2WEBP 1 "March 7, 2014"
.SH NAME
gif2webp \- Convert a GIF image to WebP
.SH SYNOPSIS
.B gif2webp
.RI [ options ] " input_file.gif \-o output_file.webp
.br
.SH DESCRIPTION
This manual page documents the
.B gif2webp
command.
.PP
\fBgif2webp\fP converts a GIF image to a WebP image.
.SH OPTIONS
The basic options are:
.TP
.BI \-o " string
Specify the name of the output WebP file. If omitted, \fBgif2webp\fP will
perform conversion but only report statistics.
Using "\-" as output name will direct output to 'stdout'.
.TP
.B \-h, \-help
Usage information.
.TP
.B \-version
Print the version number (as major.minor.revision) and exit.
.TP
.B \-lossy
Encode the image using lossy compression.
.TP
.B \-mixed
Mixed compression mode: optimize compression of the image by picking either
lossy or lossless compression for each frame heuristically.
.TP
.BI \-q " float
Specify the compression factor for RGB channels between 0 and 100. The default
is 75.
.br
In case of lossless compression (default), a small factor enables faster
compression speed, but produces a larger file. Maximum compression is achieved
by using a value of 100.
.br
In case of lossy compression (specified by the \-lossy option), a small factor
produces a smaller file with lower quality. Best quality is achieved by using a
value of 100.
.TP
.BI \-m " int
Specify the compression method to use. This parameter controls the
trade off between encoding speed and the compressed file size and quality.
Possible values range from 0 to 6. Default value is 4.
When higher values are used, the encoder will spend more time inspecting
additional encoding possibilities and decide on the quality gain.
Lower value can result is faster processing time at the expense of
larger file size and lower compression quality.
.TP
.BI \-kmin " int
.TP
.BI \-kmax " int
Specify the minimum and maximum distance between consecutive key frames
(independently decodable frames) in the output animation. The tool will insert
some key frames into the output animation as needed so that this criteria is
satisfied.
.br
A 'kmin' value of 0 will turn off insertion of key frames.
Typical values are in the range 3 to 30. Default values are kmin = 9,
kmax = 17 for lossless compression and kmin = 3, kmax = 5 for lossy compression.
.br
These two options are relevant only for animated images with large number of
frames (>50).
.br
When lower values are used, more frames will be converted to key frames. This
may lead to smaller number of frames required to decode a frame on average,
thereby improving the decoding performance. But this may lead to slightly bigger
file sizes.
Higher values may lead to worse decoding performance, but smaller file sizes.
.br
Some restrictions:
.br
(i) kmin < kmax,
.br
(ii) kmin >= kmax / 2 + 1 and
.br
(iii) kmax - kmin <= 30.
.br
If any of these restrictions are not met, they will be enforced automatically.
.TP
.BI \-metadata " string
A comma separated list of metadata to copy from the input to the output if
present.
Valid values: \fBall\fP, \fBnone\fP, \fBicc\fP, \fBxmp\fP.
The default is \fBxmp\fP.
.TP
.BI \-f " int
For lossy encoding only (specified by the \-lossy option). Specify the strength
of the deblocking filter, between 0 (no filtering) and 100 (maximum filtering).
A value of 0 will turn off any filtering. Higher value will increase the
strength of the filtering process applied after decoding the picture. The higher
the value the smoother the picture will appear. Typical values are usually in
the range of 20 to 50.
.TP
.B \-mt
Use multi-threading for encoding, if possible. This option is only effective
when using lossy compression.
.TP
.B \-v
Print extra information.
.TP
.B \-quiet
Do not print anything.
.SH BUGS
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/
.SH EXAMPLES
gif2webp picture.gif \-o picture.webp
.br
gif2webp \-q 70 picture.gif \-o picture.webp
.br
gif2webp \-lossy \-m 3 picture.gif \-o picture_lossy.webp
.br
gif2webp \-lossy \-f 50 picture.gif \-o picture.webp
.br
gif2webp \-q 70 \-o picture.webp \-\- \-\-\-picture.gif
.SH AUTHORS
\fBgif2webp\fP was written by the WebP team.
.br
The latest source tree is available at http://www.webmproject.org/code
.PP
This manual page was written by Urvang Joshi <urvang@google.com>, for the
Debian project (and may be used by others).
.SH SEE ALSO
.BR cwebp (1),
.BR dwebp (1),
.BR webpmux (1)
.br
Please refer to http://developers.google.com/speed/webp/ for additional
information.

91
man/vwebp.1 Normal file
View File

@ -0,0 +1,91 @@
.\" Hey, EMACS: -*- nroff -*-
.TH VWEBP 1 "July 23, 2014"
.SH NAME
vwebp \- decompress a WebP file and display it in a window
.SH SYNOPSIS
.B vwebp
.RI [ options ] " input_file.webp
.br
.SH DESCRIPTION
This manual page documents the
.B vwebp
command.
.PP
\fBvwebp\fP decompresses a WebP file and displays it in a window using OpenGL.
.SH OPTIONS
.TP
.B \-h
Print usage summary.
.TP
.B \-version
Print version number and exit.
.TP
.B \-noicc
Don't use the ICC profile if present.
.TP
.B \-nofancy
Don't use the fancy YUV420 upscaler.
.TP
.B \-nofilter
Disable in-loop filtering.
.TP
.BI \-dither " strength
Specify a dithering \fBstrength\fP between 0 and 100. Dithering is a
post-processing effect applied to chroma components in lossy compression.
It helps by smoothing gradients and avoiding banding artifacts. Default: 50.
.\" TODO(jzern): restore post-v0.4.1
.\" .TP
.\" .BI \-noalphadither
.\" By default, quantized transparency planes are dithered during decompression,
.\" to smooth the gradients. This flag will prevent this dithering.
.TP
.B \-mt
Use multi-threading for decoding, if possible.
.TP
.B \-info
Display image information on top of the decoded image.
.TP
.BI \-\- " string
Explicitly specify the input file. This option is useful if the input
file starts with an '\-' for instance. This option must appear \fBlast\fP.
Any other options afterward will be ignored. If the input file is "\-",
the data will be read from \fIstdin\fP instead of a file.
.TP
.SH KEYBOARD SHORTCUTS
.TP
.B 'c'
Toggle use of color profile.
.TP
.B 'i'
Overlay file information.
.TP
.B 'q' / 'Q' / ESC
Quit.
.SH BUGS
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/
.SH EXAMPLES
vwebp picture.webp
.br
vwebp picture.webp -mt -dither 0
.br
vwebp \-\- \-\-\-picture.webp
.SH AUTHORS
\fBvwebp\fP was written by the WebP team.
.br
The latest source tree is available at http://www.webmproject.org/code
.PP
This manual page was written for the Debian project (and may be used by others).
.SH SEE ALSO
.BR dwebp (1)
.br
Please refer to http://developers.google.com/speed/webp/ for additional
information.

211
man/webpmux.1 Normal file
View File

@ -0,0 +1,211 @@
.\" Hey, EMACS: -*- nroff -*-
.TH WEBPMUX 1 "August 28, 2014"
.SH NAME
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
.I INPUT
.B \-o
.I OUTPUT
.br
.B webpmux \-set
.I SET_OPTIONS
.I INPUT
.B \-o
.I OUTPUT
.br
.B webpmux \-strip
.I STRIP_OPTIONS
.I INPUT
.B \-o
.I OUTPUT
.br
.B webpmux \-frame
.I FRAME_OPTIONS
.B [ \-frame ... ] [ \-loop
.I LOOP_COUNT
.B ]
.br
.RS 8
.B [ \-bgcolor
.I BACKGROUND_COLOR
.B ] \-o
.I OUTPUT
.RE
.br
.B webpmux \-info
.I INPUT
.br
.B webpmux [\-h|\-help]
.br
.B webpmux \-version
.SH DESCRIPTION
This manual page documents the
.B webpmux
command.
.PP
\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
.B icc
Get ICC profile.
.TP
.B exif
Get EXIF metadata.
.TP
.B xmp
Get XMP metadata.
.TP
.BI frame " n
Get nth frame from an animated image. (n = 0 has a special meaning: last frame).
.SS SET_OPTIONS (\-set)
.TP
.BI icc " file.icc
Set ICC profile.
.P
Where: 'file.icc' contains the ICC profile to be set.
.TP
.BI exif " file.exif
Set EXIF metadata.
.P
Where: 'file.exif' contains the EXIF metadata to be set.
.TP
.BI xmp " file.xmp
Set XMP metadata.
.P
Where: 'file.xmp' contains the XMP metadata to be set.
.SS STRIP_OPTIONS (\-strip)
.TP
.B icc
Strip ICC profile.
.TP
.B exif
Strip EXIF metadata.
.TP
.B xmp
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).
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
default to +0+0.
.TP
.BI \-loop " n
Loop the frames n number of times. 0 indicates the frames should loop forever.
Valid range is 0 to 65535 [Default: 0 (infinite)].
.TP
.BI \-bgcolor " A,R,G,B
Background color of the canvas.
.br
where: 'A', 'R', 'G' and 'B' are integers in the range 0 to 255 specifying the
Alpha, Red, Green and Blue component values respectively
[Default: 255,255,255,255].
.SS INPUT
.TP
Input file in WebP format.
.SS OUTPUT (\-o)
.TP
Output file in WebP format.
.SS Note:
.TP
The nature of EXIF, XMP and ICC data is not checked and is assumed to be valid.
.SH BUGS
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/
.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 1.webp +100 \-frame 2.webp +100+50+50
.br
.RS 8
\-frame 3.webp +100+50+50+1+b \-loop 10 \-bgcolor 255,255,255,255
.br
\-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
webpmux \-get icc \-o image_profile.icc \-\- \-\-\-icc_container.webp
.br
webpmux \-strip icc \-o without_icc.webp \-\- \-\-\-icc_container.webp
.SH AUTHORS
\fBwebpmux\fP is written by the WebP team.
.br
The latest source tree is available at http://www.webmproject.org/code
.PP
This manual page was written by Vikas Arora <vikaas.arora@gmail.com>,
for the Debian project (and may be used by others).
.SH SEE ALSO
.BR cwebp (1),
.BR dwebp (1),
.BR gif2webp (1)
.br
Please refer to http://developers.google.com/speed/webp/ for additional
information.

1
src/.gitignore vendored
View File

@ -1 +0,0 @@
/*.pc

View File

@ -1,16 +1,54 @@
SUBDIRS = dec enc
# The mux and demux libraries depend on libwebp, thus the '.' to force the
# build order so it's available to them.
SUBDIRS = dec enc dsp utils .
if WANT_MUX
SUBDIRS += mux
endif
if WANT_DEMUX
SUBDIRS += demux
endif
AM_CPPFLAGS = -I$(top_srcdir)/src
lib_LTLIBRARIES = libwebp.la
libwebp_la_SOURCES =
libwebp_la_LIBADD = dec/libwebpdecode.la \
enc/libwebpencode.la
libwebp_la_LDFLAGS = -version-info 0:0:0
libwebpinclude_HEADERS = webp/types.h webp/decode.h webp/decode_vp8.h \
webp/encode.h
libwebpincludedir = $(includedir)/webp
if BUILD_LIBWEBPDECODER
lib_LTLIBRARIES += libwebpdecoder.la
endif
common_HEADERS =
common_HEADERS += webp/decode.h
common_HEADERS += webp/types.h
commondir = $(includedir)/webp
libwebp_la_SOURCES =
libwebpinclude_HEADERS =
libwebpinclude_HEADERS += webp/encode.h
noinst_HEADERS =
noinst_HEADERS += webp/format_constants.h
libwebp_la_LIBADD =
libwebp_la_LIBADD += dec/libwebpdecode.la
libwebp_la_LIBADD += dsp/libwebpdsp.la
libwebp_la_LIBADD += enc/libwebpencode.la
libwebp_la_LIBADD += utils/libwebputils.la
# Use '-no-undefined' to declare that libwebp does not depend on any libraries
# 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:2:0
libwebpincludedir = $(includedir)/webp
pkgconfig_DATA = libwebp.pc
if BUILD_LIBWEBPDECODER
libwebpdecoder_la_SOURCES =
libwebpdecoder_la_LIBADD =
libwebpdecoder_la_LIBADD += dec/libwebpdecode.la
libwebpdecoder_la_LIBADD += dsp/libwebpdspdecode.la
libwebpdecoder_la_LIBADD += utils/libwebputilsdecode.la
libwebpdecoder_la_LDFLAGS = -no-undefined -version-info 1:2:0
pkgconfig_DATA += libwebpdecoder.pc
endif
${pkgconfig_DATA}: ${top_builddir}/config.status

View File

@ -1,14 +1,27 @@
AM_CPPFLAGS = -I$(top_srcdir)/src
libwebpdecode_la_SOURCES = bits.h vp8i.h yuv.h bits.c dsp.c frame.c \
quant.c tree.c vp8.c webp.c yuv.c idec.c
libwebpdecode_la_LDFLAGS = -version-info 0:0:0
libwebpdecodeinclude_HEADERS = ../webp/decode.h ../webp/decode_vp8.h ../webp/types.h
libwebpdecodeincludedir = $(includedir)/webp
noinst_HEADERS = bits.h vp8i.h webpi.h yuv.h
noinst_LTLIBRARIES = libwebpdecode.la
# uncomment the following line (and comment the above) if you want
# to install libwebpdecode library.
#lib_LTLIBRARIES = libwebpdecode.la
libwebpdecode_la_SOURCES =
libwebpdecode_la_SOURCES += alpha.c
libwebpdecode_la_SOURCES += alphai.h
libwebpdecode_la_SOURCES += buffer.c
libwebpdecode_la_SOURCES += decode_vp8.h
libwebpdecode_la_SOURCES += frame.c
libwebpdecode_la_SOURCES += idec.c
libwebpdecode_la_SOURCES += io.c
libwebpdecode_la_SOURCES += quant.c
libwebpdecode_la_SOURCES += tree.c
libwebpdecode_la_SOURCES += vp8.c
libwebpdecode_la_SOURCES += vp8i.h
libwebpdecode_la_SOURCES += vp8l.c
libwebpdecode_la_SOURCES += vp8li.h
libwebpdecode_la_SOURCES += webp.c
libwebpdecode_la_SOURCES += webpi.h
libwebpdecodeinclude_HEADERS =
libwebpdecodeinclude_HEADERS += ../webp/decode.h
libwebpdecodeinclude_HEADERS += ../webp/types.h
noinst_HEADERS =
noinst_HEADERS += ../webp/format_constants.h
libwebpdecode_la_CPPFLAGS = $(USE_EXPERIMENTAL_CODE)
libwebpdecodeincludedir = $(includedir)/webp

165
src/dec/alpha.c Normal file
View File

@ -0,0 +1,165 @@
// Copyright 2011 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.
// -----------------------------------------------------------------------------
//
// Alpha-plane decompression.
//
// Author: Skal (pascal.massimino@gmail.com)
#include <stdlib.h>
#include "./alphai.h"
#include "./vp8i.h"
#include "./vp8li.h"
#include "../utils/quant_levels_dec.h"
#include "../utils/utils.h"
#include "../webp/format_constants.h"
//------------------------------------------------------------------------------
// ALPHDecoder object.
ALPHDecoder* ALPHNew(void) {
ALPHDecoder* const dec = (ALPHDecoder*)WebPSafeCalloc(1ULL, sizeof(*dec));
return dec;
}
void ALPHDelete(ALPHDecoder* const dec) {
if (dec != NULL) {
VP8LDelete(dec->vp8l_dec_);
dec->vp8l_dec_ = NULL;
WebPSafeFree(dec);
}
}
//------------------------------------------------------------------------------
// Decoding.
// Initialize alpha decoding by parsing the alpha header and decoding the image
// header for alpha data stored using lossless compression.
// Returns false in case of error in alpha header (data too short, invalid
// compression method or filter, error in lossless header data etc).
static int ALPHInit(ALPHDecoder* const dec, const uint8_t* data,
size_t data_size, int width, int height, uint8_t* output) {
int ok = 0;
const uint8_t* const alpha_data = data + ALPHA_HEADER_LEN;
const size_t alpha_data_size = data_size - ALPHA_HEADER_LEN;
int rsrv;
assert(width > 0 && height > 0);
assert(data != NULL && output != NULL);
dec->width_ = width;
dec->height_ = height;
if (data_size <= ALPHA_HEADER_LEN) {
return 0;
}
dec->method_ = (data[0] >> 0) & 0x03;
dec->filter_ = (data[0] >> 2) & 0x03;
dec->pre_processing_ = (data[0] >> 4) & 0x03;
rsrv = (data[0] >> 6) & 0x03;
if (dec->method_ < ALPHA_NO_COMPRESSION ||
dec->method_ > ALPHA_LOSSLESS_COMPRESSION ||
dec->filter_ >= WEBP_FILTER_LAST ||
dec->pre_processing_ > ALPHA_PREPROCESSED_LEVELS ||
rsrv != 0) {
return 0;
}
if (dec->method_ == ALPHA_NO_COMPRESSION) {
const size_t alpha_decoded_size = dec->width_ * dec->height_;
ok = (alpha_data_size >= alpha_decoded_size);
} else {
assert(dec->method_ == ALPHA_LOSSLESS_COMPRESSION);
ok = VP8LDecodeAlphaHeader(dec, alpha_data, alpha_data_size, output);
}
return ok;
}
// Decodes, unfilters and dequantizes *at least* 'num_rows' rows of alpha
// starting from row number 'row'. It assumes that rows up to (row - 1) have
// already been decoded.
// Returns false in case of bitstream error.
static int ALPHDecode(VP8Decoder* const dec, int row, int num_rows) {
ALPHDecoder* const alph_dec = dec->alph_dec_;
const int width = alph_dec->width_;
const int height = alph_dec->height_;
WebPUnfilterFunc unfilter_func = WebPUnfilters[alph_dec->filter_];
uint8_t* const output = dec->alpha_plane_;
if (alph_dec->method_ == ALPHA_NO_COMPRESSION) {
const size_t offset = row * width;
const size_t num_pixels = num_rows * width;
assert(dec->alpha_data_size_ >= ALPHA_HEADER_LEN + offset + num_pixels);
memcpy(dec->alpha_plane_ + offset,
dec->alpha_data_ + ALPHA_HEADER_LEN + offset, num_pixels);
} else { // alph_dec->method_ == ALPHA_LOSSLESS_COMPRESSION
assert(alph_dec->vp8l_dec_ != NULL);
if (!VP8LDecodeAlphaImageStream(alph_dec, row + num_rows)) {
return 0;
}
}
if (unfilter_func != NULL) {
unfilter_func(width, height, width, row, num_rows, output);
}
if (row + num_rows == dec->pic_hdr_.height_) {
dec->is_alpha_decoded_ = 1;
}
return 1;
}
//------------------------------------------------------------------------------
// Main entry point.
const uint8_t* VP8DecompressAlphaRows(VP8Decoder* const dec,
int row, int num_rows) {
const int width = dec->pic_hdr_.width_;
const int height = dec->pic_hdr_.height_;
if (row < 0 || num_rows <= 0 || row + num_rows > height) {
return NULL; // sanity check.
}
if (row == 0) {
// Initialize decoding.
assert(dec->alpha_plane_ != NULL);
dec->alph_dec_ = ALPHNew();
if (dec->alph_dec_ == NULL) return NULL;
if (!ALPHInit(dec->alph_dec_, dec->alpha_data_, dec->alpha_data_size_,
width, height, dec->alpha_plane_)) {
ALPHDelete(dec->alph_dec_);
dec->alph_dec_ = NULL;
return NULL;
}
// if we allowed use of alpha dithering, check whether it's needed at all
if (dec->alph_dec_->pre_processing_ != ALPHA_PREPROCESSED_LEVELS) {
dec->alpha_dithering_ = 0; // disable dithering
} else {
num_rows = height; // decode everything in one pass
}
}
if (!dec->is_alpha_decoded_) {
int ok = 0;
assert(dec->alph_dec_ != NULL);
ok = ALPHDecode(dec, row, num_rows);
if (ok && dec->alpha_dithering_ > 0) {
ok = WebPDequantizeLevels(dec->alpha_plane_, width, height,
dec->alpha_dithering_);
}
if (!ok || dec->is_alpha_decoded_) {
ALPHDelete(dec->alph_dec_);
dec->alph_dec_ = NULL;
}
if (!ok) return NULL; // Error.
}
// Return a pointer to the current decoded row.
return dec->alpha_plane_ + row * width;
}

55
src/dec/alphai.h Normal file
View File

@ -0,0 +1,55 @@
// Copyright 2013 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.
// -----------------------------------------------------------------------------
//
// Alpha decoder: internal header.
//
// Author: Urvang (urvang@google.com)
#ifndef WEBP_DEC_ALPHAI_H_
#define WEBP_DEC_ALPHAI_H_
#include "./webpi.h"
#include "../utils/filters.h"
#ifdef __cplusplus
extern "C" {
#endif
struct VP8LDecoder; // Defined in dec/vp8li.h.
typedef struct ALPHDecoder ALPHDecoder;
struct ALPHDecoder {
int width_;
int height_;
int method_;
WEBP_FILTER_TYPE filter_;
int pre_processing_;
struct VP8LDecoder* vp8l_dec_;
VP8Io io_;
int use_8b_decode; // Although alpha channel requires only 1 byte per
// pixel, sometimes VP8LDecoder may need to allocate
// 4 bytes per pixel internally during decode.
};
//------------------------------------------------------------------------------
// internal functions. Not public.
// Allocates a new alpha decoder instance.
ALPHDecoder* ALPHNew(void);
// Clears and deallocates an alpha decoder instance.
void ALPHDelete(ALPHDecoder* const dec);
//------------------------------------------------------------------------------
#ifdef __cplusplus
} // extern "C"
#endif
#endif /* WEBP_DEC_ALPHAI_H_ */

View File

@ -1,79 +0,0 @@
// Copyright 2010 Google Inc.
//
// This code is licensed under the same terms as WebM:
// Software License Agreement: http://www.webmproject.org/license/software/
// Additional IP Rights Grant: http://www.webmproject.org/license/additional/
// -----------------------------------------------------------------------------
//
// Boolean decoder
//
// Author: Skal (pascal.massimino@gmail.com)
#include "bits.h"
#if defined(__cplusplus) || defined(c_plusplus)
extern "C" {
#endif
//-----------------------------------------------------------------------------
// VP8BitReader
void VP8InitBitReader(VP8BitReader* const br,
const uint8_t* const start, const uint8_t* const end) {
assert(br);
assert(start);
assert(start <= end);
br->range_ = 255 - 1;
br->buf_ = start;
br->buf_end_ = end;
br->value_ = 0;
br->missing_ = 8;
br->eof_ = 0;
}
const uint8_t kVP8Log2Range[128] = {
7, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4,
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
0
};
// range = ((range + 1) << kVP8Log2Range[range]) - 1
const uint8_t kVP8NewRange[128] = {
127, 127, 191, 127, 159, 191, 223, 127, 143, 159, 175, 191, 207, 223, 239,
127, 135, 143, 151, 159, 167, 175, 183, 191, 199, 207, 215, 223, 231, 239,
247, 127, 131, 135, 139, 143, 147, 151, 155, 159, 163, 167, 171, 175, 179,
183, 187, 191, 195, 199, 203, 207, 211, 215, 219, 223, 227, 231, 235, 239,
243, 247, 251, 127, 129, 131, 133, 135, 137, 139, 141, 143, 145, 147, 149,
151, 153, 155, 157, 159, 161, 163, 165, 167, 169, 171, 173, 175, 177, 179,
181, 183, 185, 187, 189, 191, 193, 195, 197, 199, 201, 203, 205, 207, 209,
211, 213, 215, 217, 219, 221, 223, 225, 227, 229, 231, 233, 235, 237, 239,
241, 243, 245, 247, 249, 251, 253, 127
};
//-----------------------------------------------------------------------------
// Higher-level calls
uint32_t VP8GetValue(VP8BitReader* const br, int bits) {
uint32_t v = 0;
while (bits-- > 0) {
v |= VP8GetBit(br, 0x80) << bits;
}
return v;
}
int32_t VP8GetSignedValue(VP8BitReader* const br, int bits) {
const int value = VP8GetValue(br, bits);
return VP8Get(br) ? -value : value;
}
//-----------------------------------------------------------------------------
#if defined(__cplusplus) || defined(c_plusplus)
} // extern "C"
#endif

View File

@ -1,107 +0,0 @@
// Copyright 2010 Google Inc.
//
// This code is licensed under the same terms as WebM:
// Software License Agreement: http://www.webmproject.org/license/software/
// Additional IP Rights Grant: http://www.webmproject.org/license/additional/
// -----------------------------------------------------------------------------
//
// Boolean decoder
//
// Author: Skal (pascal.massimino@gmail.com)
#ifndef WEBP_DEC_BITS_H_
#define WEBP_DEC_BITS_H_
#include <assert.h>
#include "webp/decode_vp8.h"
#if defined(__cplusplus) || defined(c_plusplus)
extern "C" {
#endif
//-----------------------------------------------------------------------------
// Bitreader and code-tree reader
typedef struct {
const uint8_t* buf_; // next byte to be read
const uint8_t* buf_end_; // end of read buffer
int eof_; // true if input is exhausted
// boolean decoder
uint32_t range_; // current range minus 1. In [127, 254] interval.
uint32_t value_; // current value
int missing_; // number of missing bits in value_ (8bit)
} VP8BitReader;
// Initialize the bit reader and the boolean decoder.
void VP8InitBitReader(VP8BitReader* const br,
const uint8_t* const start, const uint8_t* const end);
// return the next value made of 'num_bits' bits
uint32_t VP8GetValue(VP8BitReader* const br, int num_bits);
static inline uint32_t VP8Get(VP8BitReader* const br) {
return VP8GetValue(br, 1);
}
// return the next value with sign-extension.
int32_t VP8GetSignedValue(VP8BitReader* const br, int num_bits);
// Read a bit with proba 'prob'. Speed-critical function!
extern const uint8_t kVP8Log2Range[128];
extern const uint8_t kVP8NewRange[128];
static inline uint32_t VP8GetByte(VP8BitReader* const br) {
assert(br);
if (br->buf_ < br->buf_end_) {
assert(br->buf_);
return *br->buf_++;
}
br->eof_ = 1;
return 0xff;
}
static inline uint32_t VP8BitUpdate(VP8BitReader* const br, uint32_t split) {
uint32_t bit;
// Make sure we have a least 8 bits in 'value_'
if (br->missing_ > 0) {
br->value_ |= VP8GetByte(br) << br->missing_;
br->missing_ -= 8;
}
bit = ((br->value_ >> 8) > split);
if (bit) {
br->range_ -= split + 1;
br->value_ -= (split + 1) << 8;
} else {
br->range_ = split;
}
return bit;
}
static inline void VP8Shift(VP8BitReader* const br) {
// range_ is in [0..127] interval here.
const int shift = kVP8Log2Range[br->range_];
br->range_ = kVP8NewRange[br->range_];
br->value_ <<= shift;
br->missing_ += shift;
}
static inline uint32_t VP8GetBit(VP8BitReader* const br, int prob) {
const uint32_t split = (br->range_ * prob) >> 8;
const uint32_t bit = VP8BitUpdate(br, split);
if (br->range_ < 0x7f) {
VP8Shift(br);
}
return bit;
}
static inline int VP8GetSigned(VP8BitReader* const br, int v) {
const uint32_t split = br->range_ >> 1;
const uint32_t bit = VP8BitUpdate(br, split);
VP8Shift(br);
return bit ? -v : v;
}
#if defined(__cplusplus) || defined(c_plusplus)
} // extern "C"
#endif
#endif // WEBP_DEC_BITS_H_

251
src/dec/buffer.c Normal file
View File

@ -0,0 +1,251 @@
// Copyright 2011 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.
// -----------------------------------------------------------------------------
//
// Everything about WebPDecBuffer
//
// Author: Skal (pascal.massimino@gmail.com)
#include <stdlib.h>
#include "./vp8i.h"
#include "./webpi.h"
#include "../utils/utils.h"
//------------------------------------------------------------------------------
// WebPDecBuffer
// Number of bytes per pixel for the different color-spaces.
static const int kModeBpp[MODE_LAST] = {
3, 4, 3, 4, 4, 2, 2,
4, 4, 4, 2, // pre-multiplied modes
1, 1 };
// Check that webp_csp_mode is within the bounds of WEBP_CSP_MODE.
// Convert to an integer to handle both the unsigned/signed enum cases
// without the need for casting to remove type limit warnings.
static int IsValidColorspace(int webp_csp_mode) {
return (webp_csp_mode >= MODE_RGB && webp_csp_mode < MODE_LAST);
}
static VP8StatusCode CheckDecBuffer(const WebPDecBuffer* const buffer) {
int ok = 1;
const WEBP_CSP_MODE mode = buffer->colorspace;
const int width = buffer->width;
const int height = buffer->height;
if (!IsValidColorspace(mode)) {
ok = 0;
} else if (!WebPIsRGBMode(mode)) { // YUV checks
const WebPYUVABuffer* const buf = &buffer->u.YUVA;
const int y_stride = abs(buf->y_stride);
const int u_stride = abs(buf->u_stride);
const int v_stride = abs(buf->v_stride);
const int a_stride = abs(buf->a_stride);
const uint64_t y_size = (uint64_t)y_stride * height;
const uint64_t u_size = (uint64_t)u_stride * ((height + 1) / 2);
const uint64_t v_size = (uint64_t)v_stride * ((height + 1) / 2);
const uint64_t a_size = (uint64_t)a_stride * height;
ok &= (y_size <= buf->y_size);
ok &= (u_size <= buf->u_size);
ok &= (v_size <= buf->v_size);
ok &= (y_stride >= width);
ok &= (u_stride >= (width + 1) / 2);
ok &= (v_stride >= (width + 1) / 2);
ok &= (buf->y != NULL);
ok &= (buf->u != NULL);
ok &= (buf->v != NULL);
if (mode == MODE_YUVA) {
ok &= (a_stride >= width);
ok &= (a_size <= buf->a_size);
ok &= (buf->a != NULL);
}
} else { // RGB checks
const WebPRGBABuffer* const buf = &buffer->u.RGBA;
const int stride = abs(buf->stride);
const uint64_t size = (uint64_t)stride * height;
ok &= (size <= buf->size);
ok &= (stride >= width * kModeBpp[mode]);
ok &= (buf->rgba != NULL);
}
return ok ? VP8_STATUS_OK : VP8_STATUS_INVALID_PARAM;
}
static VP8StatusCode AllocateBuffer(WebPDecBuffer* const buffer) {
const int w = buffer->width;
const int h = buffer->height;
const WEBP_CSP_MODE mode = buffer->colorspace;
if (w <= 0 || h <= 0 || !IsValidColorspace(mode)) {
return VP8_STATUS_INVALID_PARAM;
}
if (!buffer->is_external_memory && buffer->private_memory == NULL) {
uint8_t* output;
int uv_stride = 0, a_stride = 0;
uint64_t uv_size = 0, a_size = 0, total_size;
// We need memory and it hasn't been allocated yet.
// => initialize output buffer, now that dimensions are known.
const int stride = w * kModeBpp[mode];
const uint64_t size = (uint64_t)stride * h;
if (!WebPIsRGBMode(mode)) {
uv_stride = (w + 1) / 2;
uv_size = (uint64_t)uv_stride * ((h + 1) / 2);
if (mode == MODE_YUVA) {
a_stride = w;
a_size = (uint64_t)a_stride * h;
}
}
total_size = size + 2 * uv_size + a_size;
// Security/sanity checks
output = (uint8_t*)WebPSafeMalloc(total_size, sizeof(*output));
if (output == NULL) {
return VP8_STATUS_OUT_OF_MEMORY;
}
buffer->private_memory = output;
if (!WebPIsRGBMode(mode)) { // YUVA initialization
WebPYUVABuffer* const buf = &buffer->u.YUVA;
buf->y = output;
buf->y_stride = stride;
buf->y_size = (size_t)size;
buf->u = output + size;
buf->u_stride = uv_stride;
buf->u_size = (size_t)uv_size;
buf->v = output + size + uv_size;
buf->v_stride = uv_stride;
buf->v_size = (size_t)uv_size;
if (mode == MODE_YUVA) {
buf->a = output + size + 2 * uv_size;
}
buf->a_size = (size_t)a_size;
buf->a_stride = a_stride;
} else { // RGBA initialization
WebPRGBABuffer* const buf = &buffer->u.RGBA;
buf->rgba = output;
buf->stride = stride;
buf->size = (size_t)size;
}
}
return CheckDecBuffer(buffer);
}
VP8StatusCode WebPFlipBuffer(WebPDecBuffer* const buffer) {
if (buffer == NULL) {
return VP8_STATUS_INVALID_PARAM;
}
if (WebPIsRGBMode(buffer->colorspace)) {
WebPRGBABuffer* const buf = &buffer->u.RGBA;
buf->rgba += (buffer->height - 1) * buf->stride;
buf->stride = -buf->stride;
} else {
WebPYUVABuffer* const buf = &buffer->u.YUVA;
const int H = buffer->height;
buf->y += (H - 1) * buf->y_stride;
buf->y_stride = -buf->y_stride;
buf->u += ((H - 1) >> 1) * buf->u_stride;
buf->u_stride = -buf->u_stride;
buf->v += ((H - 1) >> 1) * buf->v_stride;
buf->v_stride = -buf->v_stride;
if (buf->a != NULL) {
buf->a += (H - 1) * buf->a_stride;
buf->a_stride = -buf->a_stride;
}
}
return VP8_STATUS_OK;
}
VP8StatusCode WebPAllocateDecBuffer(int w, int h,
const WebPDecoderOptions* const options,
WebPDecBuffer* const out) {
VP8StatusCode status;
if (out == NULL || w <= 0 || h <= 0) {
return VP8_STATUS_INVALID_PARAM;
}
if (options != NULL) { // First, apply options if there is any.
if (options->use_cropping) {
const int cw = options->crop_width;
const int ch = options->crop_height;
const int x = options->crop_left & ~1;
const int y = options->crop_top & ~1;
if (x < 0 || y < 0 || cw <= 0 || ch <= 0 || x + cw > w || y + ch > h) {
return VP8_STATUS_INVALID_PARAM; // out of frame boundary.
}
w = cw;
h = ch;
}
if (options->use_scaling) {
if (options->scaled_width <= 0 || options->scaled_height <= 0) {
return VP8_STATUS_INVALID_PARAM;
}
w = options->scaled_width;
h = options->scaled_height;
}
}
out->width = w;
out->height = h;
// Then, allocate buffer for real.
status = AllocateBuffer(out);
if (status != VP8_STATUS_OK) return status;
#if WEBP_DECODER_ABI_VERSION > 0x0203
// Use the stride trick if vertical flip is needed.
if (options != NULL && options->flip) {
status = WebPFlipBuffer(out);
}
#endif
return status;
}
//------------------------------------------------------------------------------
// constructors / destructors
int WebPInitDecBufferInternal(WebPDecBuffer* buffer, int version) {
if (WEBP_ABI_IS_INCOMPATIBLE(version, WEBP_DECODER_ABI_VERSION)) {
return 0; // version mismatch
}
if (buffer == NULL) return 0;
memset(buffer, 0, sizeof(*buffer));
return 1;
}
void WebPFreeDecBuffer(WebPDecBuffer* buffer) {
if (buffer != NULL) {
if (!buffer->is_external_memory) {
WebPSafeFree(buffer->private_memory);
}
buffer->private_memory = NULL;
}
}
void WebPCopyDecBuffer(const WebPDecBuffer* const src,
WebPDecBuffer* const dst) {
if (src != NULL && dst != NULL) {
*dst = *src;
if (src->private_memory != NULL) {
dst->is_external_memory = 1; // dst buffer doesn't own the memory.
dst->private_memory = NULL;
}
}
}
// Copy and transfer ownership from src to dst (beware of parameter order!)
void WebPGrabDecBuffer(WebPDecBuffer* const src, WebPDecBuffer* const dst) {
if (src != NULL && dst != NULL) {
*dst = *src;
if (src->private_memory != NULL) {
src->is_external_memory = 1; // src relinquishes ownership
src->private_memory = NULL;
}
}
}
//------------------------------------------------------------------------------

185
src/dec/decode_vp8.h Normal file
View File

@ -0,0 +1,185 @@
// Copyright 2010 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.
// -----------------------------------------------------------------------------
//
// Low-level API for VP8 decoder
//
// Author: Skal (pascal.massimino@gmail.com)
#ifndef WEBP_WEBP_DECODE_VP8_H_
#define WEBP_WEBP_DECODE_VP8_H_
#include "../webp/decode.h"
#ifdef __cplusplus
extern "C" {
#endif
//------------------------------------------------------------------------------
// Lower-level API
//
// These functions provide fine-grained control of the decoding process.
// The call flow should resemble:
//
// VP8Io io;
// VP8InitIo(&io);
// io.data = data;
// io.data_size = size;
// /* customize io's functions (setup()/put()/teardown()) if needed. */
//
// VP8Decoder* dec = VP8New();
// bool ok = VP8Decode(dec);
// if (!ok) printf("Error: %s\n", VP8StatusMessage(dec));
// VP8Delete(dec);
// return ok;
// Input / Output
typedef struct VP8Io VP8Io;
typedef int (*VP8IoPutHook)(const VP8Io* io);
typedef int (*VP8IoSetupHook)(VP8Io* io);
typedef void (*VP8IoTeardownHook)(const VP8Io* io);
struct VP8Io {
// set by VP8GetHeaders()
int width, height; // picture dimensions, in pixels (invariable).
// These are the original, uncropped dimensions.
// The actual area passed to put() is stored
// in mb_w / mb_h fields.
// set before calling put()
int mb_y; // position of the current rows (in pixels)
int mb_w; // number of columns in the sample
int mb_h; // number of rows in the sample
const uint8_t* y, *u, *v; // rows to copy (in yuv420 format)
int y_stride; // row stride for luma
int uv_stride; // row stride for chroma
void* opaque; // user data
// called when fresh samples are available. Currently, samples are in
// YUV420 format, and can be up to width x 24 in size (depending on the
// in-loop filtering level, e.g.). Should return false in case of error
// or abort request. The actual size of the area to update is mb_w x mb_h
// in size, taking cropping into account.
VP8IoPutHook put;
// called just before starting to decode the blocks.
// Must return false in case of setup error, true otherwise. If false is
// returned, teardown() will NOT be called. But if the setup succeeded
// and true is returned, then teardown() will always be called afterward.
VP8IoSetupHook setup;
// Called just after block decoding is finished (or when an error occurred
// during put()). Is NOT called if setup() failed.
VP8IoTeardownHook teardown;
// this is a recommendation for the user-side yuv->rgb converter. This flag
// is set when calling setup() hook and can be overwritten by it. It then
// can be taken into consideration during the put() method.
int fancy_upsampling;
// Input buffer.
size_t data_size;
const uint8_t* data;
// If true, in-loop filtering will not be performed even if present in the
// bitstream. Switching off filtering may speed up decoding at the expense
// of more visible blocking. Note that output will also be non-compliant
// with the VP8 specifications.
int bypass_filtering;
// Cropping parameters.
int use_cropping;
int crop_left, crop_right, crop_top, crop_bottom;
// Scaling parameters.
int use_scaling;
int scaled_width, scaled_height;
// If non NULL, pointer to the alpha data (if present) corresponding to the
// start of the current row (That is: it is pre-offset by mb_y and takes
// cropping into account).
const uint8_t* a;
};
// Internal, version-checked, entry point
int VP8InitIoInternal(VP8Io* const, int);
// Set the custom IO function pointers and user-data. The setter for IO hooks
// should be called before initiating incremental decoding. Returns true if
// WebPIDecoder object is successfully modified, false otherwise.
int WebPISetIOHooks(WebPIDecoder* const idec,
VP8IoPutHook put,
VP8IoSetupHook setup,
VP8IoTeardownHook teardown,
void* user_data);
// Main decoding object. This is an opaque structure.
typedef struct VP8Decoder VP8Decoder;
// Create a new decoder object.
VP8Decoder* VP8New(void);
// Must be called to make sure 'io' is initialized properly.
// Returns false in case of version mismatch. Upon such failure, no other
// decoding function should be called (VP8Decode, VP8GetHeaders, ...)
static WEBP_INLINE int VP8InitIo(VP8Io* const io) {
return VP8InitIoInternal(io, WEBP_DECODER_ABI_VERSION);
}
// Decode the VP8 frame header. Returns true if ok.
// Note: 'io->data' must be pointing to the start of the VP8 frame header.
int VP8GetHeaders(VP8Decoder* const dec, VP8Io* const io);
// Decode a picture. Will call VP8GetHeaders() if it wasn't done already.
// Returns false in case of error.
int VP8Decode(VP8Decoder* const dec, VP8Io* const io);
// Return current status of the decoder:
VP8StatusCode VP8Status(VP8Decoder* const dec);
// return readable string corresponding to the last status.
const char* VP8StatusMessage(VP8Decoder* const dec);
// Resets the decoder in its initial state, reclaiming memory.
// Not a mandatory call between calls to VP8Decode().
void VP8Clear(VP8Decoder* const dec);
// Destroy the decoder object.
void VP8Delete(VP8Decoder* const dec);
//------------------------------------------------------------------------------
// Miscellaneous VP8/VP8L bitstream probing functions.
// Returns true if the next 3 bytes in data contain the VP8 signature.
WEBP_EXTERN(int) VP8CheckSignature(const uint8_t* const data, size_t data_size);
// Validates the VP8 data-header and retrieves basic header information viz
// width and height. Returns 0 in case of formatting error. *width/*height
// can be passed NULL.
WEBP_EXTERN(int) VP8GetInfo(
const uint8_t* data,
size_t data_size, // data available so far
size_t chunk_size, // total data size expected in the chunk
int* const width, int* const height);
// Returns true if the next byte(s) in data is a VP8L signature.
WEBP_EXTERN(int) VP8LCheckSignature(const uint8_t* const data, size_t size);
// Validates the VP8L data-header and retrieves basic header information viz
// width, height and alpha. Returns 0 in case of formatting error.
// width/height/has_alpha can be passed NULL.
WEBP_EXTERN(int) VP8LGetInfo(
const uint8_t* data, size_t data_size, // data available so far
int* const width, int* const height, int* const has_alpha);
#ifdef __cplusplus
} // extern "C"
#endif
#endif /* WEBP_WEBP_DECODE_VP8_H_ */

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

648
src/dec/io.c Normal file
View File

@ -0,0 +1,648 @@
// Copyright 2011 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.
// -----------------------------------------------------------------------------
//
// functions for sample output.
//
// Author: Skal (pascal.massimino@gmail.com)
#include <assert.h>
#include <stdlib.h>
#include "../dec/vp8i.h"
#include "./webpi.h"
#include "../dsp/dsp.h"
#include "../dsp/yuv.h"
#include "../utils/utils.h"
//------------------------------------------------------------------------------
// Main YUV<->RGB conversion functions
static int EmitYUV(const VP8Io* const io, WebPDecParams* const p) {
WebPDecBuffer* output = p->output;
const WebPYUVABuffer* const buf = &output->u.YUVA;
uint8_t* const y_dst = buf->y + io->mb_y * buf->y_stride;
uint8_t* const u_dst = buf->u + (io->mb_y >> 1) * buf->u_stride;
uint8_t* const v_dst = buf->v + (io->mb_y >> 1) * buf->v_stride;
const int mb_w = io->mb_w;
const int mb_h = io->mb_h;
const int uv_w = (mb_w + 1) / 2;
const int uv_h = (mb_h + 1) / 2;
int j;
for (j = 0; j < mb_h; ++j) {
memcpy(y_dst + j * buf->y_stride, io->y + j * io->y_stride, mb_w);
}
for (j = 0; j < uv_h; ++j) {
memcpy(u_dst + j * buf->u_stride, io->u + j * io->uv_stride, uv_w);
memcpy(v_dst + j * buf->v_stride, io->v + j * io->uv_stride, uv_w);
}
return io->mb_h;
}
// Point-sampling U/V sampler.
static int EmitSampledRGB(const VP8Io* const io, WebPDecParams* const p) {
WebPDecBuffer* const output = p->output;
WebPRGBABuffer* const buf = &output->u.RGBA;
uint8_t* const dst = buf->rgba + io->mb_y * buf->stride;
WebPSamplerProcessPlane(io->y, io->y_stride,
io->u, io->v, io->uv_stride,
dst, buf->stride, io->mb_w, io->mb_h,
WebPSamplers[output->colorspace]);
return io->mb_h;
}
//------------------------------------------------------------------------------
// YUV444 -> RGB conversion
#if 0 // TODO(skal): this is for future rescaling.
static int EmitRGB(const VP8Io* const io, WebPDecParams* const p) {
WebPDecBuffer* output = p->output;
const WebPRGBABuffer* const buf = &output->u.RGBA;
uint8_t* dst = buf->rgba + io->mb_y * buf->stride;
const uint8_t* y_src = io->y;
const uint8_t* u_src = io->u;
const uint8_t* v_src = io->v;
const WebPYUV444Converter convert = WebPYUV444Converters[output->colorspace];
const int mb_w = io->mb_w;
const int last = io->mb_h;
int j;
for (j = 0; j < last; ++j) {
convert(y_src, u_src, v_src, dst, mb_w);
y_src += io->y_stride;
u_src += io->uv_stride;
v_src += io->uv_stride;
dst += buf->stride;
}
return io->mb_h;
}
#endif
//------------------------------------------------------------------------------
// Fancy upsampling
#ifdef FANCY_UPSAMPLING
static int EmitFancyRGB(const VP8Io* const io, WebPDecParams* const p) {
int num_lines_out = io->mb_h; // a priori guess
const WebPRGBABuffer* const buf = &p->output->u.RGBA;
uint8_t* dst = buf->rgba + io->mb_y * buf->stride;
WebPUpsampleLinePairFunc upsample = WebPUpsamplers[p->output->colorspace];
const uint8_t* cur_y = io->y;
const uint8_t* cur_u = io->u;
const uint8_t* cur_v = io->v;
const uint8_t* top_u = p->tmp_u;
const uint8_t* top_v = p->tmp_v;
int y = io->mb_y;
const int y_end = io->mb_y + io->mb_h;
const int mb_w = io->mb_w;
const int uv_w = (mb_w + 1) / 2;
if (y == 0) {
// First line is special cased. We mirror the u/v samples at boundary.
upsample(cur_y, NULL, cur_u, cur_v, cur_u, cur_v, dst, NULL, mb_w);
} else {
// We can finish the left-over line from previous call.
upsample(p->tmp_y, cur_y, top_u, top_v, cur_u, cur_v,
dst - buf->stride, dst, mb_w);
++num_lines_out;
}
// Loop over each output pairs of row.
for (; y + 2 < y_end; y += 2) {
top_u = cur_u;
top_v = cur_v;
cur_u += io->uv_stride;
cur_v += io->uv_stride;
dst += 2 * buf->stride;
cur_y += 2 * io->y_stride;
upsample(cur_y - io->y_stride, cur_y,
top_u, top_v, cur_u, cur_v,
dst - buf->stride, dst, mb_w);
}
// move to last row
cur_y += io->y_stride;
if (io->crop_top + y_end < io->crop_bottom) {
// Save the unfinished samples for next call (as we're not done yet).
memcpy(p->tmp_y, cur_y, mb_w * sizeof(*p->tmp_y));
memcpy(p->tmp_u, cur_u, uv_w * sizeof(*p->tmp_u));
memcpy(p->tmp_v, cur_v, uv_w * sizeof(*p->tmp_v));
// The fancy upsampler leaves a row unfinished behind
// (except for the very last row)
num_lines_out--;
} else {
// Process the very last row of even-sized picture
if (!(y_end & 1)) {
upsample(cur_y, NULL, cur_u, cur_v, cur_u, cur_v,
dst + buf->stride, NULL, mb_w);
}
}
return num_lines_out;
}
#endif /* FANCY_UPSAMPLING */
//------------------------------------------------------------------------------
static int EmitAlphaYUV(const VP8Io* const io, WebPDecParams* const p) {
const uint8_t* alpha = io->a;
const WebPYUVABuffer* const buf = &p->output->u.YUVA;
const int mb_w = io->mb_w;
const int mb_h = io->mb_h;
uint8_t* dst = buf->a + io->mb_y * buf->a_stride;
int j;
if (alpha != NULL) {
for (j = 0; j < mb_h; ++j) {
memcpy(dst, alpha, mb_w * sizeof(*dst));
alpha += io->width;
dst += buf->a_stride;
}
} else if (buf->a != NULL) {
// the user requested alpha, but there is none, set it to opaque.
for (j = 0; j < mb_h; ++j) {
memset(dst, 0xff, mb_w * sizeof(*dst));
dst += buf->a_stride;
}
}
return 0;
}
static int GetAlphaSourceRow(const VP8Io* const io,
const uint8_t** alpha, int* const num_rows) {
int start_y = io->mb_y;
*num_rows = io->mb_h;
// Compensate for the 1-line delay of the fancy upscaler.
// This is similar to EmitFancyRGB().
if (io->fancy_upsampling) {
if (start_y == 0) {
// We don't process the last row yet. It'll be done during the next call.
--*num_rows;
} else {
--start_y;
// Fortunately, *alpha data is persistent, so we can go back
// one row and finish alpha blending, now that the fancy upscaler
// completed the YUV->RGB interpolation.
*alpha -= io->width;
}
if (io->crop_top + io->mb_y + io->mb_h == io->crop_bottom) {
// If it's the very last call, we process all the remaining rows!
*num_rows = io->crop_bottom - io->crop_top - start_y;
}
}
return start_y;
}
static int EmitAlphaRGB(const VP8Io* const io, WebPDecParams* const p) {
const uint8_t* alpha = io->a;
if (alpha != NULL) {
const int mb_w = io->mb_w;
const WEBP_CSP_MODE colorspace = p->output->colorspace;
const int alpha_first =
(colorspace == MODE_ARGB || colorspace == MODE_Argb);
const WebPRGBABuffer* const buf = &p->output->u.RGBA;
int num_rows;
const int start_y = GetAlphaSourceRow(io, &alpha, &num_rows);
uint8_t* const base_rgba = buf->rgba + start_y * buf->stride;
uint8_t* dst = base_rgba + (alpha_first ? 0 : 3);
uint32_t alpha_mask = 0xff;
int i, j;
for (j = 0; j < num_rows; ++j) {
for (i = 0; i < mb_w; ++i) {
const uint32_t alpha_value = alpha[i];
dst[4 * i] = alpha_value;
alpha_mask &= alpha_value;
}
alpha += io->width;
dst += buf->stride;
}
// alpha_mask is < 0xff if there's non-trivial alpha to premultiply with.
if (alpha_mask != 0xff && WebPIsPremultipliedMode(colorspace)) {
WebPApplyAlphaMultiply(base_rgba, alpha_first,
mb_w, num_rows, buf->stride);
}
}
return 0;
}
static int EmitAlphaRGBA4444(const VP8Io* const io, WebPDecParams* const p) {
const uint8_t* alpha = io->a;
if (alpha != NULL) {
const int mb_w = io->mb_w;
const WEBP_CSP_MODE colorspace = p->output->colorspace;
const WebPRGBABuffer* const buf = &p->output->u.RGBA;
int num_rows;
const int start_y = GetAlphaSourceRow(io, &alpha, &num_rows);
uint8_t* const base_rgba = buf->rgba + start_y * buf->stride;
#ifdef WEBP_SWAP_16BIT_CSP
uint8_t* alpha_dst = base_rgba;
#else
uint8_t* alpha_dst = base_rgba + 1;
#endif
uint32_t alpha_mask = 0x0f;
int i, j;
for (j = 0; j < num_rows; ++j) {
for (i = 0; i < mb_w; ++i) {
// Fill in the alpha value (converted to 4 bits).
const uint32_t alpha_value = alpha[i] >> 4;
alpha_dst[2 * i] = (alpha_dst[2 * i] & 0xf0) | alpha_value;
alpha_mask &= alpha_value;
}
alpha += io->width;
alpha_dst += buf->stride;
}
if (alpha_mask != 0x0f && WebPIsPremultipliedMode(colorspace)) {
WebPApplyAlphaMultiply4444(base_rgba, mb_w, num_rows, buf->stride);
}
}
return 0;
}
//------------------------------------------------------------------------------
// YUV rescaling (no final RGB conversion needed)
static int Rescale(const uint8_t* src, int src_stride,
int new_lines, WebPRescaler* const wrk) {
int num_lines_out = 0;
while (new_lines > 0) { // import new contributions of source rows.
const int lines_in = WebPRescalerImport(wrk, new_lines, src, src_stride);
src += lines_in * src_stride;
new_lines -= lines_in;
num_lines_out += WebPRescalerExport(wrk); // emit output row(s)
}
return num_lines_out;
}
static int EmitRescaledYUV(const VP8Io* const io, WebPDecParams* const p) {
const int mb_h = io->mb_h;
const int uv_mb_h = (mb_h + 1) >> 1;
WebPRescaler* const scaler = &p->scaler_y;
int num_lines_out = 0;
if (WebPIsAlphaMode(p->output->colorspace) && io->a != NULL) {
// Before rescaling, we premultiply the luma directly into the io->y
// internal buffer. This is OK since these samples are not used for
// intra-prediction (the top samples are saved in cache_y_/u_/v_).
// But we need to cast the const away, though.
WebPMultRows((uint8_t*)io->y, io->y_stride,
io->a, io->width, io->mb_w, mb_h, 0);
}
num_lines_out = Rescale(io->y, io->y_stride, mb_h, scaler);
Rescale(io->u, io->uv_stride, uv_mb_h, &p->scaler_u);
Rescale(io->v, io->uv_stride, uv_mb_h, &p->scaler_v);
return num_lines_out;
}
static int EmitRescaledAlphaYUV(const VP8Io* const io, WebPDecParams* const p) {
if (io->a != NULL) {
const WebPYUVABuffer* const buf = &p->output->u.YUVA;
uint8_t* dst_y = buf->y + p->last_y * buf->y_stride;
const uint8_t* src_a = buf->a + p->last_y * buf->a_stride;
const int num_lines_out = Rescale(io->a, io->width, io->mb_h, &p->scaler_a);
if (num_lines_out > 0) { // unmultiply the Y
WebPMultRows(dst_y, buf->y_stride, src_a, buf->a_stride,
p->scaler_a.dst_width, num_lines_out, 1);
}
}
return 0;
}
static int InitYUVRescaler(const VP8Io* const io, WebPDecParams* const p) {
const int has_alpha = WebPIsAlphaMode(p->output->colorspace);
const WebPYUVABuffer* const buf = &p->output->u.YUVA;
const int out_width = io->scaled_width;
const int out_height = io->scaled_height;
const int uv_out_width = (out_width + 1) >> 1;
const int uv_out_height = (out_height + 1) >> 1;
const int uv_in_width = (io->mb_w + 1) >> 1;
const int uv_in_height = (io->mb_h + 1) >> 1;
const size_t work_size = 2 * out_width; // scratch memory for luma rescaler
const size_t uv_work_size = 2 * uv_out_width; // and for each u/v ones
size_t tmp_size;
int32_t* work;
tmp_size = (work_size + 2 * uv_work_size) * sizeof(*work);
if (has_alpha) {
tmp_size += work_size * sizeof(*work);
}
p->memory = WebPSafeCalloc(1ULL, tmp_size);
if (p->memory == NULL) {
return 0; // memory error
}
work = (int32_t*)p->memory;
WebPRescalerInit(&p->scaler_y, io->mb_w, io->mb_h,
buf->y, out_width, out_height, buf->y_stride, 1,
io->mb_w, out_width, io->mb_h, out_height,
work);
WebPRescalerInit(&p->scaler_u, uv_in_width, uv_in_height,
buf->u, uv_out_width, uv_out_height, buf->u_stride, 1,
uv_in_width, uv_out_width,
uv_in_height, uv_out_height,
work + work_size);
WebPRescalerInit(&p->scaler_v, uv_in_width, uv_in_height,
buf->v, uv_out_width, uv_out_height, buf->v_stride, 1,
uv_in_width, uv_out_width,
uv_in_height, uv_out_height,
work + work_size + uv_work_size);
p->emit = EmitRescaledYUV;
if (has_alpha) {
WebPRescalerInit(&p->scaler_a, io->mb_w, io->mb_h,
buf->a, out_width, out_height, buf->a_stride, 1,
io->mb_w, out_width, io->mb_h, out_height,
work + work_size + 2 * uv_work_size);
p->emit_alpha = EmitRescaledAlphaYUV;
WebPInitAlphaProcessing();
}
return 1;
}
//------------------------------------------------------------------------------
// RGBA rescaling
static int ExportRGB(WebPDecParams* const p, int y_pos) {
const WebPYUV444Converter convert =
WebPYUV444Converters[p->output->colorspace];
const WebPRGBABuffer* const buf = &p->output->u.RGBA;
uint8_t* dst = buf->rgba + (p->last_y + y_pos) * buf->stride;
int num_lines_out = 0;
// For RGB rescaling, because of the YUV420, current scan position
// U/V can be +1/-1 line from the Y one. Hence the double test.
while (WebPRescalerHasPendingOutput(&p->scaler_y) &&
WebPRescalerHasPendingOutput(&p->scaler_u)) {
assert(p->last_y + y_pos + num_lines_out < p->output->height);
assert(p->scaler_u.y_accum == p->scaler_v.y_accum);
WebPRescalerExportRow(&p->scaler_y, 0);
WebPRescalerExportRow(&p->scaler_u, 0);
WebPRescalerExportRow(&p->scaler_v, 0);
convert(p->scaler_y.dst, p->scaler_u.dst, p->scaler_v.dst,
dst, p->scaler_y.dst_width);
dst += buf->stride;
++num_lines_out;
}
return num_lines_out;
}
static int EmitRescaledRGB(const VP8Io* const io, WebPDecParams* const p) {
const int mb_h = io->mb_h;
const int uv_mb_h = (mb_h + 1) >> 1;
int j = 0, uv_j = 0;
int num_lines_out = 0;
while (j < mb_h) {
const int y_lines_in =
WebPRescalerImport(&p->scaler_y, mb_h - j,
io->y + j * io->y_stride, io->y_stride);
const int u_lines_in =
WebPRescalerImport(&p->scaler_u, uv_mb_h - uv_j,
io->u + uv_j * io->uv_stride, io->uv_stride);
const int v_lines_in =
WebPRescalerImport(&p->scaler_v, uv_mb_h - uv_j,
io->v + uv_j * io->uv_stride, io->uv_stride);
(void)v_lines_in; // remove a gcc warning
assert(u_lines_in == v_lines_in);
j += y_lines_in;
uv_j += u_lines_in;
num_lines_out += ExportRGB(p, num_lines_out);
}
return num_lines_out;
}
static int ExportAlpha(WebPDecParams* const p, int y_pos) {
const WebPRGBABuffer* const buf = &p->output->u.RGBA;
uint8_t* const base_rgba = buf->rgba + (p->last_y + y_pos) * buf->stride;
const WEBP_CSP_MODE colorspace = p->output->colorspace;
const int alpha_first =
(colorspace == MODE_ARGB || colorspace == MODE_Argb);
uint8_t* dst = base_rgba + (alpha_first ? 0 : 3);
int num_lines_out = 0;
const int is_premult_alpha = WebPIsPremultipliedMode(colorspace);
uint32_t alpha_mask = 0xff;
const int width = p->scaler_a.dst_width;
while (WebPRescalerHasPendingOutput(&p->scaler_a)) {
int i;
assert(p->last_y + y_pos + num_lines_out < p->output->height);
WebPRescalerExportRow(&p->scaler_a, 0);
for (i = 0; i < width; ++i) {
const uint32_t alpha_value = p->scaler_a.dst[i];
dst[4 * i] = alpha_value;
alpha_mask &= alpha_value;
}
dst += buf->stride;
++num_lines_out;
}
if (is_premult_alpha && alpha_mask != 0xff) {
WebPApplyAlphaMultiply(base_rgba, alpha_first,
width, num_lines_out, buf->stride);
}
return num_lines_out;
}
static int ExportAlphaRGBA4444(WebPDecParams* const p, int y_pos) {
const WebPRGBABuffer* const buf = &p->output->u.RGBA;
uint8_t* const base_rgba = buf->rgba + (p->last_y + y_pos) * buf->stride;
#ifdef WEBP_SWAP_16BIT_CSP
uint8_t* alpha_dst = base_rgba;
#else
uint8_t* alpha_dst = base_rgba + 1;
#endif
int num_lines_out = 0;
const WEBP_CSP_MODE colorspace = p->output->colorspace;
const int width = p->scaler_a.dst_width;
const int is_premult_alpha = WebPIsPremultipliedMode(colorspace);
uint32_t alpha_mask = 0x0f;
while (WebPRescalerHasPendingOutput(&p->scaler_a)) {
int i;
assert(p->last_y + y_pos + num_lines_out < p->output->height);
WebPRescalerExportRow(&p->scaler_a, 0);
for (i = 0; i < width; ++i) {
// Fill in the alpha value (converted to 4 bits).
const uint32_t alpha_value = p->scaler_a.dst[i] >> 4;
alpha_dst[2 * i] = (alpha_dst[2 * i] & 0xf0) | alpha_value;
alpha_mask &= alpha_value;
}
alpha_dst += buf->stride;
++num_lines_out;
}
if (is_premult_alpha && alpha_mask != 0x0f) {
WebPApplyAlphaMultiply4444(base_rgba, width, num_lines_out, buf->stride);
}
return num_lines_out;
}
static int EmitRescaledAlphaRGB(const VP8Io* const io, WebPDecParams* const p) {
if (io->a != NULL) {
WebPRescaler* const scaler = &p->scaler_a;
int j = 0;
int pos = 0;
while (j < io->mb_h) {
j += WebPRescalerImport(scaler, io->mb_h - j,
io->a + j * io->width, io->width);
pos += p->emit_alpha_row(p, pos);
}
}
return 0;
}
static int InitRGBRescaler(const VP8Io* const io, WebPDecParams* const p) {
const int has_alpha = WebPIsAlphaMode(p->output->colorspace);
const int out_width = io->scaled_width;
const int out_height = io->scaled_height;
const int uv_in_width = (io->mb_w + 1) >> 1;
const int uv_in_height = (io->mb_h + 1) >> 1;
const size_t work_size = 2 * out_width; // scratch memory for one rescaler
int32_t* work; // rescalers work area
uint8_t* tmp; // tmp storage for scaled YUV444 samples before RGB conversion
size_t tmp_size1, tmp_size2, total_size;
tmp_size1 = 3 * work_size;
tmp_size2 = 3 * out_width;
if (has_alpha) {
tmp_size1 += work_size;
tmp_size2 += out_width;
}
total_size = tmp_size1 * sizeof(*work) + tmp_size2 * sizeof(*tmp);
p->memory = WebPSafeCalloc(1ULL, total_size);
if (p->memory == NULL) {
return 0; // memory error
}
work = (int32_t*)p->memory;
tmp = (uint8_t*)(work + tmp_size1);
WebPRescalerInit(&p->scaler_y, io->mb_w, io->mb_h,
tmp + 0 * out_width, out_width, out_height, 0, 1,
io->mb_w, out_width, io->mb_h, out_height,
work + 0 * work_size);
WebPRescalerInit(&p->scaler_u, uv_in_width, uv_in_height,
tmp + 1 * out_width, out_width, out_height, 0, 1,
io->mb_w, 2 * out_width, io->mb_h, 2 * out_height,
work + 1 * work_size);
WebPRescalerInit(&p->scaler_v, uv_in_width, uv_in_height,
tmp + 2 * out_width, out_width, out_height, 0, 1,
io->mb_w, 2 * out_width, io->mb_h, 2 * out_height,
work + 2 * work_size);
p->emit = EmitRescaledRGB;
if (has_alpha) {
WebPRescalerInit(&p->scaler_a, io->mb_w, io->mb_h,
tmp + 3 * out_width, out_width, out_height, 0, 1,
io->mb_w, out_width, io->mb_h, out_height,
work + 3 * work_size);
p->emit_alpha = EmitRescaledAlphaRGB;
if (p->output->colorspace == MODE_RGBA_4444 ||
p->output->colorspace == MODE_rgbA_4444) {
p->emit_alpha_row = ExportAlphaRGBA4444;
} else {
p->emit_alpha_row = ExportAlpha;
}
WebPInitAlphaProcessing();
}
return 1;
}
//------------------------------------------------------------------------------
// Default custom functions
static int CustomSetup(VP8Io* io) {
WebPDecParams* const p = (WebPDecParams*)io->opaque;
const WEBP_CSP_MODE colorspace = p->output->colorspace;
const int is_rgb = WebPIsRGBMode(colorspace);
const int is_alpha = WebPIsAlphaMode(colorspace);
p->memory = NULL;
p->emit = NULL;
p->emit_alpha = NULL;
p->emit_alpha_row = NULL;
if (!WebPIoInitFromOptions(p->options, io, is_alpha ? MODE_YUV : MODE_YUVA)) {
return 0;
}
if (is_alpha && WebPIsPremultipliedMode(colorspace)) {
WebPInitUpsamplers();
}
if (io->use_scaling) {
const int ok = is_rgb ? InitRGBRescaler(io, p) : InitYUVRescaler(io, p);
if (!ok) {
return 0; // memory error
}
} else {
if (is_rgb) {
p->emit = EmitSampledRGB; // default
if (io->fancy_upsampling) {
#ifdef FANCY_UPSAMPLING
const int uv_width = (io->mb_w + 1) >> 1;
p->memory = WebPSafeMalloc(1ULL, (size_t)(io->mb_w + 2 * uv_width));
if (p->memory == NULL) {
return 0; // memory error.
}
p->tmp_y = (uint8_t*)p->memory;
p->tmp_u = p->tmp_y + io->mb_w;
p->tmp_v = p->tmp_u + uv_width;
p->emit = EmitFancyRGB;
WebPInitUpsamplers();
#endif
} else {
WebPInitSamplers();
}
} else {
p->emit = EmitYUV;
}
if (is_alpha) { // need transparency output
p->emit_alpha =
(colorspace == MODE_RGBA_4444 || colorspace == MODE_rgbA_4444) ?
EmitAlphaRGBA4444
: is_rgb ? EmitAlphaRGB
: EmitAlphaYUV;
if (is_rgb) {
WebPInitAlphaProcessing();
}
}
}
if (is_rgb) {
VP8YUVInit();
}
return 1;
}
//------------------------------------------------------------------------------
static int CustomPut(const VP8Io* io) {
WebPDecParams* const p = (WebPDecParams*)io->opaque;
const int mb_w = io->mb_w;
const int mb_h = io->mb_h;
int num_lines_out;
assert(!(io->mb_y & 1));
if (mb_w <= 0 || mb_h <= 0) {
return 0;
}
num_lines_out = p->emit(io, p);
if (p->emit_alpha != NULL) {
p->emit_alpha(io, p);
}
p->last_y += num_lines_out;
return 1;
}
//------------------------------------------------------------------------------
static void CustomTeardown(const VP8Io* io) {
WebPDecParams* const p = (WebPDecParams*)io->opaque;
WebPSafeFree(p->memory);
p->memory = NULL;
}
//------------------------------------------------------------------------------
// Main entry point
void WebPInitCustomIo(WebPDecParams* const params, VP8Io* const io) {
io->put = CustomPut;
io->setup = CustomSetup;
io->teardown = CustomTeardown;
io->opaque = params;
}
//------------------------------------------------------------------------------

View File

@ -1,21 +1,19 @@
// Copyright 2010 Google Inc.
// Copyright 2010 Google Inc. All Rights Reserved.
//
// This code is licensed under the same terms as WebM:
// Software License Agreement: http://www.webmproject.org/license/software/
// Additional IP Rights Grant: http://www.webmproject.org/license/additional/
// 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.
// -----------------------------------------------------------------------------
//
// Quantizer initialization
//
// Author: Skal (pascal.massimino@gmail.com)
#include "vp8i.h"
#include "./vp8i.h"
#if defined(__cplusplus) || defined(c_plusplus)
extern "C" {
#endif
static inline int clip(int v, int M) {
static WEBP_INLINE int clip(int v, int M) {
return v < 0 ? 0 : v > M ? M : v;
}
@ -58,7 +56,7 @@ static const uint16_t kAcTable[128] = {
249, 254, 259, 264, 269, 274, 279, 284
};
//-----------------------------------------------------------------------------
//------------------------------------------------------------------------------
// Paragraph 9.6
void VP8ParseQuant(VP8Decoder* const dec) {
@ -94,18 +92,19 @@ void VP8ParseQuant(VP8Decoder* const dec) {
m->y1_mat_[1] = kAcTable[clip(q + 0, 127)];
m->y2_mat_[0] = kDcTable[clip(q + dqy2_dc, 127)] * 2;
// TODO(skal): make it another table?
m->y2_mat_[1] = kAcTable[clip(q + dqy2_ac, 127)] * 155 / 100;
// For all x in [0..284], x*155/100 is bitwise equal to (x*101581) >> 16.
// The smallest precision for that is '(x*6349) >> 12' but 16 is a good
// word size.
m->y2_mat_[1] = (kAcTable[clip(q + dqy2_ac, 127)] * 101581) >> 16;
if (m->y2_mat_[1] < 8) m->y2_mat_[1] = 8;
m->uv_mat_[0] = kDcTable[clip(q + dquv_dc, 117)];
m->uv_mat_[1] = kAcTable[clip(q + dquv_ac, 127)];
m->uv_quant_ = q + dquv_ac; // for dithering strength evaluation
}
}
}
//-----------------------------------------------------------------------------
//------------------------------------------------------------------------------
#if defined(__cplusplus) || defined(c_plusplus)
} // extern "C"
#endif

View File

@ -1,22 +1,21 @@
// Copyright 2010 Google Inc.
// Copyright 2010 Google Inc. All Rights Reserved.
//
// This code is licensed under the same terms as WebM:
// Software License Agreement: http://www.webmproject.org/license/software/
// Additional IP Rights Grant: http://www.webmproject.org/license/additional/
// 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.
// -----------------------------------------------------------------------------
//
// Coding trees and probas
//
// Author: Skal (pascal.massimino@gmail.com)
#include "vp8i.h"
#include "./vp8i.h"
#include "../utils/bit_reader_inl.h"
#define USE_GENERIC_TREE
#if defined(__cplusplus) || defined(c_plusplus)
extern "C" {
#endif
#ifdef USE_GENERIC_TREE
static const int8_t kYModesIntra4[18] = {
-B_DC_PRED, 1,
@ -31,61 +30,12 @@ static const int8_t kYModesIntra4[18] = {
};
#endif
#ifndef ONLY_KEYFRAME_CODE
// inter prediction modes
enum {
LEFT4 = 0, ABOVE4 = 1, ZERO4 = 2, NEW4 = 3,
NEARESTMV, NEARMV, ZEROMV, NEWMV, SPLITMV };
static const int8_t kYModesInter[8] = {
-DC_PRED, 1,
2, 3,
-V_PRED, -H_PRED,
-TM_PRED, -B_PRED
};
static const int8_t kMBSplit[6] = {
-3, 1,
-2, 2,
-0, -1
};
static const int8_t kMVRef[8] = {
-ZEROMV, 1,
-NEARESTMV, 2,
-NEARMV, 3,
-NEWMV, -SPLITMV
};
static const int8_t kMVRef4[6] = {
-LEFT4, 1
-ABOVE4, 2
-ZERO4, -NEW4
};
#endif
//-----------------------------------------------------------------------------
//------------------------------------------------------------------------------
// Default probabilities
// Inter
#ifndef ONLY_KEYFRAME_CODE
static const uint8_t kYModeProbaInter0[4] = { 112, 86, 140, 37 };
static const uint8_t kUVModeProbaInter0[3] = { 162, 101, 204 };
static const uint8_t kMVProba0[2][NUM_MV_PROBAS] = {
{ 162, 128, 225, 146, 172, 147, 214, 39,
156, 128, 129, 132, 75, 145, 178, 206,
239, 254, 254 },
{ 164, 128, 204, 170, 119, 235, 140, 230,
228, 128, 130, 130, 74, 148, 180, 203,
236, 254, 254 }
};
#endif
// Paragraph 13.5
static const uint8_t
CoeffsProba0[NUM_TYPES][NUM_BANDS][NUM_CTX][NUM_PROBAS] = {
// genereated using vp8_default_coef_probs() in entropy.c:129
{ { { 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128 },
{ 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128 },
{ 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128 }
@ -326,28 +276,38 @@ static const uint8_t kBModesProba[NUM_BMODES][NUM_BMODES][NUM_BMODES - 1] = {
void VP8ResetProba(VP8Proba* const proba) {
memset(proba->segments_, 255u, sizeof(proba->segments_));
memcpy(proba->coeffs_, CoeffsProba0, sizeof(CoeffsProba0));
#ifndef ONLY_KEYFRAME_CODE
memcpy(proba->mv_, kMVProba0, sizeof(kMVProba0));
memcpy(proba->ymode_, kYModeProbaInter0, sizeof(kYModeProbaInter0));
memcpy(proba->uvmode_, kUVModeProbaInter0, sizeof(kUVModeProbaInter0));
#endif
// proba->bands_[][] is initialized later
}
void VP8ParseIntraMode(VP8BitReader* const br, VP8Decoder* const dec) {
uint8_t* const top = dec->intra_t_ + 4 * dec->mb_x_;
static void ParseIntraMode(VP8BitReader* const br,
VP8Decoder* const dec, int mb_x) {
uint8_t* const top = dec->intra_t_ + 4 * mb_x;
uint8_t* const left = dec->intra_l_;
// Hardcoded 16x16 intra-mode decision tree.
dec->is_i4x4_ = !VP8GetBit(br, 145); // decide for B_PRED first
if (!dec->is_i4x4_) {
VP8MBData* const block = dec->mb_data_ + mb_x;
// Note: we don't save segment map (yet), as we don't expect
// to decode more than 1 keyframe.
if (dec->segment_hdr_.update_map_) {
// Hardcoded tree parsing
block->segment_ = !VP8GetBit(br, dec->proba_.segments_[0])
? VP8GetBit(br, dec->proba_.segments_[1])
: 2 + VP8GetBit(br, dec->proba_.segments_[2]);
} else {
block->segment_ = 0; // default for intra
}
if (dec->use_skip_proba_) block->skip_ = VP8GetBit(br, dec->skip_p_);
block->is_i4x4_ = !VP8GetBit(br, 145); // decide for B_PRED first
if (!block->is_i4x4_) {
// Hardcoded 16x16 intra-mode decision tree.
const int ymode =
VP8GetBit(br, 156) ? (VP8GetBit(br, 128) ? TM_PRED : H_PRED)
: (VP8GetBit(br, 163) ? V_PRED : DC_PRED);
dec->imodes_[0] = ymode;
memset(top, ymode, 4 * sizeof(top[0]));
memset(left, ymode, 4 * sizeof(left[0]));
block->imodes_[0] = ymode;
memset(top, ymode, 4 * sizeof(*top));
memset(left, ymode, 4 * sizeof(*left));
} else {
uint8_t* modes = dec->imodes_;
uint8_t* modes = block->imodes_;
int y;
for (y = 0; y < 4; ++y) {
int ymode = left[y];
@ -356,10 +316,10 @@ void VP8ParseIntraMode(VP8BitReader* const br, VP8Decoder* const dec) {
const uint8_t* const prob = kBModesProba[top[x]][ymode];
#ifdef USE_GENERIC_TREE
// Generic tree-parsing
int i = 0;
do {
int i = kYModesIntra4[VP8GetBit(br, prob[0])];
while (i > 0) {
i = kYModesIntra4[2 * i + VP8GetBit(br, prob[i])];
} while (i > 0);
}
ymode = -i;
#else
// Hardcoded tree parsing
@ -374,18 +334,27 @@ void VP8ParseIntraMode(VP8BitReader* const br, VP8Decoder* const dec) {
(!VP8GetBit(br, prob[8]) ? B_HD_PRED : B_HU_PRED)));
#endif // USE_GENERIC_TREE
top[x] = ymode;
*modes++ = ymode;
}
memcpy(modes, top, 4 * sizeof(*top));
modes += 4;
left[y] = ymode;
}
}
// Hardcoded UVMode decision tree
dec->uvmode_ = !VP8GetBit(br, 142) ? DC_PRED
: !VP8GetBit(br, 114) ? V_PRED
: VP8GetBit(br, 183) ? TM_PRED : H_PRED;
block->uvmode_ = !VP8GetBit(br, 142) ? DC_PRED
: !VP8GetBit(br, 114) ? V_PRED
: VP8GetBit(br, 183) ? TM_PRED : H_PRED;
}
//-----------------------------------------------------------------------------
int VP8ParseIntraModeRow(VP8BitReader* const br, VP8Decoder* const dec) {
int mb_x;
for (mb_x = 0; mb_x < dec->mb_w_; ++mb_x) {
ParseIntraMode(br, dec, mb_x);
}
return !dec->br_.eof_;
}
//------------------------------------------------------------------------------
// Paragraph 13
static const uint8_t
@ -524,17 +493,6 @@ static const uint8_t
}
};
#ifndef ONLY_KEYFRAME_CODE
static const uint8_t MVUpdateProba[2][NUM_MV_PROBAS] = {
{ 237, 246, 253, 253, 254, 254, 254, 254,
254, 254, 254, 254, 254, 254, 250, 250,
252, 254, 254 },
{ 231, 243, 245, 253, 254, 254, 254, 254,
254, 254, 254, 254, 254, 254, 251, 251,
254, 254, 254 }
};
#endif
// Paragraph 9.9
void VP8ParseProba(VP8BitReader* const br, VP8Decoder* const dec) {
VP8Proba* const proba = &dec->proba_;
@ -543,9 +501,9 @@ void VP8ParseProba(VP8BitReader* const br, VP8Decoder* const dec) {
for (b = 0; b < NUM_BANDS; ++b) {
for (c = 0; c < NUM_CTX; ++c) {
for (p = 0; p < NUM_PROBAS; ++p) {
if (VP8GetBit(br, CoeffsUpdateProba[t][b][c][p])) {
proba->coeffs_[t][b][c][p] = VP8GetValue(br, 8);
}
const int v = VP8GetBit(br, CoeffsUpdateProba[t][b][c][p]) ?
VP8GetValue(br, 8) : CoeffsProba0[t][b][c][p];
proba->bands_[t][b].probas_[c][p] = v;
}
}
}
@ -554,36 +512,5 @@ void VP8ParseProba(VP8BitReader* const br, VP8Decoder* const dec) {
if (dec->use_skip_proba_) {
dec->skip_p_ = VP8GetValue(br, 8);
}
#ifndef ONLY_KEYFRAME_CODE
if (!dec->frm_hdr_.key_frame_) {
int i;
dec->intra_p_ = VP8GetValue(br, 8);
dec->last_p_ = VP8GetValue(br, 8);
dec->golden_p_ = VP8GetValue(br, 8);
if (VP8Get(br)) { // update y-mode
for (i = 0; i < 4; ++i) {
proba->ymode_[i] = VP8GetValue(br, 8);
}
}
if (VP8Get(br)) { // update uv-mode
for (i = 0; i < 3; ++i) {
proba->uvmode_[i] = VP8GetValue(br, 8);
}
}
// update MV
for (i = 0; i < 2; ++i) {
int k;
for (k = 0; k < NUM_MV_PROBAS; ++k) {
if (VP8GetBit(br, MVUpdateProba[i][k])) {
const int v = VP8GetValue(br, 7);
proba->mv_[i][k] = v ? v << 1 : 1;
}
}
}
}
#endif
}
#if defined(__cplusplus) || defined(c_plusplus)
} // extern "C"
#endif

View File

@ -1,8 +1,10 @@
// Copyright 2010 Google Inc.
// Copyright 2010 Google Inc. All Rights Reserved.
//
// This code is licensed under the same terms as WebM:
// Software License Agreement: http://www.webmproject.org/license/software/
// Additional IP Rights Grant: http://www.webmproject.org/license/additional/
// 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.
// -----------------------------------------------------------------------------
//
// main entry for the decoder
@ -10,19 +12,21 @@
// Author: Skal (pascal.massimino@gmail.com)
#include <stdlib.h>
#include "vp8i.h"
#if defined(__cplusplus) || defined(c_plusplus)
extern "C" {
#endif
#include "./alphai.h"
#include "./vp8i.h"
#include "./vp8li.h"
#include "./webpi.h"
#include "../utils/bit_reader_inl.h"
#include "../utils/utils.h"
//-----------------------------------------------------------------------------
//------------------------------------------------------------------------------
int WebPGetDecoderVersion(void) {
return (DEC_MAJ_VERSION << 16) | (DEC_MIN_VERSION << 8) | DEC_REV_VERSION;
}
//-----------------------------------------------------------------------------
//------------------------------------------------------------------------------
// VP8Decoder
static void SetOk(VP8Decoder* const dec) {
@ -31,19 +35,22 @@ static void SetOk(VP8Decoder* const dec) {
}
int VP8InitIoInternal(VP8Io* const io, int version) {
if (version != WEBP_DECODER_ABI_VERSION)
if (WEBP_ABI_IS_INCOMPATIBLE(version, WEBP_DECODER_ABI_VERSION)) {
return 0; // mismatch error
if (io) {
}
if (io != NULL) {
memset(io, 0, sizeof(*io));
}
return 1;
}
VP8Decoder* VP8New(void) {
VP8Decoder* dec = (VP8Decoder*)calloc(1, sizeof(VP8Decoder));
if (dec) {
VP8Decoder* const dec = (VP8Decoder*)WebPSafeCalloc(1ULL, sizeof(*dec));
if (dec != NULL) {
SetOk(dec);
WebPGetWorkerInterface()->Init(&dec->worker_);
dec->ready_ = 0;
dec->num_parts_ = 1;
}
return dec;
}
@ -54,31 +61,86 @@ VP8StatusCode VP8Status(VP8Decoder* const dec) {
}
const char* VP8StatusMessage(VP8Decoder* const dec) {
if (!dec) return "no object";
if (dec == NULL) return "no object";
if (!dec->error_msg_) return "OK";
return dec->error_msg_;
}
void VP8Delete(VP8Decoder* const dec) {
if (dec) {
if (dec != NULL) {
VP8Clear(dec);
free(dec);
WebPSafeFree(dec);
}
}
int VP8SetError(VP8Decoder* const dec,
VP8StatusCode error, const char * const msg) {
dec->status_ = error;
dec->error_msg_ = msg;
dec->ready_ = 0;
VP8StatusCode error, const char* const msg) {
// TODO This check would be unnecessary if alpha decompression was separated
// from VP8ProcessRow/FinishRow. This avoids setting 'dec->status_' to
// something other than VP8_STATUS_BITSTREAM_ERROR on alpha decompression
// failure.
if (dec->status_ == VP8_STATUS_OK) {
dec->status_ = error;
dec->error_msg_ = msg;
dec->ready_ = 0;
}
return 0;
}
//-----------------------------------------------------------------------------
//------------------------------------------------------------------------------
int VP8CheckSignature(const uint8_t* const data, size_t data_size) {
return (data_size >= 3 &&
data[0] == 0x9d && data[1] == 0x01 && data[2] == 0x2a);
}
int VP8GetInfo(const uint8_t* data, size_t data_size, size_t chunk_size,
int* const width, int* const height) {
if (data == NULL || data_size < VP8_FRAME_HEADER_SIZE) {
return 0; // not enough data
}
// check signature
if (!VP8CheckSignature(data + 3, data_size - 3)) {
return 0; // Wrong signature.
} else {
const uint32_t bits = data[0] | (data[1] << 8) | (data[2] << 16);
const int key_frame = !(bits & 1);
const int w = ((data[7] << 8) | data[6]) & 0x3fff;
const int h = ((data[9] << 8) | data[8]) & 0x3fff;
if (!key_frame) { // Not a keyframe.
return 0;
}
if (((bits >> 1) & 7) > 3) {
return 0; // unknown profile
}
if (!((bits >> 4) & 1)) {
return 0; // first frame is invisible!
}
if (((bits >> 5)) >= chunk_size) { // partition_length
return 0; // inconsistent size information.
}
if (w == 0 || h == 0) {
return 0; // We don't support both width and height to be zero.
}
if (width) {
*width = w;
}
if (height) {
*height = h;
}
return 1;
}
}
//------------------------------------------------------------------------------
// Header parsing
static void ResetSegmentHeader(VP8SegmentHeader* const hdr) {
assert(hdr);
assert(hdr != NULL);
hdr->use_segment_ = 0;
hdr->update_map_ = 0;
hdr->absolute_delta_ = 1;
@ -89,8 +151,8 @@ static void ResetSegmentHeader(VP8SegmentHeader* const hdr) {
// Paragraph 9.3
static int ParseSegmentHeader(VP8BitReader* br,
VP8SegmentHeader* hdr, VP8Proba* proba) {
assert(br);
assert(hdr);
assert(br != NULL);
assert(hdr != NULL);
hdr->use_segment_ = VP8Get(br);
if (hdr->use_segment_) {
hdr->update_map_ = VP8Get(br);
@ -126,7 +188,7 @@ static int ParseSegmentHeader(VP8BitReader* br,
// is returned, and this is an unrecoverable error.
// If the partitions were positioned ok, VP8_STATUS_OK is returned.
static VP8StatusCode ParsePartitions(VP8Decoder* const dec,
const uint8_t* buf, uint32_t size) {
const uint8_t* buf, size_t size) {
VP8BitReader* const br = &dec->br_;
const uint8_t* sz = buf;
const uint8_t* buf_end = buf + size;
@ -177,31 +239,13 @@ static int ParseFilterHeader(VP8BitReader* br, VP8Decoder* const dec) {
}
}
dec->filter_type_ = (hdr->level_ == 0) ? 0 : hdr->simple_ ? 1 : 2;
if (dec->filter_type_ > 0) { // precompute filter levels per segment
if (dec->segment_hdr_.use_segment_) {
int s;
for (s = 0; s < NUM_MB_SEGMENTS; ++s) {
int strength = dec->segment_hdr_.filter_strength_[s];
if (!dec->segment_hdr_.absolute_delta_) {
strength += hdr->level_;
}
dec->filter_levels_[s] = strength;
}
} else {
dec->filter_levels_[0] = hdr->level_;
}
}
return !br->eof_;
}
static inline uint32_t get_le32(const uint8_t* const data) {
return data[0] | (data[1] << 8) | (data[2] << 16) | (data[3] << 24);
}
// Topmost call
int VP8GetHeaders(VP8Decoder* const dec, VP8Io* const io) {
uint8_t* buf;
uint32_t buf_size;
const uint8_t* buf;
size_t buf_size;
VP8FrameHeader* frm_hdr;
VP8PictureHeader* pic_hdr;
VP8BitReader* br;
@ -215,42 +259,11 @@ int VP8GetHeaders(VP8Decoder* const dec, VP8Io* const io) {
return VP8SetError(dec, VP8_STATUS_INVALID_PARAM,
"null VP8Io passed to VP8GetHeaders()");
}
buf = (uint8_t *)io->data;
buf = io->data;
buf_size = io->data_size;
if (buf == NULL || buf_size <= 4) {
if (buf_size < 4) {
return VP8SetError(dec, VP8_STATUS_NOT_ENOUGH_DATA,
"Not enough data to parse frame header");
}
// Skip over valid RIFF headers
if (!memcmp(buf, "RIFF", 4)) {
uint32_t riff_size;
uint32_t chunk_size;
if (buf_size < 20 + 4) {
return VP8SetError(dec, VP8_STATUS_NOT_ENOUGH_DATA,
"RIFF: Truncated header.");
}
if (memcmp(buf + 8, "WEBP", 4)) { // wrong image file signature
return VP8SetError(dec, VP8_STATUS_BITSTREAM_ERROR,
"RIFF: WEBP signature not found.");
}
riff_size = get_le32(buf + 4);
if (riff_size < 12) {
return VP8SetError(dec, VP8_STATUS_NOT_ENOUGH_DATA,
"RIFF: Truncated header.");
}
if (memcmp(buf + 12, "VP8 ", 4)) {
return VP8SetError(dec, VP8_STATUS_BITSTREAM_ERROR,
"RIFF: Invalid compression format.");
}
chunk_size = get_le32(buf + 16);
if (chunk_size > riff_size - 12) {
return VP8SetError(dec, VP8_STATUS_BITSTREAM_ERROR,
"RIFF: Inconsistent size information.");
}
buf += 20;
buf_size -= 20;
"Truncated header.");
}
// Paragraph 9.1
@ -278,7 +291,7 @@ int VP8GetHeaders(VP8Decoder* const dec, VP8Io* const io) {
return VP8SetError(dec, VP8_STATUS_NOT_ENOUGH_DATA,
"cannot parse picture header");
}
if (buf[0] != 0x9d || buf[1] != 0x01 || buf[2] != 0x2a) {
if (!VP8CheckSignature(buf, buf_size)) {
return VP8SetError(dec, VP8_STATUS_BITSTREAM_ERROR,
"Bad code word");
}
@ -291,12 +304,20 @@ int VP8GetHeaders(VP8Decoder* const dec, VP8Io* const io) {
dec->mb_w_ = (pic_hdr->width_ + 15) >> 4;
dec->mb_h_ = (pic_hdr->height_ + 15) >> 4;
// Setup default output area (can be later modified during io->setup())
io->width = pic_hdr->width_;
io->height = pic_hdr->height_;
io->use_scaling = 0;
io->use_cropping = 0;
io->crop_top = 0;
io->crop_left = 0;
io->crop_right = io->width;
io->crop_bottom = io->height;
io->mb_w = io->width; // sanity check
io->mb_h = io->height; // ditto
VP8ResetProba(&dec->proba_);
ResetSegmentHeader(&dec->segment_hdr_);
dec->segment_ = 0; // default for intra
}
// Check if we have all the partition #0 available, and initialize dec->br_
@ -305,6 +326,7 @@ int VP8GetHeaders(VP8Decoder* const dec, VP8Io* const io) {
return VP8SetError(dec, VP8_STATUS_NOT_ENOUGH_DATA,
"bad partition length");
}
br = &dec->br_;
VP8InitBitReader(br, buf, buf + frm_hdr->partition_length_);
buf += frm_hdr->partition_length_;
@ -333,38 +355,11 @@ int VP8GetHeaders(VP8Decoder* const dec, VP8Io* const io) {
// Frame buffer marking
if (!frm_hdr->key_frame_) {
// Paragraph 9.7
#ifndef ONLY_KEYFRAME_CODE
dec->buffer_flags_ = VP8Get(br) << 0; // update golden
dec->buffer_flags_ |= VP8Get(br) << 1; // update alt ref
if (!(dec->buffer_flags_ & 1)) {
dec->buffer_flags_ |= VP8GetValue(br, 2) << 2;
}
if (!(dec->buffer_flags_ & 2)) {
dec->buffer_flags_ |= VP8GetValue(br, 2) << 4;
}
dec->buffer_flags_ |= VP8Get(br) << 6; // sign bias golden
dec->buffer_flags_ |= VP8Get(br) << 7; // sign bias alt ref
#else
return VP8SetError(dec, VP8_STATUS_UNSUPPORTED_FEATURE,
"Not a key frame.");
#endif
} else {
dec->buffer_flags_ = 0x003 | 0x100;
}
// Paragraph 9.8
#ifndef ONLY_KEYFRAME_CODE
dec->update_proba_ = VP8Get(br);
if (!dec->update_proba_) { // save for later restore
dec->proba_saved_ = dec->proba_;
}
dec->buffer_flags_ &= 1 << 8;
dec->buffer_flags_ |=
(frm_hdr->key_frame_ || VP8Get(br)) << 8; // refresh last frame
#else
VP8Get(br); // just ignore the value of update_proba_
#endif
VP8Get(br); // ignore the value of update_proba_
VP8ParseProba(br, dec);
@ -373,10 +368,10 @@ int VP8GetHeaders(VP8Decoder* const dec, VP8Io* const io) {
return 1;
}
//-----------------------------------------------------------------------------
//------------------------------------------------------------------------------
// Residual decoding (Paragraph 13.2 / 13.3)
static const uint8_t kBands[16 + 1] = {
static const int kBands[16 + 1] = {
0, 1, 2, 3, 6, 4, 5, 6, 6, 6, 6, 6, 6, 6, 6, 7,
0 // extra entry as sentinel
};
@ -386,246 +381,238 @@ static const uint8_t kCat4[] = { 176, 155, 140, 135, 0 };
static const uint8_t kCat5[] = { 180, 157, 141, 134, 130, 0 };
static const uint8_t kCat6[] =
{ 254, 254, 243, 230, 196, 177, 153, 140, 133, 130, 129, 0 };
static const uint8_t * const kCat3456[] = { kCat3, kCat4, kCat5, kCat6 };
static const uint8_t* const kCat3456[] = { kCat3, kCat4, kCat5, kCat6 };
static const uint8_t kZigzag[16] = {
0, 1, 4, 8, 5, 2, 3, 6, 9, 12, 13, 10, 7, 11, 14, 15
};
typedef const uint8_t (*ProbaArray)[NUM_CTX][NUM_PROBAS]; // for const-casting
// Returns the position of the last non-zero coeff plus one
// (and 0 if there's no coeff at all)
static int GetCoeffs(VP8BitReader* const br, ProbaArray prob,
int ctx, const uint16_t dq[2], int n, int16_t* out) {
const uint8_t* p = prob[kBands[n]][ctx];
if (!VP8GetBit(br, p[0])) { // first EOB is more a 'CBP' bit.
return 0;
}
while (1) {
++n;
if (!VP8GetBit(br, p[1])) {
p = prob[kBands[n]][0];
} else { // non zero coeff
int v, j;
if (!VP8GetBit(br, p[2])) {
p = prob[kBands[n]][1];
v = 1;
// See section 13-2: http://tools.ietf.org/html/rfc6386#section-13.2
static int GetLargeValue(VP8BitReader* const br, const uint8_t* const p) {
int v;
if (!VP8GetBit(br, p[3])) {
if (!VP8GetBit(br, p[4])) {
v = 2;
} else {
v = 3 + VP8GetBit(br, p[5]);
}
} else {
if (!VP8GetBit(br, p[6])) {
if (!VP8GetBit(br, p[7])) {
v = 5 + VP8GetBit(br, 159);
} else {
if (!VP8GetBit(br, p[3])) {
if (!VP8GetBit(br, p[4])) {
v = 2;
} else {
v = 3 + VP8GetBit(br, p[5]);
}
} else {
if (!VP8GetBit(br, p[6])) {
if (!VP8GetBit(br, p[7])) {
v = 5 + VP8GetBit(br, 159);
} else {
v = 7 + 2 * VP8GetBit(br, 165) + VP8GetBit(br, 145);
}
} else {
const uint8_t* tab;
const int bit1 = VP8GetBit(br, p[8]);
const int bit0 = VP8GetBit(br, p[9 + bit1]);
const int cat = 2 * bit1 + bit0;
v = 0;
for (tab = kCat3456[cat]; *tab; ++tab) {
v += v + VP8GetBit(br, *tab);
}
v += 3 + (8 << cat);
}
}
p = prob[kBands[n]][2];
v = 7 + 2 * VP8GetBit(br, 165);
v += VP8GetBit(br, 145);
}
j = kZigzag[n - 1];
out[j] = VP8GetSigned(br, v) * dq[j > 0];
if (n == 16 || !VP8GetBit(br, p[0])) { // EOB
return n;
} else {
const uint8_t* tab;
const int bit1 = VP8GetBit(br, p[8]);
const int bit0 = VP8GetBit(br, p[9 + bit1]);
const int cat = 2 * bit1 + bit0;
v = 0;
for (tab = kCat3456[cat]; *tab; ++tab) {
v += v + VP8GetBit(br, *tab);
}
}
if (n == 16) {
return 16;
v += 3 + (8 << cat);
}
}
return v;
}
// Alias-safe way of converting 4bytes to 32bits.
typedef union {
uint8_t i8[4];
uint32_t i32;
} PackedNz;
// Returns the position of the last non-zero coeff plus one
static int GetCoeffs(VP8BitReader* const br, const VP8BandProbas* const prob,
int ctx, const quant_t dq, int n, int16_t* out) {
// n is either 0 or 1 here. kBands[n] is not necessary for extracting '*p'.
const uint8_t* p = prob[n].probas_[ctx];
for (; n < 16; ++n) {
if (!VP8GetBit(br, p[0])) {
return n; // previous coeff was last non-zero coeff
}
while (!VP8GetBit(br, p[1])) { // sequence of zero coeffs
p = prob[kBands[++n]].probas_[0];
if (n == 16) return 16;
}
{ // non zero coeff
const VP8ProbaArray* const p_ctx = &prob[kBands[n + 1]].probas_[0];
int v;
if (!VP8GetBit(br, p[2])) {
v = 1;
p = p_ctx[1];
} else {
v = GetLargeValue(br, p);
p = p_ctx[2];
}
out[kZigzag[n]] = VP8GetSigned(br, v) * dq[n > 0];
}
}
return 16;
}
// Table to unpack four bits into four bytes
static const PackedNz kUnpackTab[16] = {
{{0, 0, 0, 0}}, {{1, 0, 0, 0}}, {{0, 1, 0, 0}}, {{1, 1, 0, 0}},
{{0, 0, 1, 0}}, {{1, 0, 1, 0}}, {{0, 1, 1, 0}}, {{1, 1, 1, 0}},
{{0, 0, 0, 1}}, {{1, 0, 0, 1}}, {{0, 1, 0, 1}}, {{1, 1, 0, 1}},
{{0, 0, 1, 1}}, {{1, 0, 1, 1}}, {{0, 1, 1, 1}}, {{1, 1, 1, 1}} };
static WEBP_INLINE uint32_t NzCodeBits(uint32_t nz_coeffs, int nz, int dc_nz) {
nz_coeffs <<= 2;
nz_coeffs |= (nz > 3) ? 3 : (nz > 1) ? 2 : dc_nz;
return nz_coeffs;
}
// Macro to pack four LSB of four bytes into four bits.
#if defined(__PPC__) || defined(_M_PPC) || defined(_ARCH_PPC) || \
defined(__BIG_ENDIAN__)
#define PACK_CST 0x08040201U
#else
#define PACK_CST 0x01020408U
#endif
#define PACK(X, S) ((((X).i32 * PACK_CST) & 0xff000000) >> (S))
static void ParseResiduals(VP8Decoder* const dec,
VP8MB* const mb, VP8BitReader* const token_br) {
int out_t_nz, out_l_nz, first;
ProbaArray ac_prob;
const VP8QuantMatrix* q = &dec->dqm_[dec->segment_];
int16_t* dst = dec->coeffs_;
static int ParseResiduals(VP8Decoder* const dec,
VP8MB* const mb, VP8BitReader* const token_br) {
VP8BandProbas (* const bands)[NUM_BANDS] = dec->proba_.bands_;
const VP8BandProbas* ac_proba;
VP8MBData* const block = dec->mb_data_ + dec->mb_x_;
const VP8QuantMatrix* const q = &dec->dqm_[block->segment_];
int16_t* dst = block->coeffs_;
VP8MB* const left_mb = dec->mb_info_ - 1;
PackedNz nz_ac, nz_dc;
PackedNz tnz, lnz;
uint32_t non_zero_ac = 0;
uint32_t non_zero_dc = 0;
uint8_t tnz, lnz;
uint32_t non_zero_y = 0;
uint32_t non_zero_uv = 0;
int x, y, ch;
uint32_t out_t_nz, out_l_nz;
int first;
memset(dst, 0, 384 * sizeof(*dst));
if (!dec->is_i4x4_) { // parse DC
if (!block->is_i4x4_) { // parse DC
int16_t dc[16] = { 0 };
const int ctx = mb->dc_nz_ + left_mb->dc_nz_;
mb->dc_nz_ = left_mb->dc_nz_ =
(GetCoeffs(token_br, (ProbaArray)dec->proba_.coeffs_[1],
ctx, q->y2_mat_, 0, dc) > 0);
const int ctx = mb->nz_dc_ + left_mb->nz_dc_;
const int nz = GetCoeffs(token_br, bands[1], ctx, q->y2_mat_, 0, dc);
mb->nz_dc_ = left_mb->nz_dc_ = (nz > 0);
if (nz > 1) { // more than just the DC -> perform the full transform
VP8TransformWHT(dc, dst);
} else { // only DC is non-zero -> inlined simplified transform
int i;
const int dc0 = (dc[0] + 3) >> 3;
for (i = 0; i < 16 * 16; i += 16) dst[i] = dc0;
}
first = 1;
ac_prob = (ProbaArray)dec->proba_.coeffs_[0];
VP8TransformWHT(dc, dst);
ac_proba = bands[0];
} else {
first = 0;
ac_prob = (ProbaArray)dec->proba_.coeffs_[3];
ac_proba = bands[3];
}
tnz = kUnpackTab[mb->nz_ & 0xf];
lnz = kUnpackTab[left_mb->nz_ & 0xf];
tnz = mb->nz_ & 0x0f;
lnz = left_mb->nz_ & 0x0f;
for (y = 0; y < 4; ++y) {
int l = lnz.i8[y];
int l = lnz & 1;
uint32_t nz_coeffs = 0;
for (x = 0; x < 4; ++x) {
const int ctx = l + tnz.i8[x];
const int nz = GetCoeffs(token_br, ac_prob, ctx,
q->y1_mat_, first, dst);
tnz.i8[x] = l = (nz > 0);
nz_dc.i8[x] = (dst[0] != 0);
nz_ac.i8[x] = (nz > 1);
const int ctx = l + (tnz & 1);
const int nz = GetCoeffs(token_br, ac_proba, ctx, q->y1_mat_, first, dst);
l = (nz > first);
tnz = (tnz >> 1) | (l << 7);
nz_coeffs = NzCodeBits(nz_coeffs, nz, dst[0] != 0);
dst += 16;
}
lnz.i8[y] = l;
non_zero_dc |= PACK(nz_dc, 24 - y * 4);
non_zero_ac |= PACK(nz_ac, 24 - y * 4);
tnz >>= 4;
lnz = (lnz >> 1) | (l << 7);
non_zero_y = (non_zero_y << 8) | nz_coeffs;
}
out_t_nz = PACK(tnz, 24);
out_l_nz = PACK(lnz, 24);
out_t_nz = tnz;
out_l_nz = lnz >> 4;
tnz = kUnpackTab[mb->nz_ >> 4];
lnz = kUnpackTab[left_mb->nz_ >> 4];
for (ch = 0; ch < 4; ch += 2) {
uint32_t nz_coeffs = 0;
tnz = mb->nz_ >> (4 + ch);
lnz = left_mb->nz_ >> (4 + ch);
for (y = 0; y < 2; ++y) {
int l = lnz.i8[ch + y];
int l = lnz & 1;
for (x = 0; x < 2; ++x) {
const int ctx = l + tnz.i8[ch + x];
const int nz =
GetCoeffs(token_br, (ProbaArray)dec->proba_.coeffs_[2],
ctx, q->uv_mat_, 0, dst);
tnz.i8[ch + x] = l = (nz > 0);
nz_dc.i8[y * 2 + x] = (dst[0] != 0);
nz_ac.i8[y * 2 + x] = (nz > 1);
const int ctx = l + (tnz & 1);
const int nz = GetCoeffs(token_br, bands[2], ctx, q->uv_mat_, 0, dst);
l = (nz > 0);
tnz = (tnz >> 1) | (l << 3);
nz_coeffs = NzCodeBits(nz_coeffs, nz, dst[0] != 0);
dst += 16;
}
lnz.i8[ch + y] = l;
tnz >>= 2;
lnz = (lnz >> 1) | (l << 5);
}
non_zero_dc |= PACK(nz_dc, 8 - ch * 2);
non_zero_ac |= PACK(nz_ac, 8 - ch * 2);
// Note: we don't really need the per-4x4 details for U/V blocks.
non_zero_uv |= nz_coeffs << (4 * ch);
out_t_nz |= (tnz << 4) << ch;
out_l_nz |= (lnz & 0xf0) << ch;
}
out_t_nz |= PACK(tnz, 20);
out_l_nz |= PACK(lnz, 20);
mb->nz_ = out_t_nz;
left_mb->nz_ = out_l_nz;
dec->non_zero_ac_ = non_zero_ac;
dec->non_zero_ = non_zero_ac | non_zero_dc;
mb->skip_ = !dec->non_zero_;
}
#undef PACK
block->non_zero_y_ = non_zero_y;
block->non_zero_uv_ = non_zero_uv;
//-----------------------------------------------------------------------------
// We look at the mode-code of each block and check if some blocks have less
// than three non-zero coeffs (code < 2). This is to avoid dithering flat and
// empty blocks.
block->dither_ = (non_zero_uv & 0xaaaa) ? 0 : q->dither_;
return !(non_zero_y | non_zero_uv); // will be used for further optimization
}
//------------------------------------------------------------------------------
// Main loop
int VP8DecodeMB(VP8Decoder* const dec, VP8BitReader* const token_br) {
VP8BitReader* const br = &dec->br_;
VP8MB* const left = dec->mb_info_ - 1;
VP8MB* const info = dec->mb_info_ + dec->mb_x_;
VP8MB* const mb = dec->mb_info_ + dec->mb_x_;
VP8MBData* const block = dec->mb_data_ + dec->mb_x_;
int skip = dec->use_skip_proba_ ? block->skip_ : 0;
// Note: we don't save segment map (yet), as we don't expect
// to decode more than 1 keyframe.
if (dec->segment_hdr_.update_map_) {
// Hardcoded tree parsing
dec->segment_ = !VP8GetBit(br, dec->proba_.segments_[0]) ?
VP8GetBit(br, dec->proba_.segments_[1]) :
2 + VP8GetBit(br, dec->proba_.segments_[2]);
}
info->skip_ = dec->use_skip_proba_ ? VP8GetBit(br, dec->skip_p_) : 0;
VP8ParseIntraMode(br, dec);
if (br->eof_) {
return 0;
}
if (!info->skip_) {
ParseResiduals(dec, info, token_br);
if (!skip) {
skip = ParseResiduals(dec, mb, token_br);
} else {
left->nz_ = info->nz_ = 0;
if (!dec->is_i4x4_) {
left->dc_nz_ = info->dc_nz_ = 0;
left->nz_ = mb->nz_ = 0;
if (!block->is_i4x4_) {
left->nz_dc_ = mb->nz_dc_ = 0;
}
dec->non_zero_ = 0;
dec->non_zero_ac_ = 0;
block->non_zero_y_ = 0;
block->non_zero_uv_ = 0;
}
return (!token_br->eof_);
if (dec->filter_type_ > 0) { // store filter info
VP8FInfo* const finfo = dec->f_info_ + dec->mb_x_;
*finfo = dec->fstrengths_[block->segment_][block->is_i4x4_];
finfo->f_inner_ |= !skip;
}
return !token_br->eof_;
}
void VP8InitScanline(VP8Decoder* const dec) {
VP8MB* const left = dec->mb_info_ - 1;
left->nz_ = 0;
left->nz_dc_ = 0;
memset(dec->intra_l_, B_DC_PRED, sizeof(dec->intra_l_));
dec->mb_x_ = 0;
}
static int ParseFrame(VP8Decoder* const dec, VP8Io* io) {
for (dec->mb_y_ = 0; dec->mb_y_ < dec->mb_h_; ++dec->mb_y_) {
VP8MB* const left = dec->mb_info_ - 1;
for (dec->mb_y_ = 0; dec->mb_y_ < dec->br_mb_y_; ++dec->mb_y_) {
// Parse bitstream for this row.
VP8BitReader* const token_br =
&dec->parts_[dec->mb_y_ & (dec->num_parts_ - 1)];
left->nz_ = 0;
left->dc_nz_ = 0;
memset(dec->intra_l_, B_DC_PRED, sizeof(dec->intra_l_));
for (dec->mb_x_ = 0; dec->mb_x_ < dec->mb_w_; dec->mb_x_++) {
if (!VP8ParseIntraModeRow(&dec->br_, dec)) {
return VP8SetError(dec, VP8_STATUS_NOT_ENOUGH_DATA,
"Premature end-of-partition0 encountered.");
}
for (; dec->mb_x_ < dec->mb_w_; ++dec->mb_x_) {
if (!VP8DecodeMB(dec, token_br)) {
return VP8SetError(dec, VP8_STATUS_NOT_ENOUGH_DATA,
"Premature end-of-file encountered.");
}
VP8ReconstructBlock(dec);
// Store data and save block's filtering params
VP8StoreBlock(dec);
}
if (!VP8FinishRow(dec, io)) {
return VP8SetError(dec, VP8_STATUS_USER_ABORT,
"Output aborted.");
VP8InitScanline(dec); // Prepare for next scanline
// Reconstruct, filter and emit the row.
if (!VP8ProcessRow(dec, io)) {
return VP8SetError(dec, VP8_STATUS_USER_ABORT, "Output aborted.");
}
}
// Finish
#ifndef ONLY_KEYFRAME_CODE
if (!dec->update_proba_) {
dec->proba_ = dec->proba_saved_;
if (dec->mt_method_ > 0) {
if (!WebPGetWorkerInterface()->Sync(&dec->worker_)) return 0;
}
#endif
return 1;
}
// Main entry point
int VP8Decode(VP8Decoder* const dec, VP8Io* const io) {
int ok = 0;
if (dec == NULL) {
return 0;
}
@ -641,53 +628,41 @@ int VP8Decode(VP8Decoder* const dec, VP8Io* const io) {
}
assert(dec->ready_);
// will allocate memory and prepare everything.
if (!VP8InitFrame(dec, io)) {
VP8Clear(dec);
return VP8SetError(dec, VP8_STATUS_OUT_OF_MEMORY,
"Allocation failed");
// Finish setting up the decoding parameter. Will call io->setup().
ok = (VP8EnterCritical(dec, io) == VP8_STATUS_OK);
if (ok) { // good to go.
// Will allocate memory and prepare everything.
if (ok) ok = VP8InitFrame(dec, io);
// Main decoding loop
if (ok) ok = ParseFrame(dec, io);
// Exit.
ok &= VP8ExitCritical(dec, io);
}
if (io->setup && !io->setup(io)) {
if (!ok) {
VP8Clear(dec);
return VP8SetError(dec, VP8_STATUS_USER_ABORT,
"Frame setup failed");
}
// Disable filtering per user request (_after_ setup() is called)
if (io->bypass_filtering) dec->filter_type_ = 0;
// Main decoding loop
{
const int ret = ParseFrame(dec, io);
if (io->teardown) {
io->teardown(io);
}
if (!ret) {
VP8Clear(dec);
return 0;
}
return 0;
}
dec->ready_ = 0;
return 1;
return ok;
}
void VP8Clear(VP8Decoder* const dec) {
if (dec == NULL) {
return;
}
if (dec->mem_) {
free(dec->mem_);
}
WebPGetWorkerInterface()->End(&dec->worker_);
ALPHDelete(dec->alph_dec_);
dec->alph_dec_ = NULL;
WebPSafeFree(dec->mem_);
dec->mem_ = NULL;
dec->mem_size_ = 0;
memset(&dec->br_, 0, sizeof(dec->br_));
dec->ready_ = 0;
}
//-----------------------------------------------------------------------------
//------------------------------------------------------------------------------
#if defined(__cplusplus) || defined(c_plusplus)
} // extern "C"
#endif

View File

@ -1,8 +1,10 @@
// Copyright 2010 Google Inc.
// Copyright 2010 Google Inc. All Rights Reserved.
//
// This code is licensed under the same terms as WebM:
// Software License Agreement: http://www.webmproject.org/license/software/
// Additional IP Rights Grant: http://www.webmproject.org/license/additional/
// 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.
// -----------------------------------------------------------------------------
//
// VP8 decoder: internal header.
@ -13,22 +15,24 @@
#define WEBP_DEC_VP8I_H_
#include <string.h> // for memcpy()
#include "bits.h"
#include "./vp8li.h"
#include "../utils/bit_reader.h"
#include "../utils/random.h"
#include "../utils/thread.h"
#include "../dsp/dsp.h"
#if defined(__cplusplus) || defined(c_plusplus)
#ifdef __cplusplus
extern "C" {
#endif
//-----------------------------------------------------------------------------
//------------------------------------------------------------------------------
// Various defines and enums
// version numbers
#define DEC_MAJ_VERSION 0
#define DEC_MIN_VERSION 1
#define DEC_MIN_VERSION 4
#define DEC_REV_VERSION 2
#define ONLY_KEYFRAME_CODE // to remove any code related to P-Frames
// intra prediction modes
enum { B_DC_PRED = 0, // 4x4 modes
B_TM_PRED,
@ -95,7 +99,10 @@ enum { MB_FEATURE_TREE_PROBS = 3,
#define U_OFF (Y_OFF + BPS * 16 + BPS)
#define V_OFF (U_OFF + 16)
//-----------------------------------------------------------------------------
// minimal width under which lossy multi-threading is always disabled
#define MIN_WIDTH_FOR_THREADS 512
//------------------------------------------------------------------------------
// Headers
typedef struct {
@ -123,15 +130,19 @@ typedef struct {
int8_t filter_strength_[NUM_MB_SEGMENTS]; // filter strength for segments
} VP8SegmentHeader;
// probas associated to one of the contexts
typedef uint8_t VP8ProbaArray[NUM_PROBAS];
typedef struct { // all the probas associated to one band
VP8ProbaArray probas_[NUM_CTX];
} VP8BandProbas;
// Struct collecting all frame-persistent probabilities.
typedef struct {
uint8_t segments_[MB_FEATURE_TREE_PROBS];
// Type: 0:Intra16-AC 1:Intra16-DC 2:Chroma 3:Intra4
uint8_t coeffs_[NUM_TYPES][NUM_BANDS][NUM_CTX][NUM_PROBAS];
#ifndef ONLY_KEYFRAME_CODE
uint8_t ymode_[4], uvmode_[3];
uint8_t mv_[2][NUM_MV_PROBAS];
#endif
VP8BandProbas bands_[NUM_TYPES][NUM_BANDS];
} VP8Proba;
// Filter parameters
@ -144,27 +155,66 @@ typedef struct {
int mode_lf_delta_[NUM_MODE_LF_DELTAS];
} VP8FilterHeader;
//-----------------------------------------------------------------------------
//------------------------------------------------------------------------------
// Informations about the macroblocks.
typedef struct {
// block type
uint8_t skip_:1;
// filter specs
uint8_t f_level_:6; // filter strength: 0..63
uint8_t f_ilevel_:6; // inner limit: 1..63
uint8_t f_inner_:1; // do inner filtering?
// cbp
uint8_t nz_; // non-zero AC/DC coeffs
uint8_t dc_nz_; // non-zero DC coeffs
typedef struct { // filter specs
uint8_t f_limit_; // filter limit in [3..189], or 0 if no filtering
uint8_t f_ilevel_; // inner limit in [1..63]
uint8_t f_inner_; // do inner filtering?
uint8_t hev_thresh_; // high edge variance threshold in [0..2]
} VP8FInfo;
typedef struct { // Top/Left Contexts used for syntax-parsing
uint8_t nz_; // non-zero AC/DC coeffs (4bit for luma + 4bit for chroma)
uint8_t nz_dc_; // non-zero DC coeff (1bit)
} VP8MB;
// Dequantization matrices
typedef int quant_t[2]; // [DC / AC]. Can be 'uint16_t[2]' too (~slower).
typedef struct {
uint16_t y1_mat_[2], y2_mat_[2], uv_mat_[2]; // [DC / AC]
quant_t y1_mat_, y2_mat_, uv_mat_;
int uv_quant_; // U/V quantizer value
int dither_; // dithering amplitude (0 = off, max=255)
} VP8QuantMatrix;
//-----------------------------------------------------------------------------
// Data needed to reconstruct a macroblock
typedef struct {
int16_t coeffs_[384]; // 384 coeffs = (16+4+4) * 4*4
uint8_t is_i4x4_; // true if intra4x4
uint8_t imodes_[16]; // one 16x16 mode (#0) or sixteen 4x4 modes
uint8_t uvmode_; // chroma prediction mode
// bit-wise info about the content of each sub-4x4 blocks (in decoding order).
// Each of the 4x4 blocks for y/u/v is associated with a 2b code according to:
// code=0 -> no coefficient
// code=1 -> only DC
// code=2 -> first three coefficients are non-zero
// code=3 -> more than three coefficients are non-zero
// This allows to call specialized transform functions.
uint32_t non_zero_y_;
uint32_t non_zero_uv_;
uint8_t dither_; // local dithering strength (deduced from non_zero_*)
uint8_t skip_;
uint8_t segment_;
} VP8MBData;
// Persistent information needed by the parallel processing
typedef struct {
int id_; // cache row to process (in [0..2])
int mb_y_; // macroblock position of the row
int filter_row_; // true if row-filtering is needed
VP8FInfo* f_info_; // filter strengths (swapped with dec->f_info_)
VP8MBData* mb_data_; // reconstruction data (swapped with dec->mb_data_)
VP8Io io_; // copy of the VP8Io to pass to put()
} VP8ThreadContext;
// Saved top samples, per macroblock. Fits into a cache-line.
typedef struct {
uint8_t y[16], u[8], v[8];
} VP8TopSamples;
//------------------------------------------------------------------------------
// VP8Decoder: the main opaque structure handed over to user
struct VP8Decoder {
@ -181,20 +231,29 @@ struct VP8Decoder {
VP8FilterHeader filter_hdr_;
VP8SegmentHeader segment_hdr_;
// Worker
WebPWorker worker_;
int mt_method_; // multi-thread method: 0=off, 1=[parse+recon][filter]
// 2=[parse][recon+filter]
int cache_id_; // current cache row
int num_caches_; // number of cached rows of 16 pixels (1, 2 or 3)
VP8ThreadContext thread_ctx_; // Thread context
// dimension, in macroblock units.
int mb_w_, mb_h_;
// Macroblock to process/filter, depending on cropping and filter_type.
int tl_mb_x_, tl_mb_y_; // top-left MB that must be in-loop filtered
int br_mb_x_, br_mb_y_; // last bottom-right MB that must be decoded
// number of partitions.
int num_parts_;
// per-partition boolean decoders.
VP8BitReader parts_[MAX_NUM_PARTITIONS];
// buffer refresh flags
// bit 0: refresh Gold, bit 1: refresh Alt
// bit 2-3: copy to Gold, bit 4-5: copy to Alt
// bit 6: Gold sign bias, bit 7: Alt sign bias
// bit 8: refresh last frame
uint32_t buffer_flags_;
// Dithering strength, deduced from decoding options
int dither_; // whether to use dithering or not
VP8Random dithering_rg_; // random generator for dithering
// dequantization (one set of DC/AC dequant factor per segment)
VP8QuantMatrix dqm_[NUM_MB_SEGMENTS];
@ -203,23 +262,18 @@ struct VP8Decoder {
VP8Proba proba_;
int use_skip_proba_;
uint8_t skip_p_;
#ifndef ONLY_KEYFRAME_CODE
uint8_t intra_p_, last_p_, golden_p_;
VP8Proba proba_saved_;
int update_proba_;
#endif
// Boundary data cache and persistent buffers.
uint8_t* intra_t_; // top intra modes values: 4 * mb_w_
uint8_t intra_l_[4]; // left intra modes values
uint8_t *y_t_; // top luma samples: 16 * mb_w_
uint8_t *u_t_, *v_t_; // top u/v samples: 8 * mb_w_ each
uint8_t* intra_t_; // top intra modes values: 4 * mb_w_
uint8_t intra_l_[4]; // left intra modes values
VP8MB* mb_info_; // contextual macroblock infos (mb_w_ + 1)
uint8_t* yuv_b_; // main block for Y/U/V (size = YUV_SIZE)
int16_t* coeffs_; // 384 coeffs = (16+8+8) * 4*4
VP8TopSamples* yuv_t_; // top y/u/v samples
uint8_t* cache_y_; // macroblock row for storing unfiltered samples
VP8MB* mb_info_; // contextual macroblock info (mb_w_ + 1)
VP8FInfo* f_info_; // filter strength info
uint8_t* yuv_b_; // main block for Y/U/V (size = YUV_SIZE)
uint8_t* cache_y_; // macroblock row for storing unfiltered samples
uint8_t* cache_u_;
uint8_t* cache_v_;
int cache_y_stride_;
@ -227,99 +281,74 @@ struct VP8Decoder {
// main memory chunk for the above data. Persistent.
void* mem_;
int mem_size_;
size_t mem_size_;
// Per macroblock non-persistent infos.
int mb_x_, mb_y_; // current position, in macroblock units
uint8_t is_i4x4_; // true if intra4x4
uint8_t imodes_[16]; // one 16x16 mode (#0) or sixteen 4x4 modes
uint8_t uvmode_; // chroma prediction mode
uint8_t segment_; // block's segment
// bit-wise info about the content of each sub-4x4 blocks: there are 16 bits
// for luma (bits #0->#15), then 4 bits for chroma-u (#16->#19) and 4 bits for
// chroma-v (#20->#23), each corresponding to one 4x4 block in decoding order.
// If the bit is set, the 4x4 block contains some non-zero coefficients.
uint32_t non_zero_;
uint32_t non_zero_ac_;
VP8MBData* mb_data_; // parsed reconstruction data
// Filtering side-info
int filter_type_; // 0=off, 1=simple, 2=complex
uint8_t filter_levels_[NUM_MB_SEGMENTS]; // precalculated per-segment
int filter_type_; // 0=off, 1=simple, 2=complex
VP8FInfo fstrengths_[NUM_MB_SEGMENTS][2]; // precalculated per-segment/type
// Alpha
struct ALPHDecoder* alph_dec_; // alpha-plane decoder object
const uint8_t* alpha_data_; // compressed alpha data (if present)
size_t alpha_data_size_;
int is_alpha_decoded_; // true if alpha_data_ is decoded in alpha_plane_
uint8_t* alpha_plane_; // output. Persistent, contains the whole data.
int alpha_dithering_; // derived from decoding options (0=off, 100=full).
};
//-----------------------------------------------------------------------------
//------------------------------------------------------------------------------
// internal functions. Not public.
// in vp8.c
int VP8SetError(VP8Decoder* const dec,
VP8StatusCode error, const char * const msg);
VP8StatusCode error, const char* const msg);
// in tree.c
void VP8ResetProba(VP8Proba* const proba);
void VP8ParseProba(VP8BitReader* const br, VP8Decoder* const dec);
void VP8ParseIntraMode(VP8BitReader* const br, VP8Decoder* const dec);
// parses one row of intra mode data in partition 0, returns !eof
int VP8ParseIntraModeRow(VP8BitReader* const br, VP8Decoder* const dec);
// in quant.c
void VP8ParseQuant(VP8Decoder* const dec);
// in frame.c
int VP8InitFrame(VP8Decoder* const dec, VP8Io* io);
// Predict a block and add residual
void VP8ReconstructBlock(VP8Decoder* const dec);
// Store a block, along with filtering params
void VP8StoreBlock(VP8Decoder* const dec);
// Finalize and transmit a complete row. Return false in case of user-abort.
int VP8FinishRow(VP8Decoder* const dec, VP8Io* io);
// Call io->setup() and finish setting up scan parameters.
// After this call returns, one must always call VP8ExitCritical() with the
// same parameters. Both functions should be used in pair. Returns VP8_STATUS_OK
// if ok, otherwise sets and returns the error status on *dec.
VP8StatusCode VP8EnterCritical(VP8Decoder* const dec, VP8Io* const io);
// Must always be called in pair with VP8EnterCritical().
// Returns false in case of error.
int VP8ExitCritical(VP8Decoder* const dec, VP8Io* const io);
// Return the multi-threading method to use (0=off), depending
// on options and bitstream size. Only for lossy decoding.
int VP8GetThreadMethod(const WebPDecoderOptions* const options,
const WebPHeaderStructure* const headers,
int width, int height);
// Initialize dithering post-process if needed.
void VP8InitDithering(const WebPDecoderOptions* const options,
VP8Decoder* const dec);
// Process the last decoded row (filtering + output).
int VP8ProcessRow(VP8Decoder* const dec, VP8Io* const io);
// To be called at the start of a new scanline, to initialize predictors.
void VP8InitScanline(VP8Decoder* const dec);
// Decode one macroblock. Returns false if there is not enough data.
int VP8DecodeMB(VP8Decoder* const dec, VP8BitReader* const token_br);
// in dsp.c
typedef void (*VP8Idct)(const int16_t* coeffs, uint8_t* dst);
extern VP8Idct VP8Transform;
extern VP8Idct VP8TransformUV;
extern VP8Idct VP8TransformDC;
extern VP8Idct VP8TransformDCUV;
extern void (*VP8TransformWHT)(const int16_t* in, int16_t* out);
// in alpha.c
const uint8_t* VP8DecompressAlphaRows(VP8Decoder* const dec,
int row, int num_rows);
// *dst is the destination block, with stride BPS. Boundary samples are
// assumed accessible when needed.
typedef void (*VP8PredFunc)(uint8_t *dst);
extern VP8PredFunc VP8PredLuma16[NUM_B_DC_MODES];
extern VP8PredFunc VP8PredChroma8[NUM_B_DC_MODES];
extern VP8PredFunc VP8PredLuma4[NUM_BMODES];
//------------------------------------------------------------------------------
void VP8DspInit(void); // must be called before anything using the above
void VP8DspInitTables(void); // needs to be called no matter what.
// simple filter (only for luma)
typedef void (*VP8SimpleFilterFunc)(uint8_t* p, int stride, int thresh);
extern VP8SimpleFilterFunc VP8SimpleVFilter16;
extern VP8SimpleFilterFunc VP8SimpleHFilter16;
extern VP8SimpleFilterFunc VP8SimpleVFilter16i; // filter 3 inner edges
extern VP8SimpleFilterFunc VP8SimpleHFilter16i;
// regular filter (on both macroblock edges and inner edges)
typedef void (*VP8LumaFilterFunc)(uint8_t* luma, int stride,
int thresh, int ithresh, int hev_t);
typedef void (*VP8ChromaFilterFunc)(uint8_t* u, uint8_t* v, int stride,
int thresh, int ithresh, int hev_t);
// on outter edge
extern VP8LumaFilterFunc VP8VFilter16;
extern VP8LumaFilterFunc VP8HFilter16;
extern VP8ChromaFilterFunc VP8VFilter8;
extern VP8ChromaFilterFunc VP8HFilter8;
// on inner edge
extern VP8LumaFilterFunc VP8VFilter16i; // filtering 3 inner edges altogether
extern VP8LumaFilterFunc VP8HFilter16i;
extern VP8ChromaFilterFunc VP8VFilter8i; // filtering u and v altogether
extern VP8ChromaFilterFunc VP8HFilter8i;
//-----------------------------------------------------------------------------
#if defined(__cplusplus) || defined(c_plusplus)
#ifdef __cplusplus
} // extern "C"
#endif
#endif // WEBP_DEC_VP8I_H_
#endif /* WEBP_DEC_VP8I_H_ */

1404
src/dec/vp8l.c Normal file

File diff suppressed because it is too large Load Diff

132
src/dec/vp8li.h Normal file
View File

@ -0,0 +1,132 @@
// Copyright 2012 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.
// -----------------------------------------------------------------------------
//
// Lossless decoder: internal header.
//
// Author: Skal (pascal.massimino@gmail.com)
// Vikas Arora(vikaas.arora@gmail.com)
#ifndef WEBP_DEC_VP8LI_H_
#define WEBP_DEC_VP8LI_H_
#include <string.h> // for memcpy()
#include "./webpi.h"
#include "../utils/bit_reader.h"
#include "../utils/color_cache.h"
#include "../utils/huffman.h"
#ifdef __cplusplus
extern "C" {
#endif
typedef enum {
READ_DATA = 0,
READ_HDR = 1,
READ_DIM = 2
} VP8LDecodeState;
typedef struct VP8LTransform VP8LTransform;
struct VP8LTransform {
VP8LImageTransformType type_; // transform type.
int bits_; // subsampling bits defining transform window.
int xsize_; // transform window X index.
int ysize_; // transform window Y index.
uint32_t *data_; // transform data.
};
typedef struct {
int color_cache_size_;
VP8LColorCache color_cache_;
int huffman_mask_;
int huffman_subsample_bits_;
int huffman_xsize_;
uint32_t *huffman_image_;
int num_htree_groups_;
HTreeGroup *htree_groups_;
} VP8LMetadata;
typedef struct VP8LDecoder VP8LDecoder;
struct VP8LDecoder {
VP8StatusCode status_;
VP8LDecodeState action_;
VP8LDecodeState state_;
VP8Io *io_;
const WebPDecBuffer *output_; // shortcut to io->opaque->output
uint32_t *pixels_; // Internal data: either uint8_t* for alpha
// or uint32_t* for BGRA.
uint32_t *argb_cache_; // Scratch buffer for temporary BGRA storage.
VP8LBitReader br_;
int width_;
int height_;
int last_row_; // last input row decoded so far.
int last_pixel_; // last pixel decoded so far. However, it may
// not be transformed, scaled and
// color-converted yet.
int last_out_row_; // last row output so far.
VP8LMetadata hdr_;
int next_transform_;
VP8LTransform transforms_[NUM_TRANSFORMS];
// or'd bitset storing the transforms types.
uint32_t transforms_seen_;
uint8_t *rescaler_memory; // Working memory for rescaling work.
WebPRescaler *rescaler; // Common rescaler for all channels.
};
//------------------------------------------------------------------------------
// internal functions. Not public.
struct ALPHDecoder; // Defined in dec/alphai.h.
// in vp8l.c
// Decodes image header for alpha data stored using lossless compression.
// Returns false in case of error.
int VP8LDecodeAlphaHeader(struct ALPHDecoder* const alph_dec,
const uint8_t* const data, size_t data_size,
uint8_t* const output);
// Decodes *at least* 'last_row' rows of alpha. If some of the initial rows are
// already decoded in previous call(s), it will resume decoding from where it
// was paused.
// Returns false in case of bitstream error.
int VP8LDecodeAlphaImageStream(struct ALPHDecoder* const alph_dec,
int last_row);
// Allocates and initialize a new lossless decoder instance.
VP8LDecoder* VP8LNew(void);
// Decodes the image header. Returns false in case of error.
int VP8LDecodeHeader(VP8LDecoder* const dec, VP8Io* const io);
// Decodes an image. It's required to decode the lossless header before calling
// this function. Returns false in case of error, with updated dec->status_.
int VP8LDecodeImage(VP8LDecoder* const dec);
// Resets the decoder in its initial state, reclaiming memory.
// Preserves the dec->status_ value.
void VP8LClear(VP8LDecoder* const dec);
// Clears and deallocate a lossless decoder instance.
void VP8LDelete(VP8LDecoder* const dec);
//------------------------------------------------------------------------------
#ifdef __cplusplus
} // extern "C"
#endif
#endif /* WEBP_DEC_VP8LI_H_ */

File diff suppressed because it is too large Load Diff

View File

@ -1,63 +1,120 @@
// Copyright 2011 Google Inc.
// Copyright 2011 Google Inc. All Rights Reserved.
//
// This code is licensed under the same terms as WebM:
// Software License Agreement: http://www.webmproject.org/license/software/
// Additional IP Rights Grant: http://www.webmproject.org/license/additional/
// 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.
// -----------------------------------------------------------------------------
//
// Internal header: WebP decoding parameters and custom IO on buffer
//
// Author: somnath@google.com (Somnath Banerjee)
#ifndef WEBP_DEC_WEBPI_H
#define WEBP_DEC_WEBPI_H
#ifndef WEBP_DEC_WEBPI_H_
#define WEBP_DEC_WEBPI_H_
#if defined(__cplusplus) || defined(c_plusplus)
#ifdef __cplusplus
extern "C" {
#endif
#include "webp/decode_vp8.h"
#include "../utils/rescaler.h"
#include "./decode_vp8.h"
// Decoding output parameters.
//------------------------------------------------------------------------------
// WebPDecParams: Decoding output parameters. Transient internal object.
typedef struct WebPDecParams WebPDecParams;
typedef int (*OutputFunc)(const VP8Io* const io, WebPDecParams* const p);
typedef int (*OutputRowFunc)(WebPDecParams* const p, int y_pos);
struct WebPDecParams {
WebPDecBuffer* output; // output buffer.
uint8_t* tmp_y, *tmp_u, *tmp_v; // cache for the fancy upsampler
// or used for tmp rescaling
int last_y; // coordinate of the line that was last output
const WebPDecoderOptions* options; // if not NULL, use alt decoding features
// rescalers
WebPRescaler scaler_y, scaler_u, scaler_v, scaler_a;
void* memory; // overall scratch memory for the output work.
OutputFunc emit; // output RGB or YUV samples
OutputFunc emit_alpha; // output alpha channel
OutputRowFunc emit_alpha_row; // output one line of rescaled alpha values
};
// Should be called first, before any use of the WebPDecParams object.
void WebPResetDecParams(WebPDecParams* const params);
//------------------------------------------------------------------------------
// Header parsing helpers
// Structure storing a description of the RIFF headers.
typedef struct {
uint8_t* output; // rgb(a) or luma
uint8_t *u, *v; // chroma u/v
uint8_t *top_y, *top_u, *top_v; // cache for the fancy upscaler
int stride; // rgb(a) stride or luma stride
int u_stride; // chroma-u stride
int v_stride; // chroma-v stride
WEBP_CSP_MODE mode; // rgb(a) or yuv
int last_y; // coordinate of the line that was last output
int output_size; // size of 'output' buffer
int output_u_size; // size of 'u' buffer
int output_v_size; // size of 'v' buffer
int external_buffer; // If true, the output buffers are externally owned
} WebPDecParams;
const uint8_t* data; // input buffer
size_t data_size; // input buffer size
int have_all_data; // true if all data is known to be available
size_t offset; // offset to main data chunk (VP8 or VP8L)
const uint8_t* alpha_data; // points to alpha chunk (if present)
size_t alpha_data_size; // alpha chunk size
size_t compressed_size; // VP8/VP8L compressed data size
size_t riff_size; // size of the riff payload (or 0 if absent)
int is_lossless; // true if a VP8L chunk is present
} WebPHeaderStructure;
// If a RIFF container is detected, validate it and skip over it. Returns
// VP8 bit-stream size if RIFF header is valid else returns 0
uint32_t WebPCheckRIFFHeader(const uint8_t** data_ptr,
uint32_t *data_size_ptr);
// Skips over all valid chunks prior to the first VP8/VP8L frame header.
// Returns: VP8_STATUS_OK, VP8_STATUS_BITSTREAM_ERROR (invalid header/chunk),
// VP8_STATUS_NOT_ENOUGH_DATA (partial input) or VP8_STATUS_UNSUPPORTED_FEATURE
// in the case of non-decodable features (animation for instance).
// In 'headers', compressed_size, offset, alpha_data, alpha_size, and lossless
// fields are updated appropriately upon success.
VP8StatusCode WebPParseHeaders(WebPHeaderStructure* const headers);
// Initializes VP8Io with custom setup, io and teardown functions
void WebPInitCustomIo(VP8Io* const io);
//------------------------------------------------------------------------------
// Misc utils
// Initializes params_out by allocating output buffer and setting the
// stride information. It also outputs width and height information of
// the WebP image. Returns 1 if succeeds.
int WebPInitDecParams(const uint8_t* data, uint32_t data_size, int* width,
int* height, WebPDecParams* const params_out);
// Initializes VP8Io with custom setup, io and teardown functions. The default
// hooks will use the supplied 'params' as io->opaque handle.
void WebPInitCustomIo(WebPDecParams* const params, VP8Io* const io);
// Verifies various size configurations (e.g stride >= width, specified
// output size <= stride * height etc.). Returns 0 if checks fail.
int WebPCheckDecParams(const VP8Io* io, const WebPDecParams* params);
// Setup crop_xxx fields, mb_w and mb_h in io. 'src_colorspace' refers
// to the *compressed* format, not the output one.
int WebPIoInitFromOptions(const WebPDecoderOptions* const options,
VP8Io* const io, WEBP_CSP_MODE src_colorspace);
// Deallocate memory allocated by WebPInitDecParams() and reset the
// WebPDecParams object.
void WebPClearDecParams(WebPDecParams* params);
//------------------------------------------------------------------------------
// Internal functions regarding WebPDecBuffer memory (in buffer.c).
// Don't really need to be externally visible for now.
#if defined(__cplusplus) || defined(c_plusplus)
// Prepare 'buffer' with the requested initial dimensions width/height.
// If no external storage is supplied, initializes buffer by allocating output
// memory and setting up the stride information. Validate the parameters. Return
// an error code in case of problem (no memory, or invalid stride / size /
// dimension / etc.). If *options is not NULL, also verify that the options'
// parameters are valid and apply them to the width/height dimensions of the
// output buffer. This takes cropping / scaling / rotation into account.
// Also incorporates the options->flip flag to flip the buffer parameters if
// needed.
VP8StatusCode WebPAllocateDecBuffer(int width, int height,
const WebPDecoderOptions* const options,
WebPDecBuffer* const buffer);
// Flip buffer vertically by negating the various strides.
VP8StatusCode WebPFlipBuffer(WebPDecBuffer* const buffer);
// Copy 'src' into 'dst' buffer, making sure 'dst' is not marked as owner of the
// memory (still held by 'src').
void WebPCopyDecBuffer(const WebPDecBuffer* const src,
WebPDecBuffer* const dst);
// Copy and transfer ownership from src to dst (beware of parameter order!)
void WebPGrabDecBuffer(WebPDecBuffer* const src, WebPDecBuffer* const dst);
//------------------------------------------------------------------------------
#ifdef __cplusplus
} // extern "C"
#endif
#endif // WEBP_DEC_WEBPI_H
#endif /* WEBP_DEC_WEBPI_H_ */

View File

@ -1,46 +0,0 @@
// Copyright 2010 Google Inc.
//
// This code is licensed under the same terms as WebM:
// Software License Agreement: http://www.webmproject.org/license/software/
// Additional IP Rights Grant: http://www.webmproject.org/license/additional/
// -----------------------------------------------------------------------------
//
// YUV->RGB conversion function
//
// Author: Skal (pascal.massimino@gmail.com)
#include "yuv.h"
#if defined(__cplusplus) || defined(c_plusplus)
extern "C" {
#endif
enum { YUV_HALF = 1 << (YUV_FIX - 1) };
int16_t VP8kVToR[256], VP8kUToB[256];
int32_t VP8kVToG[256], VP8kUToG[256];
uint8_t VP8kClip[YUV_RANGE_MAX - YUV_RANGE_MIN];
static int done = 0;
void VP8YUVInit(void) {
int i;
if (done) {
return;
}
for (i = 0; i < 256; ++i) {
VP8kVToR[i] = (89858 * (i - 128) + YUV_HALF) >> YUV_FIX;
VP8kUToG[i] = -22014 * (i - 128) + YUV_HALF;
VP8kVToG[i] = -45773 * (i - 128);
VP8kUToB[i] = (113618 * (i - 128) + YUV_HALF) >> YUV_FIX;
}
for (i = YUV_RANGE_MIN; i < YUV_RANGE_MAX; ++i) {
const int k = ((i - 16) * 76283 + YUV_HALF) >> YUV_FIX;
VP8kClip[i - YUV_RANGE_MIN] = (k < 0) ? 0 : (k > 255) ? 255 : k;
}
done = 1;
}
#if defined(__cplusplus) || defined(c_plusplus)
} // extern "C"
#endif

View File

@ -1,66 +0,0 @@
// Copyright 2010 Google Inc.
//
// This code is licensed under the same terms as WebM:
// Software License Agreement: http://www.webmproject.org/license/software/
// Additional IP Rights Grant: http://www.webmproject.org/license/additional/
// -----------------------------------------------------------------------------
//
// inline YUV->RGB conversion function
//
// Author: Skal (pascal.massimino@gmail.com)
#ifndef WEBP_DEC_YUV_H_
#define WEBP_DEC_YUV_H_
#include "webp/decode_vp8.h"
#if defined(__cplusplus) || defined(c_plusplus)
extern "C" {
#endif
enum { YUV_FIX = 16, // fixed-point precision
YUV_RANGE_MIN = -227, // min value of r/g/b output
YUV_RANGE_MAX = 256 + 226 // max value of r/g/b output
};
extern int16_t VP8kVToR[256], VP8kUToB[256];
extern int32_t VP8kVToG[256], VP8kUToG[256];
extern uint8_t VP8kClip[YUV_RANGE_MAX - YUV_RANGE_MIN];
inline static void VP8YuvToRgb(uint8_t y, uint8_t u, uint8_t v,
uint8_t* const rgb) {
const int r_off = VP8kVToR[v];
const int g_off = (VP8kVToG[v] + VP8kUToG[u]) >> YUV_FIX;
const int b_off = VP8kUToB[u];
rgb[0] = VP8kClip[y + r_off - YUV_RANGE_MIN];
rgb[1] = VP8kClip[y + g_off - YUV_RANGE_MIN];
rgb[2] = VP8kClip[y + b_off - YUV_RANGE_MIN];
}
inline static void VP8YuvToRgba(int y, int u, int v, uint8_t* const rgba) {
VP8YuvToRgb(y, u, v, rgba);
rgba[3] = 0xff;
}
inline static void VP8YuvToBgr(uint8_t y, uint8_t u, uint8_t v,
uint8_t* const bgr) {
const int r_off = VP8kVToR[v];
const int g_off = (VP8kVToG[v] + VP8kUToG[u]) >> YUV_FIX;
const int b_off = VP8kUToB[u];
bgr[0] = VP8kClip[y + b_off - YUV_RANGE_MIN];
bgr[1] = VP8kClip[y + g_off - YUV_RANGE_MIN];
bgr[2] = VP8kClip[y + r_off - YUV_RANGE_MIN];
}
inline static void VP8YuvToBgra(int y, int u, int v, uint8_t* const bgra) {
VP8YuvToBgr(y, u, v, bgra);
bgra[3] = 0xff;
}
// Must be called before everything, to initialize the tables.
void VP8YUVInit(void);
#if defined(__cplusplus) || defined(c_plusplus)
} // extern "C"
#endif
#endif // WEBP_DEC_YUV_H_

14
src/demux/Makefile.am Normal file
View File

@ -0,0 +1,14 @@
lib_LTLIBRARIES = libwebpdemux.la
libwebpdemux_la_SOURCES =
libwebpdemux_la_SOURCES += demux.c
libwebpdemuxinclude_HEADERS =
libwebpdemuxinclude_HEADERS += ../webp/demux.h
libwebpdemuxinclude_HEADERS += ../webp/mux_types.h
libwebpdemuxinclude_HEADERS += ../webp/types.h
libwebpdemux_la_LIBADD = ../libwebp.la
libwebpdemux_la_LDFLAGS = -no-undefined -version-info 1:2:0
libwebpdemuxincludedir = $(includedir)/webp
pkgconfig_DATA = libwebpdemux.pc

1002
src/demux/demux.c Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,11 @@
prefix=@prefix@
exec_prefix=@exec_prefix@
libdir=@libdir@
includedir=@includedir@
Name: libwebpdemux
Description: Library for parsing the WebP graphics format container
Version: @PACKAGE_VERSION@
Requires: libwebp >= 0.2.0
Cflags: -I${includedir}
Libs: -L${libdir} -lwebpdemux

72
src/dsp/Makefile.am Normal file
View File

@ -0,0 +1,72 @@
noinst_LTLIBRARIES = libwebpdsp.la libwebpdsp_avx2.la
noinst_LTLIBRARIES += libwebpdsp_sse2.la libwebpdspdecode_sse2.la
if BUILD_LIBWEBPDECODER
noinst_LTLIBRARIES += libwebpdspdecode.la
endif
common_HEADERS = ../webp/types.h
commondir = $(includedir)/webp
COMMON_SOURCES =
COMMON_SOURCES += alpha_processing.c
COMMON_SOURCES += cpu.c
COMMON_SOURCES += dec.c
COMMON_SOURCES += dec_clip_tables.c
COMMON_SOURCES += dec_mips32.c
COMMON_SOURCES += dec_neon.c
COMMON_SOURCES += dsp.h
COMMON_SOURCES += lossless.c
COMMON_SOURCES += lossless.h
COMMON_SOURCES += lossless_mips32.c
COMMON_SOURCES += lossless_neon.c
COMMON_SOURCES += neon.h
COMMON_SOURCES += upsampling.c
COMMON_SOURCES += upsampling_neon.c
COMMON_SOURCES += yuv.c
COMMON_SOURCES += yuv.h
COMMON_SOURCES += yuv_mips32.c
ENC_SOURCES =
ENC_SOURCES += enc.c
ENC_SOURCES += enc_mips32.c
ENC_SOURCES += enc_neon.c
libwebpdsp_avx2_la_SOURCES =
libwebpdsp_avx2_la_SOURCES += enc_avx2.c
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
libwebpdspdecode_sse2_la_SOURCES += yuv_sse2.c
libwebpdspdecode_sse2_la_SOURCES += yuv_tables_sse2.h
libwebpdspdecode_sse2_la_CPPFLAGS = $(libwebpdsp_sse2_la_CPPFLAGS)
libwebpdspdecode_sse2_la_CFLAGS = $(libwebpdsp_sse2_la_CFLAGS)
libwebpdsp_sse2_la_SOURCES =
libwebpdsp_sse2_la_SOURCES += enc_sse2.c
libwebpdsp_sse2_la_CPPFLAGS = $(libwebpdsp_la_CPPFLAGS)
libwebpdsp_sse2_la_CFLAGS = $(AM_CFLAGS) $(SSE2_FLAGS)
libwebpdsp_sse2_la_LIBADD = libwebpdspdecode_sse2.la
libwebpdsp_la_SOURCES = $(COMMON_SOURCES) $(ENC_SOURCES)
noinst_HEADERS =
noinst_HEADERS += ../dec/decode_vp8.h
noinst_HEADERS += ../webp/decode.h
libwebpdsp_la_CPPFLAGS = $(USE_EXPERIMENTAL_CODE) $(USE_SWAP_16BIT_CSP)
libwebpdsp_la_LDFLAGS = -lm
libwebpdsp_la_LIBADD = libwebpdsp_avx2.la libwebpdsp_sse2.la
if BUILD_LIBWEBPDECODER
libwebpdspdecode_la_SOURCES = $(COMMON_SOURCES)
libwebpdspdecode_la_CPPFLAGS = $(libwebpdsp_la_CPPFLAGS)
libwebpdspdecode_la_LDFLAGS = $(libwebpdsp_la_LDFLAGS)
libwebpdspdecode_la_LIBADD = libwebpdspdecode_sse2.la
endif

329
src/dsp/alpha_processing.c Normal file
View File

@ -0,0 +1,329 @@
// Copyright 2013 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 <assert.h>
#include "./dsp.h"
// Tables can be faster on some platform but incur some extra binary size (~2k).
// #define USE_TABLES_FOR_ALPHA_MULT
// -----------------------------------------------------------------------------
#define MFIX 24 // 24bit fixed-point arithmetic
#define HALF ((1u << MFIX) >> 1)
#define KINV_255 ((1u << MFIX) / 255u)
static uint32_t Mult(uint8_t x, uint32_t mult) {
const uint32_t v = (x * mult + HALF) >> MFIX;
assert(v <= 255); // <- 24bit precision is enough to ensure that.
return v;
}
#ifdef USE_TABLES_FOR_ALPHA_MULT
static const uint32_t kMultTables[2][256] = {
{ // (255u << MFIX) / alpha
0x00000000, 0xff000000, 0x7f800000, 0x55000000, 0x3fc00000, 0x33000000,
0x2a800000, 0x246db6db, 0x1fe00000, 0x1c555555, 0x19800000, 0x172e8ba2,
0x15400000, 0x139d89d8, 0x1236db6d, 0x11000000, 0x0ff00000, 0x0f000000,
0x0e2aaaaa, 0x0d6bca1a, 0x0cc00000, 0x0c249249, 0x0b9745d1, 0x0b1642c8,
0x0aa00000, 0x0a333333, 0x09cec4ec, 0x0971c71c, 0x091b6db6, 0x08cb08d3,
0x08800000, 0x0839ce73, 0x07f80000, 0x07ba2e8b, 0x07800000, 0x07492492,
0x07155555, 0x06e45306, 0x06b5e50d, 0x0689d89d, 0x06600000, 0x063831f3,
0x06124924, 0x05ee23b8, 0x05cba2e8, 0x05aaaaaa, 0x058b2164, 0x056cefa8,
0x05500000, 0x05343eb1, 0x05199999, 0x05000000, 0x04e76276, 0x04cfb2b7,
0x04b8e38e, 0x04a2e8ba, 0x048db6db, 0x0479435e, 0x04658469, 0x045270d0,
0x04400000, 0x042e29f7, 0x041ce739, 0x040c30c3, 0x03fc0000, 0x03ec4ec4,
0x03dd1745, 0x03ce540f, 0x03c00000, 0x03b21642, 0x03a49249, 0x03976fc6,
0x038aaaaa, 0x037e3f1f, 0x03722983, 0x03666666, 0x035af286, 0x034fcace,
0x0344ec4e, 0x033a5440, 0x03300000, 0x0325ed09, 0x031c18f9, 0x0312818a,
0x03092492, 0x03000000, 0x02f711dc, 0x02ee5846, 0x02e5d174, 0x02dd7baf,
0x02d55555, 0x02cd5cd5, 0x02c590b2, 0x02bdef7b, 0x02b677d4, 0x02af286b,
0x02a80000, 0x02a0fd5c, 0x029a1f58, 0x029364d9, 0x028ccccc, 0x0286562d,
0x02800000, 0x0279c952, 0x0273b13b, 0x026db6db, 0x0267d95b, 0x026217ec,
0x025c71c7, 0x0256e62a, 0x0251745d, 0x024c1bac, 0x0246db6d, 0x0241b2f9,
0x023ca1af, 0x0237a6f4, 0x0232c234, 0x022df2df, 0x02293868, 0x02249249,
0x02200000, 0x021b810e, 0x021714fb, 0x0212bb51, 0x020e739c, 0x020a3d70,
0x02061861, 0x02020408, 0x01fe0000, 0x01fa0be8, 0x01f62762, 0x01f25213,
0x01ee8ba2, 0x01ead3ba, 0x01e72a07, 0x01e38e38, 0x01e00000, 0x01dc7f10,
0x01d90b21, 0x01d5a3e9, 0x01d24924, 0x01cefa8d, 0x01cbb7e3, 0x01c880e5,
0x01c55555, 0x01c234f7, 0x01bf1f8f, 0x01bc14e5, 0x01b914c1, 0x01b61eed,
0x01b33333, 0x01b05160, 0x01ad7943, 0x01aaaaaa, 0x01a7e567, 0x01a5294a,
0x01a27627, 0x019fcbd2, 0x019d2a20, 0x019a90e7, 0x01980000, 0x01957741,
0x0192f684, 0x01907da4, 0x018e0c7c, 0x018ba2e8, 0x018940c5, 0x0186e5f0,
0x01849249, 0x018245ae, 0x01800000, 0x017dc11f, 0x017b88ee, 0x0179574e,
0x01772c23, 0x01750750, 0x0172e8ba, 0x0170d045, 0x016ebdd7, 0x016cb157,
0x016aaaaa, 0x0168a9b9, 0x0166ae6a, 0x0164b8a7, 0x0162c859, 0x0160dd67,
0x015ef7bd, 0x015d1745, 0x015b3bea, 0x01596596, 0x01579435, 0x0155c7b4,
0x01540000, 0x01523d03, 0x01507eae, 0x014ec4ec, 0x014d0fac, 0x014b5edc,
0x0149b26c, 0x01480a4a, 0x01466666, 0x0144c6af, 0x01432b16, 0x0141938b,
0x01400000, 0x013e7063, 0x013ce4a9, 0x013b5cc0, 0x0139d89d, 0x01385830,
0x0136db6d, 0x01356246, 0x0133ecad, 0x01327a97, 0x01310bf6, 0x012fa0be,
0x012e38e3, 0x012cd459, 0x012b7315, 0x012a150a, 0x0128ba2e, 0x01276276,
0x01260dd6, 0x0124bc44, 0x01236db6, 0x01222222, 0x0120d97c, 0x011f93bc,
0x011e50d7, 0x011d10c4, 0x011bd37a, 0x011a98ef, 0x0119611a, 0x01182bf2,
0x0116f96f, 0x0115c988, 0x01149c34, 0x0113716a, 0x01124924, 0x01112358,
0x01100000, 0x010edf12, 0x010dc087, 0x010ca458, 0x010b8a7d, 0x010a72f0,
0x01095da8, 0x01084a9f, 0x010739ce, 0x01062b2e, 0x01051eb8, 0x01041465,
0x01030c30, 0x01020612, 0x01010204, 0x01000000 },
{ // alpha * KINV_255
0x00000000, 0x00010101, 0x00020202, 0x00030303, 0x00040404, 0x00050505,
0x00060606, 0x00070707, 0x00080808, 0x00090909, 0x000a0a0a, 0x000b0b0b,
0x000c0c0c, 0x000d0d0d, 0x000e0e0e, 0x000f0f0f, 0x00101010, 0x00111111,
0x00121212, 0x00131313, 0x00141414, 0x00151515, 0x00161616, 0x00171717,
0x00181818, 0x00191919, 0x001a1a1a, 0x001b1b1b, 0x001c1c1c, 0x001d1d1d,
0x001e1e1e, 0x001f1f1f, 0x00202020, 0x00212121, 0x00222222, 0x00232323,
0x00242424, 0x00252525, 0x00262626, 0x00272727, 0x00282828, 0x00292929,
0x002a2a2a, 0x002b2b2b, 0x002c2c2c, 0x002d2d2d, 0x002e2e2e, 0x002f2f2f,
0x00303030, 0x00313131, 0x00323232, 0x00333333, 0x00343434, 0x00353535,
0x00363636, 0x00373737, 0x00383838, 0x00393939, 0x003a3a3a, 0x003b3b3b,
0x003c3c3c, 0x003d3d3d, 0x003e3e3e, 0x003f3f3f, 0x00404040, 0x00414141,
0x00424242, 0x00434343, 0x00444444, 0x00454545, 0x00464646, 0x00474747,
0x00484848, 0x00494949, 0x004a4a4a, 0x004b4b4b, 0x004c4c4c, 0x004d4d4d,
0x004e4e4e, 0x004f4f4f, 0x00505050, 0x00515151, 0x00525252, 0x00535353,
0x00545454, 0x00555555, 0x00565656, 0x00575757, 0x00585858, 0x00595959,
0x005a5a5a, 0x005b5b5b, 0x005c5c5c, 0x005d5d5d, 0x005e5e5e, 0x005f5f5f,
0x00606060, 0x00616161, 0x00626262, 0x00636363, 0x00646464, 0x00656565,
0x00666666, 0x00676767, 0x00686868, 0x00696969, 0x006a6a6a, 0x006b6b6b,
0x006c6c6c, 0x006d6d6d, 0x006e6e6e, 0x006f6f6f, 0x00707070, 0x00717171,
0x00727272, 0x00737373, 0x00747474, 0x00757575, 0x00767676, 0x00777777,
0x00787878, 0x00797979, 0x007a7a7a, 0x007b7b7b, 0x007c7c7c, 0x007d7d7d,
0x007e7e7e, 0x007f7f7f, 0x00808080, 0x00818181, 0x00828282, 0x00838383,
0x00848484, 0x00858585, 0x00868686, 0x00878787, 0x00888888, 0x00898989,
0x008a8a8a, 0x008b8b8b, 0x008c8c8c, 0x008d8d8d, 0x008e8e8e, 0x008f8f8f,
0x00909090, 0x00919191, 0x00929292, 0x00939393, 0x00949494, 0x00959595,
0x00969696, 0x00979797, 0x00989898, 0x00999999, 0x009a9a9a, 0x009b9b9b,
0x009c9c9c, 0x009d9d9d, 0x009e9e9e, 0x009f9f9f, 0x00a0a0a0, 0x00a1a1a1,
0x00a2a2a2, 0x00a3a3a3, 0x00a4a4a4, 0x00a5a5a5, 0x00a6a6a6, 0x00a7a7a7,
0x00a8a8a8, 0x00a9a9a9, 0x00aaaaaa, 0x00ababab, 0x00acacac, 0x00adadad,
0x00aeaeae, 0x00afafaf, 0x00b0b0b0, 0x00b1b1b1, 0x00b2b2b2, 0x00b3b3b3,
0x00b4b4b4, 0x00b5b5b5, 0x00b6b6b6, 0x00b7b7b7, 0x00b8b8b8, 0x00b9b9b9,
0x00bababa, 0x00bbbbbb, 0x00bcbcbc, 0x00bdbdbd, 0x00bebebe, 0x00bfbfbf,
0x00c0c0c0, 0x00c1c1c1, 0x00c2c2c2, 0x00c3c3c3, 0x00c4c4c4, 0x00c5c5c5,
0x00c6c6c6, 0x00c7c7c7, 0x00c8c8c8, 0x00c9c9c9, 0x00cacaca, 0x00cbcbcb,
0x00cccccc, 0x00cdcdcd, 0x00cecece, 0x00cfcfcf, 0x00d0d0d0, 0x00d1d1d1,
0x00d2d2d2, 0x00d3d3d3, 0x00d4d4d4, 0x00d5d5d5, 0x00d6d6d6, 0x00d7d7d7,
0x00d8d8d8, 0x00d9d9d9, 0x00dadada, 0x00dbdbdb, 0x00dcdcdc, 0x00dddddd,
0x00dedede, 0x00dfdfdf, 0x00e0e0e0, 0x00e1e1e1, 0x00e2e2e2, 0x00e3e3e3,
0x00e4e4e4, 0x00e5e5e5, 0x00e6e6e6, 0x00e7e7e7, 0x00e8e8e8, 0x00e9e9e9,
0x00eaeaea, 0x00ebebeb, 0x00ececec, 0x00ededed, 0x00eeeeee, 0x00efefef,
0x00f0f0f0, 0x00f1f1f1, 0x00f2f2f2, 0x00f3f3f3, 0x00f4f4f4, 0x00f5f5f5,
0x00f6f6f6, 0x00f7f7f7, 0x00f8f8f8, 0x00f9f9f9, 0x00fafafa, 0x00fbfbfb,
0x00fcfcfc, 0x00fdfdfd, 0x00fefefe, 0x00ffffff }
};
static WEBP_INLINE uint32_t GetScale(uint32_t a, int inverse) {
return kMultTables[!inverse][a];
}
#else
static WEBP_INLINE uint32_t GetScale(uint32_t a, int inverse) {
return inverse ? (255u << MFIX) / a : a * KINV_255;
}
#endif // USE_TABLES_FOR_ALPHA_MULT
static void MultARGBRow(uint32_t* const ptr, int width, int inverse) {
int x;
for (x = 0; x < width; ++x) {
const uint32_t argb = ptr[x];
if (argb < 0xff000000u) { // alpha < 255
if (argb <= 0x00ffffffu) { // alpha == 0
ptr[x] = 0;
} else {
const uint32_t alpha = (argb >> 24) & 0xff;
const uint32_t scale = GetScale(alpha, inverse);
uint32_t out = argb & 0xff000000u;
out |= Mult(argb >> 0, scale) << 0;
out |= Mult(argb >> 8, scale) << 8;
out |= Mult(argb >> 16, scale) << 16;
ptr[x] = out;
}
}
}
}
static void MultRow(uint8_t* const ptr, const uint8_t* const alpha,
int width, int inverse) {
int x;
for (x = 0; x < width; ++x) {
const uint32_t a = alpha[x];
if (a != 255) {
if (a == 0) {
ptr[x] = 0;
} else {
const uint32_t scale = GetScale(a, inverse);
ptr[x] = Mult(ptr[x], scale);
}
}
}
}
#undef KINV_255
#undef HALF
#undef MFIX
void (*WebPMultARGBRow)(uint32_t* const ptr, int width, int inverse);
void (*WebPMultRow)(uint8_t* const ptr, const uint8_t* const alpha,
int width, int inverse);
//------------------------------------------------------------------------------
// Generic per-plane calls
void WebPMultARGBRows(uint8_t* ptr, int stride, int width, int num_rows,
int inverse) {
int n;
for (n = 0; n < num_rows; ++n) {
WebPMultARGBRow((uint32_t*)ptr, width, inverse);
ptr += stride;
}
}
void WebPMultRows(uint8_t* ptr, int stride,
const uint8_t* alpha, int alpha_stride,
int width, int num_rows, int inverse) {
int n;
for (n = 0; n < num_rows; ++n) {
WebPMultRow(ptr, alpha, width, inverse);
ptr += stride;
alpha += alpha_stride;
}
}
//------------------------------------------------------------------------------
// Premultiplied modes
// non dithered-modes
// (x * a * 32897) >> 23 is bit-wise equivalent to (int)(x * a / 255.)
// for all 8bit x or a. For bit-wise equivalence to (int)(x * a / 255. + .5),
// one can use instead: (x * a * 65793 + (1 << 23)) >> 24
#if 1 // (int)(x * a / 255.)
#define MULTIPLIER(a) ((a) * 32897U)
#define PREMULTIPLY(x, m) (((x) * (m)) >> 23)
#else // (int)(x * a / 255. + .5)
#define MULTIPLIER(a) ((a) * 65793U)
#define PREMULTIPLY(x, m) (((x) * (m) + (1U << 23)) >> 24)
#endif
static void ApplyAlphaMultiply(uint8_t* rgba, int alpha_first,
int w, int h, int stride) {
while (h-- > 0) {
uint8_t* const rgb = rgba + (alpha_first ? 1 : 0);
const uint8_t* const alpha = rgba + (alpha_first ? 0 : 3);
int i;
for (i = 0; i < w; ++i) {
const uint32_t a = alpha[4 * i];
if (a != 0xff) {
const uint32_t mult = MULTIPLIER(a);
rgb[4 * i + 0] = PREMULTIPLY(rgb[4 * i + 0], mult);
rgb[4 * i + 1] = PREMULTIPLY(rgb[4 * i + 1], mult);
rgb[4 * i + 2] = PREMULTIPLY(rgb[4 * i + 2], mult);
}
}
rgba += stride;
}
}
#undef MULTIPLIER
#undef PREMULTIPLY
// rgbA4444
#define MULTIPLIER(a) ((a) * 0x1111) // 0x1111 ~= (1 << 16) / 15
static WEBP_INLINE uint8_t dither_hi(uint8_t x) {
return (x & 0xf0) | (x >> 4);
}
static WEBP_INLINE uint8_t dither_lo(uint8_t x) {
return (x & 0x0f) | (x << 4);
}
static WEBP_INLINE uint8_t multiply(uint8_t x, uint32_t m) {
return (x * m) >> 16;
}
static WEBP_INLINE void ApplyAlphaMultiply4444(uint8_t* rgba4444,
int w, int h, int stride,
int rg_byte_pos /* 0 or 1 */) {
while (h-- > 0) {
int i;
for (i = 0; i < w; ++i) {
const uint32_t rg = rgba4444[2 * i + rg_byte_pos];
const uint32_t ba = rgba4444[2 * i + (rg_byte_pos ^ 1)];
const uint8_t a = ba & 0x0f;
const uint32_t mult = MULTIPLIER(a);
const uint8_t r = multiply(dither_hi(rg), mult);
const uint8_t g = multiply(dither_lo(rg), mult);
const uint8_t b = multiply(dither_hi(ba), mult);
rgba4444[2 * i + rg_byte_pos] = (r & 0xf0) | ((g >> 4) & 0x0f);
rgba4444[2 * i + (rg_byte_pos ^ 1)] = (b & 0xf0) | a;
}
rgba4444 += stride;
}
}
#undef MULTIPLIER
static void ApplyAlphaMultiply_16b(uint8_t* rgba4444,
int w, int h, int stride) {
#ifdef WEBP_SWAP_16BIT_CSP
ApplyAlphaMultiply4444(rgba4444, w, h, stride, 1);
#else
ApplyAlphaMultiply4444(rgba4444, w, h, stride, 0);
#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
}

130
src/dsp/cpu.c Normal file
View File

@ -0,0 +1,130 @@
// Copyright 2011 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.
// -----------------------------------------------------------------------------
//
// CPU detection
//
// Author: Christian Duvivier (cduvivier@google.com)
#include "./dsp.h"
#if defined(__ANDROID__)
#include <cpu-features.h>
#endif
//------------------------------------------------------------------------------
// SSE2 detection.
//
// apple/darwin gcc-4.0.1 defines __PIC__, but not __pic__ with -fPIC.
#if (defined(__pic__) || defined(__PIC__)) && defined(__i386__)
static WEBP_INLINE void GetCPUInfo(int cpu_info[4], int info_type) {
__asm__ volatile (
"mov %%ebx, %%edi\n"
"cpuid\n"
"xchg %%edi, %%ebx\n"
: "=a"(cpu_info[0]), "=D"(cpu_info[1]), "=c"(cpu_info[2]), "=d"(cpu_info[3])
: "a"(info_type));
}
#elif defined(__i386__) || defined(__x86_64__)
static WEBP_INLINE void GetCPUInfo(int cpu_info[4], int info_type) {
__asm__ volatile (
"cpuid\n"
: "=a"(cpu_info[0]), "=b"(cpu_info[1]), "=c"(cpu_info[2]), "=d"(cpu_info[3])
: "a"(info_type));
}
#elif defined(_MSC_FULL_VER) && _MSC_FULL_VER >= 150030729 // >= VS2008 SP1
#define GetCPUInfo(info, type) __cpuidex(info, type, 0) // set ecx=0
#elif defined(WEBP_MSC_SSE2)
#define GetCPUInfo __cpuid
#endif
// NaCl has no support for xgetbv or the raw opcode.
#if !defined(__native_client__) && (defined(__i386__) || defined(__x86_64__))
static WEBP_INLINE uint64_t xgetbv(void) {
const uint32_t ecx = 0;
uint32_t eax, edx;
// Use the raw opcode for xgetbv for compatibility with older toolchains.
__asm__ volatile (
".byte 0x0f, 0x01, 0xd0\n"
: "=a"(eax), "=d"(edx) : "c" (ecx));
return ((uint64_t)edx << 32) | eax;
}
#elif defined(_MSC_FULL_VER) && _MSC_FULL_VER >= 160040219 // >= VS2010 SP1
#define xgetbv() _xgetbv(0)
#elif defined(_MSC_VER) && defined(_M_IX86)
static WEBP_INLINE uint64_t xgetbv(void) {
uint32_t eax_, edx_;
__asm {
xor ecx, ecx // ecx = 0
// Use the raw opcode for xgetbv for compatibility with older toolchains.
__asm _emit 0x0f __asm _emit 0x01 __asm _emit 0xd0
mov eax_, eax
mov edx_, edx
}
return ((uint64_t)edx_ << 32) | eax_;
}
#else
#define xgetbv() 0U // no AVX for older x64 or unrecognized toolchains.
#endif
#if defined(__i386__) || defined(__x86_64__) || defined(WEBP_MSC_SSE2)
static int x86CPUInfo(CPUFeature feature) {
int cpu_info[4];
GetCPUInfo(cpu_info, 1);
if (feature == kSSE2) {
return 0 != (cpu_info[3] & 0x04000000);
}
if (feature == kSSE3) {
return 0 != (cpu_info[2] & 0x00000001);
}
if (feature == kAVX) {
// bits 27 (OSXSAVE) & 28 (256-bit AVX)
if ((cpu_info[2] & 0x18000000) == 0x18000000) {
// XMM state and YMM state enabled by the OS.
return (xgetbv() & 0x6) == 0x6;
}
}
if (feature == kAVX2) {
if (x86CPUInfo(kAVX)) {
GetCPUInfo(cpu_info, 7);
return ((cpu_info[1] & 0x00000020) == 0x00000020);
}
}
return 0;
}
VP8CPUInfo VP8GetCPUInfo = x86CPUInfo;
#elif defined(WEBP_ANDROID_NEON) // NB: needs to be before generic NEON test.
static int AndroidCPUInfo(CPUFeature feature) {
const AndroidCpuFamily cpu_family = android_getCpuFamily();
const uint64_t cpu_features = android_getCpuFeatures();
if (feature == kNEON) {
return (cpu_family == ANDROID_CPU_FAMILY_ARM &&
0 != (cpu_features & ANDROID_CPU_ARM_FEATURE_NEON));
}
return 0;
}
VP8CPUInfo VP8GetCPUInfo = AndroidCPUInfo;
#elif defined(WEBP_USE_NEON)
// define a dummy function to enable turning off NEON at runtime by setting
// VP8DecGetCPUInfo = NULL
static int armCPUInfo(CPUFeature feature) {
(void)feature;
return 1;
}
VP8CPUInfo VP8GetCPUInfo = armCPUInfo;
#elif defined(WEBP_USE_MIPS32)
static int mipsCPUInfo(CPUFeature feature) {
(void)feature;
return 1;
}
VP8CPUInfo VP8GetCPUInfo = mipsCPUInfo;
#else
VP8CPUInfo VP8GetCPUInfo = NULL;
#endif

View File

@ -1,72 +1,44 @@
// Copyright 2010 Google Inc.
// Copyright 2010 Google Inc. All Rights Reserved.
//
// This code is licensed under the same terms as WebM:
// Software License Agreement: http://www.webmproject.org/license/software/
// Additional IP Rights Grant: http://www.webmproject.org/license/additional/
// 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.
// -----------------------------------------------------------------------------
//
// speed-critical functions.
// Speed-critical decoding functions.
//
// Author: Skal (pascal.massimino@gmail.com)
#include "vp8i.h"
#include "./dsp.h"
#include "../dec/vp8i.h"
#if defined(__SSE2__)
#include <emmintrin.h>
#endif
//------------------------------------------------------------------------------
#if defined(__cplusplus) || defined(c_plusplus)
extern "C" {
#endif
//-----------------------------------------------------------------------------
// run-time tables (~4k)
static uint8_t abs0[255 + 255 + 1]; // abs(i)
static uint8_t abs1[255 + 255 + 1]; // abs(i)>>1
static int8_t sclip1[1020 + 1020 + 1]; // clips [-1020, 1020] to [-128, 127]
static int8_t sclip2[112 + 112 + 1]; // clips [-112, 112] to [-16, 15]
static uint8_t clip1[255 + 510 + 1]; // clips [-255,510] to [0,255]
// We declare this variable 'volatile' to prevent instruction reordering
// and make sure it's set to true _last_ (so as to be thread-safe)
static volatile int tables_ok = 0;
void VP8DspInitTables(void) {
if (!tables_ok) {
int i;
for (i = -255; i <= 255; ++i) {
abs0[255 + i] = (i < 0) ? -i : i;
abs1[255 + i] = abs0[255 + i] >> 1;
}
for (i = -1020; i <= 1020; ++i) {
sclip1[1020 + i] = (i < -128) ? -128 : (i > 127) ? 127 : i;
}
for (i = -112; i <= 112; ++i) {
sclip2[112 + i] = (i < -16) ? -16 : (i > 15) ? 15 : i;
}
for (i = -255; i <= 255 + 255; ++i) {
clip1[255 + i] = (i < 0) ? 0 : (i > 255) ? 255 : i;
}
tables_ok = 1;
}
}
static inline uint8_t clip_8b(int v) {
static WEBP_INLINE uint8_t clip_8b(int v) {
return (!(v & ~0xff)) ? v : (v < 0) ? 0 : 255;
}
//-----------------------------------------------------------------------------
//------------------------------------------------------------------------------
// Transforms (Paragraph 14.4)
#define STORE(x, y, v) \
dst[x + y * BPS] = clip_8b(dst[x + y * BPS] + ((v) >> 3))
#define STORE2(y, dc, d, c) do { \
const int DC = (dc); \
STORE(0, y, DC + (d)); \
STORE(1, y, DC + (c)); \
STORE(2, y, DC - (c)); \
STORE(3, y, DC - (d)); \
} while (0)
static const int kC1 = 20091 + (1 << 16);
static const int kC2 = 35468;
#define MUL(a, b) (((a) * (b)) >> 16)
static void Transform(const int16_t* in, uint8_t* dst) {
static void TransformOne(const int16_t* in, uint8_t* dst) {
int C[4 * 4], *tmp;
int i;
tmp = C;
@ -104,13 +76,32 @@ static void Transform(const int16_t* in, uint8_t* dst) {
dst += BPS;
}
}
// Simplified transform when only in[0], in[1] and in[4] are non-zero
static void TransformAC3(const int16_t* in, uint8_t* dst) {
const int a = in[0] + 4;
const int c4 = MUL(in[4], kC2);
const int d4 = MUL(in[4], kC1);
const int c1 = MUL(in[1], kC2);
const int d1 = MUL(in[1], kC1);
STORE2(0, a + d4, d1, c1);
STORE2(1, a + c4, d1, c1);
STORE2(2, a - c4, d1, c1);
STORE2(3, a - d4, d1, c1);
}
#undef MUL
#undef STORE2
static void TransformTwo(const int16_t* in, uint8_t* dst, int do_two) {
TransformOne(in, dst);
if (do_two) {
TransformOne(in + 16, dst + 4);
}
}
static void TransformUV(const int16_t* in, uint8_t* dst) {
Transform(in + 0 * 16, dst);
Transform(in + 1 * 16, dst + 4);
Transform(in + 2 * 16, dst + 4 * BPS);
Transform(in + 3 * 16, dst + 4 * BPS + 4);
VP8Transform(in + 0 * 16, dst, 1);
VP8Transform(in + 2 * 16, dst + 4 * BPS, 1);
}
static void TransformDC(const int16_t *in, uint8_t* dst) {
@ -124,21 +115,15 @@ static void TransformDC(const int16_t *in, uint8_t* dst) {
}
static void TransformDCUV(const int16_t* in, uint8_t* dst) {
if (in[0 * 16]) TransformDC(in + 0 * 16, dst);
if (in[1 * 16]) TransformDC(in + 1 * 16, dst + 4);
if (in[2 * 16]) TransformDC(in + 2 * 16, dst + 4 * BPS);
if (in[3 * 16]) TransformDC(in + 3 * 16, dst + 4 * BPS + 4);
if (in[0 * 16]) VP8TransformDC(in + 0 * 16, dst);
if (in[1 * 16]) VP8TransformDC(in + 1 * 16, dst + 4);
if (in[2 * 16]) VP8TransformDC(in + 2 * 16, dst + 4 * BPS);
if (in[3 * 16]) VP8TransformDC(in + 3 * 16, dst + 4 * BPS + 4);
}
#undef STORE
// default C implementations:
VP8Idct VP8Transform = Transform;
VP8Idct VP8TransformUV = TransformUV;
VP8Idct VP8TransformDC = TransformDC;
VP8Idct VP8TransformDCUV = TransformDCUV;
//-----------------------------------------------------------------------------
//------------------------------------------------------------------------------
// Paragraph 14.3
static void TransformWHT(const int16_t* in, int16_t* out) {
@ -168,16 +153,16 @@ static void TransformWHT(const int16_t* in, int16_t* out) {
}
}
void (*VP8TransformWHT)(const int16_t* in, int16_t* out) = TransformWHT;
void (*VP8TransformWHT)(const int16_t* in, int16_t* out);
//-----------------------------------------------------------------------------
//------------------------------------------------------------------------------
// Intra predictions
#define OUT(x, y) dst[(x) + (y) * BPS]
#define DST(x, y) dst[(x) + (y) * BPS]
static inline void TrueMotion(uint8_t *dst, int size) {
static WEBP_INLINE void TrueMotion(uint8_t *dst, int size) {
const uint8_t* top = dst - BPS;
const uint8_t* const clip0 = clip1 + 255 - top[-1];
const uint8_t* const clip0 = VP8kclip1 - top[-1];
int y;
for (y = 0; y < size; ++y) {
const uint8_t* const clip = clip0 + dst[-1];
@ -192,7 +177,7 @@ static void TM4(uint8_t *dst) { TrueMotion(dst, 4); }
static void TM8uv(uint8_t *dst) { TrueMotion(dst, 8); }
static void TM16(uint8_t *dst) { TrueMotion(dst, 16); }
//-----------------------------------------------------------------------------
//------------------------------------------------------------------------------
// 16x16
static void VE16(uint8_t *dst) { // vertical
@ -210,7 +195,7 @@ static void HE16(uint8_t *dst) { // horizontal
}
}
static inline void Put16(int v, uint8_t* dst) {
static WEBP_INLINE void Put16(int v, uint8_t* dst) {
int j;
for (j = 0; j < 16; ++j) {
memset(dst + j * BPS, v, 16);
@ -248,7 +233,7 @@ static void DC16NoTopLeft(uint8_t *dst) { // DC with no top and left samples
Put16(0x80, dst);
}
//-----------------------------------------------------------------------------
//------------------------------------------------------------------------------
// 4x4
#define AVG3(a, b, c) (((a) + 2 * (b) + (c) + 2) >> 2)
@ -298,13 +283,13 @@ static void RD4(uint8_t *dst) { // Down-right
const int B = dst[1 - BPS];
const int C = dst[2 - BPS];
const int D = dst[3 - BPS];
OUT(0, 3) = AVG3(J, K, L);
OUT(0, 2) = OUT(1, 3) = AVG3(I, J, K);
OUT(0, 1) = OUT(1, 2) = OUT(2, 3) = AVG3(X, I, J);
OUT(0, 0) = OUT(1, 1) = OUT(2, 2) = OUT(3, 3) = AVG3(A, X, I);
OUT(1, 0) = OUT(2, 1) = OUT(3, 2) = AVG3(B, A, X);
OUT(2, 0) = OUT(3, 1) = AVG3(C, B, A);
OUT(3, 0) = AVG3(D, C, B);
DST(0, 3) = AVG3(J, K, L);
DST(0, 2) = DST(1, 3) = AVG3(I, J, K);
DST(0, 1) = DST(1, 2) = DST(2, 3) = AVG3(X, I, J);
DST(0, 0) = DST(1, 1) = DST(2, 2) = DST(3, 3) = AVG3(A, X, I);
DST(1, 0) = DST(2, 1) = DST(3, 2) = AVG3(B, A, X);
DST(2, 0) = DST(3, 1) = AVG3(C, B, A);
DST(3, 0) = AVG3(D, C, B);
}
static void LD4(uint8_t *dst) { // Down-Left
@ -316,13 +301,13 @@ static void LD4(uint8_t *dst) { // Down-Left
const int F = dst[5 - BPS];
const int G = dst[6 - BPS];
const int H = dst[7 - BPS];
OUT(0, 0) = AVG3(A, B, C);
OUT(1, 0) = OUT(0, 1) = AVG3(B, C, D);
OUT(2, 0) = OUT(1, 1) = OUT(0, 2) = AVG3(C, D, E);
OUT(3, 0) = OUT(2, 1) = OUT(1, 2) = OUT(0, 3) = AVG3(D, E, F);
OUT(3, 1) = OUT(2, 2) = OUT(1, 3) = AVG3(E, F, G);
OUT(3, 2) = OUT(2, 3) = AVG3(F, G, H);
OUT(3, 3) = AVG3(G, H, H);
DST(0, 0) = AVG3(A, B, C);
DST(1, 0) = DST(0, 1) = AVG3(B, C, D);
DST(2, 0) = DST(1, 1) = DST(0, 2) = AVG3(C, D, E);
DST(3, 0) = DST(2, 1) = DST(1, 2) = DST(0, 3) = AVG3(D, E, F);
DST(3, 1) = DST(2, 2) = DST(1, 3) = AVG3(E, F, G);
DST(3, 2) = DST(2, 3) = AVG3(F, G, H);
DST(3, 3) = AVG3(G, H, H);
}
static void VR4(uint8_t *dst) { // Vertical-Right
@ -334,17 +319,17 @@ static void VR4(uint8_t *dst) { // Vertical-Right
const int B = dst[1 - BPS];
const int C = dst[2 - BPS];
const int D = dst[3 - BPS];
OUT(0, 0) = OUT(1, 2) = AVG2(X, A);
OUT(1, 0) = OUT(2, 2) = AVG2(A, B);
OUT(2, 0) = OUT(3, 2) = AVG2(B, C);
OUT(3, 0) = AVG2(C, D);
DST(0, 0) = DST(1, 2) = AVG2(X, A);
DST(1, 0) = DST(2, 2) = AVG2(A, B);
DST(2, 0) = DST(3, 2) = AVG2(B, C);
DST(3, 0) = AVG2(C, D);
OUT(0, 3) = AVG3(K, J, I);
OUT(0, 2) = AVG3(J, I, X);
OUT(0, 1) = OUT(1, 3) = AVG3(I, X, A);
OUT(1, 1) = OUT(2, 3) = AVG3(X, A, B);
OUT(2, 1) = OUT(3, 3) = AVG3(A, B, C);
OUT(3, 1) = AVG3(B, C, D);
DST(0, 3) = AVG3(K, J, I);
DST(0, 2) = AVG3(J, I, X);
DST(0, 1) = DST(1, 3) = AVG3(I, X, A);
DST(1, 1) = DST(2, 3) = AVG3(X, A, B);
DST(2, 1) = DST(3, 3) = AVG3(A, B, C);
DST(3, 1) = AVG3(B, C, D);
}
static void VL4(uint8_t *dst) { // Vertical-Left
@ -356,17 +341,17 @@ static void VL4(uint8_t *dst) { // Vertical-Left
const int F = dst[5 - BPS];
const int G = dst[6 - BPS];
const int H = dst[7 - BPS];
OUT(0, 0) = AVG2(A, B);
OUT(1, 0) = OUT(0, 2) = AVG2(B, C);
OUT(2, 0) = OUT(1, 2) = AVG2(C, D);
OUT(3, 0) = OUT(2, 2) = AVG2(D, E);
DST(0, 0) = AVG2(A, B);
DST(1, 0) = DST(0, 2) = AVG2(B, C);
DST(2, 0) = DST(1, 2) = AVG2(C, D);
DST(3, 0) = DST(2, 2) = AVG2(D, E);
OUT(0, 1) = AVG3(A, B, C);
OUT(1, 1) = OUT(0, 3) = AVG3(B, C, D);
OUT(2, 1) = OUT(1, 3) = AVG3(C, D, E);
OUT(3, 1) = OUT(2, 3) = AVG3(D, E, F);
OUT(3, 2) = AVG3(E, F, G);
OUT(3, 3) = AVG3(F, G, H);
DST(0, 1) = AVG3(A, B, C);
DST(1, 1) = DST(0, 3) = AVG3(B, C, D);
DST(2, 1) = DST(1, 3) = AVG3(C, D, E);
DST(3, 1) = DST(2, 3) = AVG3(D, E, F);
DST(3, 2) = AVG3(E, F, G);
DST(3, 3) = AVG3(F, G, H);
}
static void HU4(uint8_t *dst) { // Horizontal-Up
@ -374,14 +359,14 @@ static void HU4(uint8_t *dst) { // Horizontal-Up
const int J = dst[-1 + 1 * BPS];
const int K = dst[-1 + 2 * BPS];
const int L = dst[-1 + 3 * BPS];
OUT(0, 0) = AVG2(I, J);
OUT(2, 0) = OUT(0, 1) = AVG2(J, K);
OUT(2, 1) = OUT(0, 2) = AVG2(K, L);
OUT(1, 0) = AVG3(I, J, K);
OUT(3, 0) = OUT(1, 1) = AVG3(J, K, L);
OUT(3, 1) = OUT(1, 2) = AVG3(K, L, L);
OUT(3, 2) = OUT(2, 2) =
OUT(0, 3) = OUT(1, 3) = OUT(2, 3) = OUT(3, 3) = L;
DST(0, 0) = AVG2(I, J);
DST(2, 0) = DST(0, 1) = AVG2(J, K);
DST(2, 1) = DST(0, 2) = AVG2(K, L);
DST(1, 0) = AVG3(I, J, K);
DST(3, 0) = DST(1, 1) = AVG3(J, K, L);
DST(3, 1) = DST(1, 2) = AVG3(K, L, L);
DST(3, 2) = DST(2, 2) =
DST(0, 3) = DST(1, 3) = DST(2, 3) = DST(3, 3) = L;
}
static void HD4(uint8_t *dst) { // Horizontal-Down
@ -394,23 +379,24 @@ static void HD4(uint8_t *dst) { // Horizontal-Down
const int B = dst[1 - BPS];
const int C = dst[2 - BPS];
OUT(0, 0) = OUT(2, 1) = AVG2(I, X);
OUT(0, 1) = OUT(2, 2) = AVG2(J, I);
OUT(0, 2) = OUT(2, 3) = AVG2(K, J);
OUT(0, 3) = AVG2(L, K);
DST(0, 0) = DST(2, 1) = AVG2(I, X);
DST(0, 1) = DST(2, 2) = AVG2(J, I);
DST(0, 2) = DST(2, 3) = AVG2(K, J);
DST(0, 3) = AVG2(L, K);
OUT(3, 0) = AVG3(A, B, C);
OUT(2, 0) = AVG3(X, A, B);
OUT(1, 0) = OUT(3, 1) = AVG3(I, X, A);
OUT(1, 1) = OUT(3, 2) = AVG3(J, I, X);
OUT(1, 2) = OUT(3, 3) = AVG3(K, J, I);
OUT(1, 3) = AVG3(L, K, J);
DST(3, 0) = AVG3(A, B, C);
DST(2, 0) = AVG3(X, A, B);
DST(1, 0) = DST(3, 1) = AVG3(I, X, A);
DST(1, 1) = DST(3, 2) = AVG3(J, I, X);
DST(1, 2) = DST(3, 3) = AVG3(K, J, I);
DST(1, 3) = AVG3(L, K, J);
}
#undef DST
#undef AVG3
#undef AVG2
//-----------------------------------------------------------------------------
//------------------------------------------------------------------------------
// Chroma
static void VE8uv(uint8_t *dst) { // vertical
@ -429,10 +415,10 @@ static void HE8uv(uint8_t *dst) { // horizontal
}
// helper for chroma-DC predictions
static inline void Put8x8uv(uint64_t v, uint8_t* dst) {
static WEBP_INLINE void Put8x8uv(uint8_t value, uint8_t* dst) {
int j;
for (j = 0; j < 8; ++j) {
*(uint64_t*)(dst + j * BPS) = v;
memset(dst + j * BPS, value, 8);
}
}
@ -442,7 +428,7 @@ static void DC8uv(uint8_t *dst) { // DC
for (i = 0; i < 8; ++i) {
dc0 += dst[i - BPS] + dst[-1 + i * BPS];
}
Put8x8uv((uint64_t)((dc0 >> 4) * 0x0101010101010101ULL), dst);
Put8x8uv(dc0 >> 4, dst);
}
static void DC8uvNoLeft(uint8_t *dst) { // DC with no left samples
@ -451,7 +437,7 @@ static void DC8uvNoLeft(uint8_t *dst) { // DC with no left samples
for (i = 0; i < 8; ++i) {
dc0 += dst[i - BPS];
}
Put8x8uv((uint64_t)((dc0 >> 3) * 0x0101010101010101ULL), dst);
Put8x8uv(dc0 >> 3, dst);
}
static void DC8uvNoTop(uint8_t *dst) { // DC with no top samples
@ -460,99 +446,102 @@ static void DC8uvNoTop(uint8_t *dst) { // DC with no top samples
for (i = 0; i < 8; ++i) {
dc0 += dst[-1 + i * BPS];
}
Put8x8uv((uint64_t)((dc0 >> 3) * 0x0101010101010101ULL), dst);
Put8x8uv(dc0 >> 3, dst);
}
static void DC8uvNoTopLeft(uint8_t *dst) { // DC with nothing
Put8x8uv(0x8080808080808080ULL, dst);
Put8x8uv(0x80, dst);
}
//-----------------------------------------------------------------------------
//------------------------------------------------------------------------------
// default C implementations
VP8PredFunc VP8PredLuma4[NUM_BMODES] = {
const VP8PredFunc VP8PredLuma4[NUM_BMODES] = {
DC4, TM4, VE4, HE4, RD4, VR4, LD4, VL4, HD4, HU4
};
VP8PredFunc VP8PredLuma16[NUM_B_DC_MODES] = {
const VP8PredFunc VP8PredLuma16[NUM_B_DC_MODES] = {
DC16, TM16, VE16, HE16,
DC16NoTop, DC16NoLeft, DC16NoTopLeft
};
VP8PredFunc VP8PredChroma8[NUM_B_DC_MODES] = {
const VP8PredFunc VP8PredChroma8[NUM_B_DC_MODES] = {
DC8uv, TM8uv, VE8uv, HE8uv,
DC8uvNoTop, DC8uvNoLeft, DC8uvNoTopLeft
};
//-----------------------------------------------------------------------------
//------------------------------------------------------------------------------
// Edge filtering functions
// 4 pixels in, 2 pixels out
static inline void do_filter2(uint8_t* p, int step) {
static WEBP_INLINE void do_filter2(uint8_t* p, int step) {
const int p1 = p[-2*step], p0 = p[-step], q0 = p[0], q1 = p[step];
const int a = 3 * (q0 - p0) + sclip1[1020 + p1 - q1];
const int a1 = sclip2[112 + ((a + 4) >> 3)];
const int a2 = sclip2[112 + ((a + 3) >> 3)];
p[-step] = clip1[255 + p0 + a2];
p[ 0] = clip1[255 + q0 - a1];
const int a = 3 * (q0 - p0) + VP8ksclip1[p1 - q1]; // in [-893,892]
const int a1 = VP8ksclip2[(a + 4) >> 3]; // in [-16,15]
const int a2 = VP8ksclip2[(a + 3) >> 3];
p[-step] = VP8kclip1[p0 + a2];
p[ 0] = VP8kclip1[q0 - a1];
}
// 4 pixels in, 4 pixels out
static inline void do_filter4(uint8_t* p, int step) {
static WEBP_INLINE void do_filter4(uint8_t* p, int step) {
const int p1 = p[-2*step], p0 = p[-step], q0 = p[0], q1 = p[step];
const int a = 3 * (q0 - p0);
const int a1 = sclip2[112 + ((a + 4) >> 3)];
const int a2 = sclip2[112 + ((a + 3) >> 3)];
const int a1 = VP8ksclip2[(a + 4) >> 3];
const int a2 = VP8ksclip2[(a + 3) >> 3];
const int a3 = (a1 + 1) >> 1;
p[-2*step] = clip1[255 + p1 + a3];
p[- step] = clip1[255 + p0 + a2];
p[ 0] = clip1[255 + q0 - a1];
p[ step] = clip1[255 + q1 - a3];
p[-2*step] = VP8kclip1[p1 + a3];
p[- step] = VP8kclip1[p0 + a2];
p[ 0] = VP8kclip1[q0 - a1];
p[ step] = VP8kclip1[q1 - a3];
}
// 6 pixels in, 6 pixels out
static inline void do_filter6(uint8_t* p, int step) {
static WEBP_INLINE void do_filter6(uint8_t* p, int step) {
const int p2 = p[-3*step], p1 = p[-2*step], p0 = p[-step];
const int q0 = p[0], q1 = p[step], q2 = p[2*step];
const int a = sclip1[1020 + 3 * (q0 - p0) + sclip1[1020 + p1 - q1]];
const int a = VP8ksclip1[3 * (q0 - p0) + VP8ksclip1[p1 - q1]];
// a is in [-128,127], a1 in [-27,27], a2 in [-18,18] and a3 in [-9,9]
const int a1 = (27 * a + 63) >> 7; // eq. to ((3 * a + 7) * 9) >> 7
const int a2 = (18 * a + 63) >> 7; // eq. to ((2 * a + 7) * 9) >> 7
const int a3 = (9 * a + 63) >> 7; // eq. to ((1 * a + 7) * 9) >> 7
p[-3*step] = clip1[255 + p2 + a3];
p[-2*step] = clip1[255 + p1 + a2];
p[- step] = clip1[255 + p0 + a1];
p[ 0] = clip1[255 + q0 - a1];
p[ step] = clip1[255 + q1 - a2];
p[ 2*step] = clip1[255 + q2 - a3];
p[-3*step] = VP8kclip1[p2 + a3];
p[-2*step] = VP8kclip1[p1 + a2];
p[- step] = VP8kclip1[p0 + a1];
p[ 0] = VP8kclip1[q0 - a1];
p[ step] = VP8kclip1[q1 - a2];
p[ 2*step] = VP8kclip1[q2 - a3];
}
static inline int hev(const uint8_t* p, int step, int thresh) {
static WEBP_INLINE int hev(const uint8_t* p, int step, int thresh) {
const int p1 = p[-2*step], p0 = p[-step], q0 = p[0], q1 = p[step];
return (abs0[255 + p1 - p0] > thresh) || (abs0[255 + q1 - q0] > thresh);
return (VP8kabs0[p1 - p0] > thresh) || (VP8kabs0[q1 - q0] > thresh);
}
static inline int needs_filter(const uint8_t* p, int step, int thresh) {
const int p1 = p[-2*step], p0 = p[-step], q0 = p[0], q1 = p[step];
return (2 * abs0[255 + p0 - q0] + abs1[255 + p1 - q1]) <= thresh;
static WEBP_INLINE int needs_filter(const uint8_t* p, int step, int t) {
const int p1 = p[-2 * step], p0 = p[-step], q0 = p[0], q1 = p[step];
return ((4 * VP8kabs0[p0 - q0] + VP8kabs0[p1 - q1]) <= t);
}
static inline int needs_filter2(const uint8_t* p, int step, int t, int it) {
const int p3 = p[-4*step], p2 = p[-3*step], p1 = p[-2*step], p0 = p[-step];
const int q0 = p[0], q1 = p[step], q2 = p[2*step], q3 = p[3*step];
if ((2 * abs0[255 + p0 - q0] + abs1[255 + p1 - q1]) > t)
return 0;
return abs0[255 + p3 - p2] <= it && abs0[255 + p2 - p1] <= it &&
abs0[255 + p1 - p0] <= it && abs0[255 + q3 - q2] <= it &&
abs0[255 + q2 - q1] <= it && abs0[255 + q1 - q0] <= it;
static WEBP_INLINE int needs_filter2(const uint8_t* p,
int step, int t, int it) {
const int p3 = p[-4 * step], p2 = p[-3 * step], p1 = p[-2 * step];
const int p0 = p[-step], q0 = p[0];
const int q1 = p[step], q2 = p[2 * step], q3 = p[3 * step];
if ((4 * VP8kabs0[p0 - q0] + VP8kabs0[p1 - q1]) > t) return 0;
return VP8kabs0[p3 - p2] <= it && VP8kabs0[p2 - p1] <= it &&
VP8kabs0[p1 - p0] <= it && VP8kabs0[q3 - q2] <= it &&
VP8kabs0[q2 - q1] <= it && VP8kabs0[q1 - q0] <= it;
}
//-----------------------------------------------------------------------------
//------------------------------------------------------------------------------
// Simple In-loop filtering (Paragraph 15.2)
static void SimpleVFilter16(uint8_t* p, int stride, int thresh) {
int i;
const int thresh2 = 2 * thresh + 1;
for (i = 0; i < 16; ++i) {
if (needs_filter(p + i, stride, thresh)) {
if (needs_filter(p + i, stride, thresh2)) {
do_filter2(p + i, stride);
}
}
@ -560,8 +549,9 @@ static void SimpleVFilter16(uint8_t* p, int stride, int thresh) {
static void SimpleHFilter16(uint8_t* p, int stride, int thresh) {
int i;
const int thresh2 = 2 * thresh + 1;
for (i = 0; i < 16; ++i) {
if (needs_filter(p + i * stride, 1, thresh)) {
if (needs_filter(p + i * stride, 1, thresh2)) {
do_filter2(p + i * stride, 1);
}
}
@ -583,13 +573,15 @@ static void SimpleHFilter16i(uint8_t* p, int stride, int thresh) {
}
}
//-----------------------------------------------------------------------------
//------------------------------------------------------------------------------
// Complex In-loop filtering (Paragraph 15.3)
static inline void FilterLoop26(uint8_t* p, int hstride, int vstride, int size,
int thresh, int ithresh, int hev_thresh) {
static WEBP_INLINE void FilterLoop26(uint8_t* p,
int hstride, int vstride, int size,
int thresh, int ithresh, int hev_thresh) {
const int thresh2 = 2 * thresh + 1;
while (size-- > 0) {
if (needs_filter2(p, hstride, thresh, ithresh)) {
if (needs_filter2(p, hstride, thresh2, ithresh)) {
if (hev(p, hstride, hev_thresh)) {
do_filter2(p, hstride);
} else {
@ -600,10 +592,12 @@ static inline void FilterLoop26(uint8_t* p, int hstride, int vstride, int size,
}
}
static inline void FilterLoop24(uint8_t* p, int hstride, int vstride, int size,
int thresh, int ithresh, int hev_thresh) {
static WEBP_INLINE void FilterLoop24(uint8_t* p,
int hstride, int vstride, int size,
int thresh, int ithresh, int hev_thresh) {
const int thresh2 = 2 * thresh + 1;
while (size-- > 0) {
if (needs_filter2(p, hstride, thresh, ithresh)) {
if (needs_filter2(p, hstride, thresh2, ithresh)) {
if (hev(p, hstride, hev_thresh)) {
do_filter2(p, hstride);
} else {
@ -669,28 +663,69 @@ static void HFilter8i(uint8_t* u, uint8_t* v, int stride,
FilterLoop24(v + 4, 1, stride, 8, thresh, ithresh, hev_thresh);
}
//-----------------------------------------------------------------------------
//------------------------------------------------------------------------------
void (*VP8VFilter16)(uint8_t*, int, int, int, int) = VFilter16;
void (*VP8HFilter16)(uint8_t*, int, int, int, int) = HFilter16;
void (*VP8VFilter8)(uint8_t*, uint8_t*, int, int, int, int) = VFilter8;
void (*VP8HFilter8)(uint8_t*, uint8_t*, int, int, int, int) = HFilter8;
void (*VP8VFilter16i)(uint8_t*, int, int, int, int) = VFilter16i;
void (*VP8HFilter16i)(uint8_t*, int, int, int, int) = HFilter16i;
void (*VP8VFilter8i)(uint8_t*, uint8_t*, int, int, int, int) = VFilter8i;
void (*VP8HFilter8i)(uint8_t*, uint8_t*, int, int, int, int) = HFilter8i;
VP8DecIdct2 VP8Transform;
VP8DecIdct VP8TransformAC3;
VP8DecIdct VP8TransformUV;
VP8DecIdct VP8TransformDC;
VP8DecIdct VP8TransformDCUV;
void (*VP8SimpleVFilter16)(uint8_t*, int, int) = SimpleVFilter16;
void (*VP8SimpleHFilter16)(uint8_t*, int, int) = SimpleHFilter16;
void (*VP8SimpleVFilter16i)(uint8_t*, int, int) = SimpleVFilter16i;
void (*VP8SimpleHFilter16i)(uint8_t*, int, int) = SimpleHFilter16i;
VP8LumaFilterFunc VP8VFilter16;
VP8LumaFilterFunc VP8HFilter16;
VP8ChromaFilterFunc VP8VFilter8;
VP8ChromaFilterFunc VP8HFilter8;
VP8LumaFilterFunc VP8VFilter16i;
VP8LumaFilterFunc VP8HFilter16i;
VP8ChromaFilterFunc VP8VFilter8i;
VP8ChromaFilterFunc VP8HFilter8i;
VP8SimpleFilterFunc VP8SimpleVFilter16;
VP8SimpleFilterFunc VP8SimpleHFilter16;
VP8SimpleFilterFunc VP8SimpleVFilter16i;
VP8SimpleFilterFunc VP8SimpleHFilter16i;
//-----------------------------------------------------------------------------
extern void VP8DspInitSSE2(void);
extern void VP8DspInitNEON(void);
extern void VP8DspInitMIPS32(void);
void VP8DspInit(void) {
// later we'll plug some SSE2 variant here
VP8InitClipTables();
VP8TransformWHT = TransformWHT;
VP8Transform = TransformTwo;
VP8TransformUV = TransformUV;
VP8TransformDC = TransformDC;
VP8TransformDCUV = TransformDCUV;
VP8TransformAC3 = TransformAC3;
VP8VFilter16 = VFilter16;
VP8HFilter16 = HFilter16;
VP8VFilter8 = VFilter8;
VP8HFilter8 = HFilter8;
VP8VFilter16i = VFilter16i;
VP8HFilter16i = HFilter16i;
VP8VFilter8i = VFilter8i;
VP8HFilter8i = HFilter8i;
VP8SimpleVFilter16 = SimpleVFilter16;
VP8SimpleHFilter16 = SimpleHFilter16;
VP8SimpleVFilter16i = SimpleVFilter16i;
VP8SimpleHFilter16i = SimpleHFilter16i;
// If defined, use CPUInfo() to overwrite some pointers with faster versions.
if (VP8GetCPUInfo != NULL) {
#if defined(WEBP_USE_SSE2)
if (VP8GetCPUInfo(kSSE2)) {
VP8DspInitSSE2();
}
#elif defined(WEBP_USE_NEON)
if (VP8GetCPUInfo(kNEON)) {
VP8DspInitNEON();
}
#elif defined(WEBP_USE_MIPS32)
if (VP8GetCPUInfo(kMIPS32)) {
VP8DspInitMIPS32();
}
#endif
}
}
#if defined(__cplusplus) || defined(c_plusplus)
} // extern "C"
#endif

366
src/dsp/dec_clip_tables.c Normal file
View File

@ -0,0 +1,366 @@
// 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.
// -----------------------------------------------------------------------------
//
// Clipping tables for filtering
//
// Author: Skal (pascal.massimino@gmail.com)
#include "./dsp.h"
#define USE_STATIC_TABLES // undefine to have run-time table initialization
#ifdef USE_STATIC_TABLES
static const uint8_t abs0[255 + 255 + 1] = {
0xff, 0xfe, 0xfd, 0xfc, 0xfb, 0xfa, 0xf9, 0xf8, 0xf7, 0xf6, 0xf5, 0xf4,
0xf3, 0xf2, 0xf1, 0xf0, 0xef, 0xee, 0xed, 0xec, 0xeb, 0xea, 0xe9, 0xe8,
0xe7, 0xe6, 0xe5, 0xe4, 0xe3, 0xe2, 0xe1, 0xe0, 0xdf, 0xde, 0xdd, 0xdc,
0xdb, 0xda, 0xd9, 0xd8, 0xd7, 0xd6, 0xd5, 0xd4, 0xd3, 0xd2, 0xd1, 0xd0,
0xcf, 0xce, 0xcd, 0xcc, 0xcb, 0xca, 0xc9, 0xc8, 0xc7, 0xc6, 0xc5, 0xc4,
0xc3, 0xc2, 0xc1, 0xc0, 0xbf, 0xbe, 0xbd, 0xbc, 0xbb, 0xba, 0xb9, 0xb8,
0xb7, 0xb6, 0xb5, 0xb4, 0xb3, 0xb2, 0xb1, 0xb0, 0xaf, 0xae, 0xad, 0xac,
0xab, 0xaa, 0xa9, 0xa8, 0xa7, 0xa6, 0xa5, 0xa4, 0xa3, 0xa2, 0xa1, 0xa0,
0x9f, 0x9e, 0x9d, 0x9c, 0x9b, 0x9a, 0x99, 0x98, 0x97, 0x96, 0x95, 0x94,
0x93, 0x92, 0x91, 0x90, 0x8f, 0x8e, 0x8d, 0x8c, 0x8b, 0x8a, 0x89, 0x88,
0x87, 0x86, 0x85, 0x84, 0x83, 0x82, 0x81, 0x80, 0x7f, 0x7e, 0x7d, 0x7c,
0x7b, 0x7a, 0x79, 0x78, 0x77, 0x76, 0x75, 0x74, 0x73, 0x72, 0x71, 0x70,
0x6f, 0x6e, 0x6d, 0x6c, 0x6b, 0x6a, 0x69, 0x68, 0x67, 0x66, 0x65, 0x64,
0x63, 0x62, 0x61, 0x60, 0x5f, 0x5e, 0x5d, 0x5c, 0x5b, 0x5a, 0x59, 0x58,
0x57, 0x56, 0x55, 0x54, 0x53, 0x52, 0x51, 0x50, 0x4f, 0x4e, 0x4d, 0x4c,
0x4b, 0x4a, 0x49, 0x48, 0x47, 0x46, 0x45, 0x44, 0x43, 0x42, 0x41, 0x40,
0x3f, 0x3e, 0x3d, 0x3c, 0x3b, 0x3a, 0x39, 0x38, 0x37, 0x36, 0x35, 0x34,
0x33, 0x32, 0x31, 0x30, 0x2f, 0x2e, 0x2d, 0x2c, 0x2b, 0x2a, 0x29, 0x28,
0x27, 0x26, 0x25, 0x24, 0x23, 0x22, 0x21, 0x20, 0x1f, 0x1e, 0x1d, 0x1c,
0x1b, 0x1a, 0x19, 0x18, 0x17, 0x16, 0x15, 0x14, 0x13, 0x12, 0x11, 0x10,
0x0f, 0x0e, 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08, 0x07, 0x06, 0x05, 0x04,
0x03, 0x02, 0x01, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14,
0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20,
0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c,
0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38,
0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, 0x40, 0x41, 0x42, 0x43, 0x44,
0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50,
0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x5b, 0x5c,
0x5d, 0x5e, 0x5f, 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68,
0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74,
0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 0x80,
0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c,
0x8d, 0x8e, 0x8f, 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98,
0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, 0xa0, 0xa1, 0xa2, 0xa3, 0xa4,
0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, 0xb0,
0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xbb, 0xbc,
0xbd, 0xbe, 0xbf, 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8,
0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, 0xd0, 0xd1, 0xd2, 0xd3, 0xd4,
0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, 0xe0,
0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb, 0xec,
0xed, 0xee, 0xef, 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8,
0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff
};
static const int8_t sclip1[1020 + 1020 + 1] = {
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
0x80, 0x80, 0x80, 0x80, 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 0x90, 0x91, 0x92, 0x93,
0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab,
0xac, 0xad, 0xae, 0xaf, 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7,
0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, 0xc0, 0xc1, 0xc2, 0xc3,
0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xdb,
0xdc, 0xdd, 0xde, 0xdf, 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7,
0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, 0xf0, 0xf1, 0xf2, 0xf3,
0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff,
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b,
0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23,
0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b,
0x3c, 0x3d, 0x3e, 0x3f, 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50, 0x51, 0x52, 0x53,
0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b,
0x6c, 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f,
0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f,
0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f,
0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f,
0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f,
0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f,
0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f,
0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f,
0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f,
0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f,
0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f,
0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f,
0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f,
0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f,
0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f,
0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f,
0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f,
0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f,
0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f,
0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f,
0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f,
0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f,
0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f,
0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f,
0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f,
0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f,
0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f,
0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f,
0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f,
0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f,
0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f,
0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f,
0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f,
0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f,
0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f,
0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f,
0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f,
0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f,
0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f,
0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f,
0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f,
0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f,
0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f,
0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f,
0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f,
0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f,
0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f,
0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f,
0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f,
0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f,
0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f,
0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f,
0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f,
0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f,
0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f,
0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f,
0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f,
0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f,
0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f,
0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f,
0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f,
0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f,
0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f,
0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f,
0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f,
0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f,
0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f,
0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f,
0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f,
0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f,
0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f,
0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f,
0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f,
0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f,
0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f
};
static const int8_t sclip2[112 + 112 + 1] = {
0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0,
0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0,
0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0,
0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0,
0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0,
0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0,
0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0,
0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0,
0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb,
0xfc, 0xfd, 0xfe, 0xff, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f,
0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f,
0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f,
0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f,
0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f,
0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f,
0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f,
0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f,
0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f
};
static const uint8_t clip1[255 + 511 + 1] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14,
0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20,
0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c,
0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38,
0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, 0x40, 0x41, 0x42, 0x43, 0x44,
0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50,
0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x5b, 0x5c,
0x5d, 0x5e, 0x5f, 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68,
0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74,
0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 0x80,
0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c,
0x8d, 0x8e, 0x8f, 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98,
0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, 0xa0, 0xa1, 0xa2, 0xa3, 0xa4,
0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, 0xb0,
0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xbb, 0xbc,
0xbd, 0xbe, 0xbf, 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8,
0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, 0xd0, 0xd1, 0xd2, 0xd3, 0xd4,
0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, 0xe0,
0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb, 0xec,
0xed, 0xee, 0xef, 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8,
0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
};
#else
// uninitialized tables
static uint8_t abs0[255 + 255 + 1];
static int8_t sclip1[1020 + 1020 + 1];
static int8_t sclip2[112 + 112 + 1];
static uint8_t clip1[255 + 511 + 1];
// We declare this variable 'volatile' to prevent instruction reordering
// and make sure it's set to true _last_ (so as to be thread-safe)
static volatile int tables_ok = 0;
#endif
const int8_t* const VP8ksclip1 = &sclip1[1020];
const int8_t* const VP8ksclip2 = &sclip2[112];
const uint8_t* const VP8kclip1 = &clip1[255];
const uint8_t* const VP8kabs0 = &abs0[255];
void VP8InitClipTables(void) {
#if !defined(USE_STATIC_TABLES)
int i;
if (!tables_ok) {
for (i = -255; i <= 255; ++i) {
abs0[255 + i] = (i < 0) ? -i : i;
}
for (i = -1020; i <= 1020; ++i) {
sclip1[1020 + i] = (i < -128) ? -128 : (i > 127) ? 127 : i;
}
for (i = -112; i <= 112; ++i) {
sclip2[112 + i] = (i < -16) ? -16 : (i > 15) ? 15 : i;
}
for (i = -255; i <= 255 + 255; ++i) {
clip1[255 + i] = (i < 0) ? 0 : (i > 255) ? 255 : i;
}
tables_ok = 1;
}
#endif // USE_STATIC_TABLES
}

578
src/dsp/dec_mips32.c Normal file
View File

@ -0,0 +1,578 @@
// 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.
// -----------------------------------------------------------------------------
//
// MIPS version of dsp functions
//
// Author(s): Djordje Pesut (djordje.pesut@imgtec.com)
// Jovan Zelincevic (jovan.zelincevic@imgtec.com)
#include "./dsp.h"
#if defined(WEBP_USE_MIPS32)
static const int kC1 = 20091 + (1 << 16);
static const int kC2 = 35468;
static WEBP_INLINE int abs_mips32(int x) {
const int sign = x >> 31;
return (x ^ sign) - sign;
}
// 4 pixels in, 2 pixels out
static WEBP_INLINE void do_filter2(uint8_t* p, int step) {
const int p1 = p[-2 * step], p0 = p[-step], q0 = p[0], q1 = p[step];
const int a = 3 * (q0 - p0) + VP8ksclip1[p1 - q1];
const int a1 = VP8ksclip2[(a + 4) >> 3];
const int a2 = VP8ksclip2[(a + 3) >> 3];
p[-step] = VP8kclip1[p0 + a2];
p[ 0] = VP8kclip1[q0 - a1];
}
// 4 pixels in, 4 pixels out
static WEBP_INLINE void do_filter4(uint8_t* p, int step) {
const int p1 = p[-2 * step], p0 = p[-step], q0 = p[0], q1 = p[step];
const int a = 3 * (q0 - p0);
const int a1 = VP8ksclip2[(a + 4) >> 3];
const int a2 = VP8ksclip2[(a + 3) >> 3];
const int a3 = (a1 + 1) >> 1;
p[-2 * step] = VP8kclip1[p1 + a3];
p[- step] = VP8kclip1[p0 + a2];
p[ 0] = VP8kclip1[q0 - a1];
p[ step] = VP8kclip1[q1 - a3];
}
// 6 pixels in, 6 pixels out
static WEBP_INLINE void do_filter6(uint8_t* p, int step) {
const int p2 = p[-3 * step], p1 = p[-2 * step], p0 = p[-step];
const int q0 = p[0], q1 = p[step], q2 = p[2 * step];
const int a = VP8ksclip1[3 * (q0 - p0) + VP8ksclip1[p1 - q1]];
const int a1 = (27 * a + 63) >> 7; // eq. to ((3 * a + 7) * 9) >> 7
const int a2 = (18 * a + 63) >> 7; // eq. to ((2 * a + 7) * 9) >> 7
const int a3 = (9 * a + 63) >> 7; // eq. to ((1 * a + 7) * 9) >> 7
p[-3 * step] = VP8kclip1[p2 + a3];
p[-2 * step] = VP8kclip1[p1 + a2];
p[- step] = VP8kclip1[p0 + a1];
p[ 0] = VP8kclip1[q0 - a1];
p[ step] = VP8kclip1[q1 - a2];
p[ 2 * step] = VP8kclip1[q2 - a3];
}
static WEBP_INLINE int hev(const uint8_t* p, int step, int thresh) {
const int p1 = p[-2 * step], p0 = p[-step], q0 = p[0], q1 = p[step];
return (abs_mips32(p1 - p0) > thresh) || (abs_mips32(q1 - q0) > thresh);
}
static WEBP_INLINE int needs_filter(const uint8_t* p, int step, int thresh) {
const int p1 = p[-2 * step], p0 = p[-step], q0 = p[0], q1 = p[step];
return ((2 * abs_mips32(p0 - q0) + (abs_mips32(p1 - q1) >> 1)) <= thresh);
}
static WEBP_INLINE int needs_filter2(const uint8_t* p,
int step, int t, int it) {
const int p3 = p[-4 * step], p2 = p[-3 * step];
const int p1 = p[-2 * step], p0 = p[-step];
const int q0 = p[0], q1 = p[step], q2 = p[2 * step], q3 = p[3 * step];
if ((2 * abs_mips32(p0 - q0) + (abs_mips32(p1 - q1) >> 1)) > t) {
return 0;
}
return abs_mips32(p3 - p2) <= it && abs_mips32(p2 - p1) <= it &&
abs_mips32(p1 - p0) <= it && abs_mips32(q3 - q2) <= it &&
abs_mips32(q2 - q1) <= it && abs_mips32(q1 - q0) <= it;
}
static WEBP_INLINE void FilterLoop26(uint8_t* p,
int hstride, int vstride, int size,
int thresh, int ithresh, int hev_thresh) {
while (size-- > 0) {
if (needs_filter2(p, hstride, thresh, ithresh)) {
if (hev(p, hstride, hev_thresh)) {
do_filter2(p, hstride);
} else {
do_filter6(p, hstride);
}
}
p += vstride;
}
}
static WEBP_INLINE void FilterLoop24(uint8_t* p,
int hstride, int vstride, int size,
int thresh, int ithresh, int hev_thresh) {
while (size-- > 0) {
if (needs_filter2(p, hstride, thresh, ithresh)) {
if (hev(p, hstride, hev_thresh)) {
do_filter2(p, hstride);
} else {
do_filter4(p, hstride);
}
}
p += vstride;
}
}
// on macroblock edges
static void VFilter16(uint8_t* p, int stride,
int thresh, int ithresh, int hev_thresh) {
FilterLoop26(p, stride, 1, 16, thresh, ithresh, hev_thresh);
}
static void HFilter16(uint8_t* p, int stride,
int thresh, int ithresh, int hev_thresh) {
FilterLoop26(p, 1, stride, 16, thresh, ithresh, hev_thresh);
}
// 8-pixels wide variant, for chroma filtering
static void VFilter8(uint8_t* u, uint8_t* v, int stride,
int thresh, int ithresh, int hev_thresh) {
FilterLoop26(u, stride, 1, 8, thresh, ithresh, hev_thresh);
FilterLoop26(v, stride, 1, 8, thresh, ithresh, hev_thresh);
}
static void HFilter8(uint8_t* u, uint8_t* v, int stride,
int thresh, int ithresh, int hev_thresh) {
FilterLoop26(u, 1, stride, 8, thresh, ithresh, hev_thresh);
FilterLoop26(v, 1, stride, 8, thresh, ithresh, hev_thresh);
}
static void VFilter8i(uint8_t* u, uint8_t* v, int stride,
int thresh, int ithresh, int hev_thresh) {
FilterLoop24(u + 4 * stride, stride, 1, 8, thresh, ithresh, hev_thresh);
FilterLoop24(v + 4 * stride, stride, 1, 8, thresh, ithresh, hev_thresh);
}
static void HFilter8i(uint8_t* u, uint8_t* v, int stride,
int thresh, int ithresh, int hev_thresh) {
FilterLoop24(u + 4, 1, stride, 8, thresh, ithresh, hev_thresh);
FilterLoop24(v + 4, 1, stride, 8, thresh, ithresh, hev_thresh);
}
// on three inner edges
static void VFilter16i(uint8_t* p, int stride,
int thresh, int ithresh, int hev_thresh) {
int k;
for (k = 3; k > 0; --k) {
p += 4 * stride;
FilterLoop24(p, stride, 1, 16, thresh, ithresh, hev_thresh);
}
}
static void HFilter16i(uint8_t* p, int stride,
int thresh, int ithresh, int hev_thresh) {
int k;
for (k = 3; k > 0; --k) {
p += 4;
FilterLoop24(p, 1, stride, 16, thresh, ithresh, hev_thresh);
}
}
//------------------------------------------------------------------------------
// Simple In-loop filtering (Paragraph 15.2)
static void SimpleVFilter16(uint8_t* p, int stride, int thresh) {
int i;
for (i = 0; i < 16; ++i) {
if (needs_filter(p + i, stride, thresh)) {
do_filter2(p + i, stride);
}
}
}
static void SimpleHFilter16(uint8_t* p, int stride, int thresh) {
int i;
for (i = 0; i < 16; ++i) {
if (needs_filter(p + i * stride, 1, thresh)) {
do_filter2(p + i * stride, 1);
}
}
}
static void SimpleVFilter16i(uint8_t* p, int stride, int thresh) {
int k;
for (k = 3; k > 0; --k) {
p += 4 * stride;
SimpleVFilter16(p, stride, thresh);
}
}
static void SimpleHFilter16i(uint8_t* p, int stride, int thresh) {
int k;
for (k = 3; k > 0; --k) {
p += 4;
SimpleHFilter16(p, stride, thresh);
}
}
static void TransformOne(const int16_t* in, uint8_t* dst) {
int temp0, temp1, temp2, temp3, temp4;
int temp5, temp6, temp7, temp8, temp9;
int temp10, temp11, temp12, temp13, temp14;
int temp15, temp16, temp17, temp18;
int16_t* p_in = (int16_t*)in;
// loops unrolled and merged to avoid usage of tmp buffer
// and to reduce number of stalls. MUL macro is written
// in assembler and inlined
__asm__ volatile(
"lh %[temp0], 0(%[in]) \n\t"
"lh %[temp8], 16(%[in]) \n\t"
"lh %[temp4], 8(%[in]) \n\t"
"lh %[temp12], 24(%[in]) \n\t"
"addu %[temp16], %[temp0], %[temp8] \n\t"
"subu %[temp0], %[temp0], %[temp8] \n\t"
"mul %[temp8], %[temp4], %[kC2] \n\t"
"mul %[temp17], %[temp12], %[kC1] \n\t"
"mul %[temp4], %[temp4], %[kC1] \n\t"
"mul %[temp12], %[temp12], %[kC2] \n\t"
"lh %[temp1], 2(%[in]) \n\t"
"lh %[temp5], 10(%[in]) \n\t"
"lh %[temp9], 18(%[in]) \n\t"
"lh %[temp13], 26(%[in]) \n\t"
"sra %[temp8], %[temp8], 16 \n\t"
"sra %[temp17], %[temp17], 16 \n\t"
"sra %[temp4], %[temp4], 16 \n\t"
"sra %[temp12], %[temp12], 16 \n\t"
"lh %[temp2], 4(%[in]) \n\t"
"lh %[temp6], 12(%[in]) \n\t"
"lh %[temp10], 20(%[in]) \n\t"
"lh %[temp14], 28(%[in]) \n\t"
"subu %[temp17], %[temp8], %[temp17] \n\t"
"addu %[temp4], %[temp4], %[temp12] \n\t"
"addu %[temp8], %[temp16], %[temp4] \n\t"
"subu %[temp4], %[temp16], %[temp4] \n\t"
"addu %[temp16], %[temp1], %[temp9] \n\t"
"subu %[temp1], %[temp1], %[temp9] \n\t"
"lh %[temp3], 6(%[in]) \n\t"
"lh %[temp7], 14(%[in]) \n\t"
"lh %[temp11], 22(%[in]) \n\t"
"lh %[temp15], 30(%[in]) \n\t"
"addu %[temp12], %[temp0], %[temp17] \n\t"
"subu %[temp0], %[temp0], %[temp17] \n\t"
"mul %[temp9], %[temp5], %[kC2] \n\t"
"mul %[temp17], %[temp13], %[kC1] \n\t"
"mul %[temp5], %[temp5], %[kC1] \n\t"
"mul %[temp13], %[temp13], %[kC2] \n\t"
"sra %[temp9], %[temp9], 16 \n\t"
"sra %[temp17], %[temp17], 16 \n\t"
"subu %[temp17], %[temp9], %[temp17] \n\t"
"sra %[temp5], %[temp5], 16 \n\t"
"sra %[temp13], %[temp13], 16 \n\t"
"addu %[temp5], %[temp5], %[temp13] \n\t"
"addu %[temp13], %[temp1], %[temp17] \n\t"
"subu %[temp1], %[temp1], %[temp17] \n\t"
"mul %[temp17], %[temp14], %[kC1] \n\t"
"mul %[temp14], %[temp14], %[kC2] \n\t"
"addu %[temp9], %[temp16], %[temp5] \n\t"
"subu %[temp5], %[temp16], %[temp5] \n\t"
"addu %[temp16], %[temp2], %[temp10] \n\t"
"subu %[temp2], %[temp2], %[temp10] \n\t"
"mul %[temp10], %[temp6], %[kC2] \n\t"
"mul %[temp6], %[temp6], %[kC1] \n\t"
"sra %[temp17], %[temp17], 16 \n\t"
"sra %[temp14], %[temp14], 16 \n\t"
"sra %[temp10], %[temp10], 16 \n\t"
"sra %[temp6], %[temp6], 16 \n\t"
"subu %[temp17], %[temp10], %[temp17] \n\t"
"addu %[temp6], %[temp6], %[temp14] \n\t"
"addu %[temp10], %[temp16], %[temp6] \n\t"
"subu %[temp6], %[temp16], %[temp6] \n\t"
"addu %[temp14], %[temp2], %[temp17] \n\t"
"subu %[temp2], %[temp2], %[temp17] \n\t"
"mul %[temp17], %[temp15], %[kC1] \n\t"
"mul %[temp15], %[temp15], %[kC2] \n\t"
"addu %[temp16], %[temp3], %[temp11] \n\t"
"subu %[temp3], %[temp3], %[temp11] \n\t"
"mul %[temp11], %[temp7], %[kC2] \n\t"
"mul %[temp7], %[temp7], %[kC1] \n\t"
"addiu %[temp8], %[temp8], 4 \n\t"
"addiu %[temp12], %[temp12], 4 \n\t"
"addiu %[temp0], %[temp0], 4 \n\t"
"addiu %[temp4], %[temp4], 4 \n\t"
"sra %[temp17], %[temp17], 16 \n\t"
"sra %[temp15], %[temp15], 16 \n\t"
"sra %[temp11], %[temp11], 16 \n\t"
"sra %[temp7], %[temp7], 16 \n\t"
"subu %[temp17], %[temp11], %[temp17] \n\t"
"addu %[temp7], %[temp7], %[temp15] \n\t"
"addu %[temp15], %[temp3], %[temp17] \n\t"
"subu %[temp3], %[temp3], %[temp17] \n\t"
"addu %[temp11], %[temp16], %[temp7] \n\t"
"subu %[temp7], %[temp16], %[temp7] \n\t"
"addu %[temp16], %[temp8], %[temp10] \n\t"
"subu %[temp8], %[temp8], %[temp10] \n\t"
"mul %[temp10], %[temp9], %[kC2] \n\t"
"mul %[temp17], %[temp11], %[kC1] \n\t"
"mul %[temp9], %[temp9], %[kC1] \n\t"
"mul %[temp11], %[temp11], %[kC2] \n\t"
"sra %[temp10], %[temp10], 16 \n\t"
"sra %[temp17], %[temp17], 16 \n\t"
"sra %[temp9], %[temp9], 16 \n\t"
"sra %[temp11], %[temp11], 16 \n\t"
"subu %[temp17], %[temp10], %[temp17] \n\t"
"addu %[temp11], %[temp9], %[temp11] \n\t"
"addu %[temp10], %[temp12], %[temp14] \n\t"
"subu %[temp12], %[temp12], %[temp14] \n\t"
"mul %[temp14], %[temp13], %[kC2] \n\t"
"mul %[temp9], %[temp15], %[kC1] \n\t"
"mul %[temp13], %[temp13], %[kC1] \n\t"
"mul %[temp15], %[temp15], %[kC2] \n\t"
"sra %[temp14], %[temp14], 16 \n\t"
"sra %[temp9], %[temp9], 16 \n\t"
"sra %[temp13], %[temp13], 16 \n\t"
"sra %[temp15], %[temp15], 16 \n\t"
"subu %[temp9], %[temp14], %[temp9] \n\t"
"addu %[temp15], %[temp13], %[temp15] \n\t"
"addu %[temp14], %[temp0], %[temp2] \n\t"
"subu %[temp0], %[temp0], %[temp2] \n\t"
"mul %[temp2], %[temp1], %[kC2] \n\t"
"mul %[temp13], %[temp3], %[kC1] \n\t"
"mul %[temp1], %[temp1], %[kC1] \n\t"
"mul %[temp3], %[temp3], %[kC2] \n\t"
"sra %[temp2], %[temp2], 16 \n\t"
"sra %[temp13], %[temp13], 16 \n\t"
"sra %[temp1], %[temp1], 16 \n\t"
"sra %[temp3], %[temp3], 16 \n\t"
"subu %[temp13], %[temp2], %[temp13] \n\t"
"addu %[temp3], %[temp1], %[temp3] \n\t"
"addu %[temp2], %[temp4], %[temp6] \n\t"
"subu %[temp4], %[temp4], %[temp6] \n\t"
"mul %[temp6], %[temp5], %[kC2] \n\t"
"mul %[temp1], %[temp7], %[kC1] \n\t"
"mul %[temp5], %[temp5], %[kC1] \n\t"
"mul %[temp7], %[temp7], %[kC2] \n\t"
"sra %[temp6], %[temp6], 16 \n\t"
"sra %[temp1], %[temp1], 16 \n\t"
"sra %[temp5], %[temp5], 16 \n\t"
"sra %[temp7], %[temp7], 16 \n\t"
"subu %[temp1], %[temp6], %[temp1] \n\t"
"addu %[temp7], %[temp5], %[temp7] \n\t"
"addu %[temp5], %[temp16], %[temp11] \n\t"
"subu %[temp16], %[temp16], %[temp11] \n\t"
"addu %[temp11], %[temp8], %[temp17] \n\t"
"subu %[temp8], %[temp8], %[temp17] \n\t"
"sra %[temp5], %[temp5], 3 \n\t"
"sra %[temp16], %[temp16], 3 \n\t"
"sra %[temp11], %[temp11], 3 \n\t"
"sra %[temp8], %[temp8], 3 \n\t"
"addu %[temp17], %[temp10], %[temp15] \n\t"
"subu %[temp10], %[temp10], %[temp15] \n\t"
"addu %[temp15], %[temp12], %[temp9] \n\t"
"subu %[temp12], %[temp12], %[temp9] \n\t"
"sra %[temp17], %[temp17], 3 \n\t"
"sra %[temp10], %[temp10], 3 \n\t"
"sra %[temp15], %[temp15], 3 \n\t"
"sra %[temp12], %[temp12], 3 \n\t"
"addu %[temp9], %[temp14], %[temp3] \n\t"
"subu %[temp14], %[temp14], %[temp3] \n\t"
"addu %[temp3], %[temp0], %[temp13] \n\t"
"subu %[temp0], %[temp0], %[temp13] \n\t"
"sra %[temp9], %[temp9], 3 \n\t"
"sra %[temp14], %[temp14], 3 \n\t"
"sra %[temp3], %[temp3], 3 \n\t"
"sra %[temp0], %[temp0], 3 \n\t"
"addu %[temp13], %[temp2], %[temp7] \n\t"
"subu %[temp2], %[temp2], %[temp7] \n\t"
"addu %[temp7], %[temp4], %[temp1] \n\t"
"subu %[temp4], %[temp4], %[temp1] \n\t"
"sra %[temp13], %[temp13], 3 \n\t"
"sra %[temp2], %[temp2], 3 \n\t"
"sra %[temp7], %[temp7], 3 \n\t"
"sra %[temp4], %[temp4], 3 \n\t"
"addiu %[temp6], $zero, 255 \n\t"
"lbu %[temp1], 0(%[dst]) \n\t"
"addu %[temp1], %[temp1], %[temp5] \n\t"
"sra %[temp5], %[temp1], 8 \n\t"
"sra %[temp18], %[temp1], 31 \n\t"
"beqz %[temp5], 1f \n\t"
"xor %[temp1], %[temp1], %[temp1] \n\t"
"movz %[temp1], %[temp6], %[temp18] \n\t"
"1: \n\t"
"lbu %[temp18], 1(%[dst]) \n\t"
"sb %[temp1], 0(%[dst]) \n\t"
"addu %[temp18], %[temp18], %[temp11] \n\t"
"sra %[temp11], %[temp18], 8 \n\t"
"sra %[temp1], %[temp18], 31 \n\t"
"beqz %[temp11], 2f \n\t"
"xor %[temp18], %[temp18], %[temp18] \n\t"
"movz %[temp18], %[temp6], %[temp1] \n\t"
"2: \n\t"
"lbu %[temp1], 2(%[dst]) \n\t"
"sb %[temp18], 1(%[dst]) \n\t"
"addu %[temp1], %[temp1], %[temp8] \n\t"
"sra %[temp8], %[temp1], 8 \n\t"
"sra %[temp18], %[temp1], 31 \n\t"
"beqz %[temp8], 3f \n\t"
"xor %[temp1], %[temp1], %[temp1] \n\t"
"movz %[temp1], %[temp6], %[temp18] \n\t"
"3: \n\t"
"lbu %[temp18], 3(%[dst]) \n\t"
"sb %[temp1], 2(%[dst]) \n\t"
"addu %[temp18], %[temp18], %[temp16] \n\t"
"sra %[temp16], %[temp18], 8 \n\t"
"sra %[temp1], %[temp18], 31 \n\t"
"beqz %[temp16], 4f \n\t"
"xor %[temp18], %[temp18], %[temp18] \n\t"
"movz %[temp18], %[temp6], %[temp1] \n\t"
"4: \n\t"
"sb %[temp18], 3(%[dst]) \n\t"
"lbu %[temp5], 32(%[dst]) \n\t"
"lbu %[temp8], 33(%[dst]) \n\t"
"lbu %[temp11], 34(%[dst]) \n\t"
"lbu %[temp16], 35(%[dst]) \n\t"
"addu %[temp5], %[temp5], %[temp17] \n\t"
"addu %[temp8], %[temp8], %[temp15] \n\t"
"addu %[temp11], %[temp11], %[temp12] \n\t"
"addu %[temp16], %[temp16], %[temp10] \n\t"
"sra %[temp18], %[temp5], 8 \n\t"
"sra %[temp1], %[temp5], 31 \n\t"
"beqz %[temp18], 5f \n\t"
"xor %[temp5], %[temp5], %[temp5] \n\t"
"movz %[temp5], %[temp6], %[temp1] \n\t"
"5: \n\t"
"sra %[temp18], %[temp8], 8 \n\t"
"sra %[temp1], %[temp8], 31 \n\t"
"beqz %[temp18], 6f \n\t"
"xor %[temp8], %[temp8], %[temp8] \n\t"
"movz %[temp8], %[temp6], %[temp1] \n\t"
"6: \n\t"
"sra %[temp18], %[temp11], 8 \n\t"
"sra %[temp1], %[temp11], 31 \n\t"
"sra %[temp17], %[temp16], 8 \n\t"
"sra %[temp15], %[temp16], 31 \n\t"
"beqz %[temp18], 7f \n\t"
"xor %[temp11], %[temp11], %[temp11] \n\t"
"movz %[temp11], %[temp6], %[temp1] \n\t"
"7: \n\t"
"beqz %[temp17], 8f \n\t"
"xor %[temp16], %[temp16], %[temp16] \n\t"
"movz %[temp16], %[temp6], %[temp15] \n\t"
"8: \n\t"
"sb %[temp5], 32(%[dst]) \n\t"
"sb %[temp8], 33(%[dst]) \n\t"
"sb %[temp11], 34(%[dst]) \n\t"
"sb %[temp16], 35(%[dst]) \n\t"
"lbu %[temp5], 64(%[dst]) \n\t"
"lbu %[temp8], 65(%[dst]) \n\t"
"lbu %[temp11], 66(%[dst]) \n\t"
"lbu %[temp16], 67(%[dst]) \n\t"
"addu %[temp5], %[temp5], %[temp9] \n\t"
"addu %[temp8], %[temp8], %[temp3] \n\t"
"addu %[temp11], %[temp11], %[temp0] \n\t"
"addu %[temp16], %[temp16], %[temp14] \n\t"
"sra %[temp18], %[temp5], 8 \n\t"
"sra %[temp1], %[temp5], 31 \n\t"
"sra %[temp17], %[temp8], 8 \n\t"
"sra %[temp15], %[temp8], 31 \n\t"
"sra %[temp12], %[temp11], 8 \n\t"
"sra %[temp10], %[temp11], 31 \n\t"
"sra %[temp9], %[temp16], 8 \n\t"
"sra %[temp3], %[temp16], 31 \n\t"
"beqz %[temp18], 9f \n\t"
"xor %[temp5], %[temp5], %[temp5] \n\t"
"movz %[temp5], %[temp6], %[temp1] \n\t"
"9: \n\t"
"beqz %[temp17], 10f \n\t"
"xor %[temp8], %[temp8], %[temp8] \n\t"
"movz %[temp8], %[temp6], %[temp15] \n\t"
"10: \n\t"
"beqz %[temp12], 11f \n\t"
"xor %[temp11], %[temp11], %[temp11] \n\t"
"movz %[temp11], %[temp6], %[temp10] \n\t"
"11: \n\t"
"beqz %[temp9], 12f \n\t"
"xor %[temp16], %[temp16], %[temp16] \n\t"
"movz %[temp16], %[temp6], %[temp3] \n\t"
"12: \n\t"
"sb %[temp5], 64(%[dst]) \n\t"
"sb %[temp8], 65(%[dst]) \n\t"
"sb %[temp11], 66(%[dst]) \n\t"
"sb %[temp16], 67(%[dst]) \n\t"
"lbu %[temp5], 96(%[dst]) \n\t"
"lbu %[temp8], 97(%[dst]) \n\t"
"lbu %[temp11], 98(%[dst]) \n\t"
"lbu %[temp16], 99(%[dst]) \n\t"
"addu %[temp5], %[temp5], %[temp13] \n\t"
"addu %[temp8], %[temp8], %[temp7] \n\t"
"addu %[temp11], %[temp11], %[temp4] \n\t"
"addu %[temp16], %[temp16], %[temp2] \n\t"
"sra %[temp18], %[temp5], 8 \n\t"
"sra %[temp1], %[temp5], 31 \n\t"
"sra %[temp17], %[temp8], 8 \n\t"
"sra %[temp15], %[temp8], 31 \n\t"
"sra %[temp12], %[temp11], 8 \n\t"
"sra %[temp10], %[temp11], 31 \n\t"
"sra %[temp9], %[temp16], 8 \n\t"
"sra %[temp3], %[temp16], 31 \n\t"
"beqz %[temp18], 13f \n\t"
"xor %[temp5], %[temp5], %[temp5] \n\t"
"movz %[temp5], %[temp6], %[temp1] \n\t"
"13: \n\t"
"beqz %[temp17], 14f \n\t"
"xor %[temp8], %[temp8], %[temp8] \n\t"
"movz %[temp8], %[temp6], %[temp15] \n\t"
"14: \n\t"
"beqz %[temp12], 15f \n\t"
"xor %[temp11], %[temp11], %[temp11] \n\t"
"movz %[temp11], %[temp6], %[temp10] \n\t"
"15: \n\t"
"beqz %[temp9], 16f \n\t"
"xor %[temp16], %[temp16], %[temp16] \n\t"
"movz %[temp16], %[temp6], %[temp3] \n\t"
"16: \n\t"
"sb %[temp5], 96(%[dst]) \n\t"
"sb %[temp8], 97(%[dst]) \n\t"
"sb %[temp11], 98(%[dst]) \n\t"
"sb %[temp16], 99(%[dst]) \n\t"
: [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2),
[temp3]"=&r"(temp3), [temp4]"=&r"(temp4), [temp5]"=&r"(temp5),
[temp6]"=&r"(temp6), [temp7]"=&r"(temp7), [temp8]"=&r"(temp8),
[temp9]"=&r"(temp9), [temp10]"=&r"(temp10), [temp11]"=&r"(temp11),
[temp12]"=&r"(temp12), [temp13]"=&r"(temp13), [temp14]"=&r"(temp14),
[temp15]"=&r"(temp15), [temp16]"=&r"(temp16), [temp17]"=&r"(temp17),
[temp18]"=&r"(temp18)
: [in]"r"(p_in), [kC1]"r"(kC1), [kC2]"r"(kC2), [dst]"r"(dst)
: "memory", "hi", "lo"
);
}
static void TransformTwo(const int16_t* in, uint8_t* dst, int do_two) {
TransformOne(in, dst);
if (do_two) {
TransformOne(in + 16, dst + 4);
}
}
#endif // WEBP_USE_MIPS32
//------------------------------------------------------------------------------
// Entry point
extern void VP8DspInitMIPS32(void);
void VP8DspInitMIPS32(void) {
#if defined(WEBP_USE_MIPS32)
VP8InitClipTables();
VP8Transform = TransformTwo;
VP8VFilter16 = VFilter16;
VP8HFilter16 = HFilter16;
VP8VFilter8 = VFilter8;
VP8HFilter8 = HFilter8;
VP8VFilter16i = VFilter16i;
VP8HFilter16i = HFilter16i;
VP8VFilter8i = VFilter8i;
VP8HFilter8i = HFilter8i;
VP8SimpleVFilter16 = SimpleVFilter16;
VP8SimpleHFilter16 = SimpleHFilter16;
VP8SimpleVFilter16i = SimpleVFilter16i;
VP8SimpleHFilter16i = SimpleHFilter16i;
#endif // WEBP_USE_MIPS32
}

1292
src/dsp/dec_neon.c Normal file

File diff suppressed because it is too large Load Diff

978
src/dsp/dec_sse2.c Normal file
View File

@ -0,0 +1,978 @@
// Copyright 2011 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.
// -----------------------------------------------------------------------------
//
// SSE2 version of some decoding functions (idct, loop filtering).
//
// Author: somnath@google.com (Somnath Banerjee)
// cduvivier@google.com (Christian Duvivier)
#include "./dsp.h"
#if defined(WEBP_USE_SSE2)
// The 3-coeff sparse transform in SSE2 is not really faster than the plain-C
// one it seems => disable it by default. Uncomment the following to enable:
// #define USE_TRANSFORM_AC3
#include <emmintrin.h>
#include "../dec/vp8i.h"
//------------------------------------------------------------------------------
// Transforms (Paragraph 14.4)
static void Transform(const int16_t* in, uint8_t* dst, int do_two) {
// This implementation makes use of 16-bit fixed point versions of two
// multiply constants:
// K1 = sqrt(2) * cos (pi/8) ~= 85627 / 2^16
// K2 = sqrt(2) * sin (pi/8) ~= 35468 / 2^16
//
// To be able to use signed 16-bit integers, we use the following trick to
// have constants within range:
// - Associated constants are obtained by subtracting the 16-bit fixed point
// version of one:
// k = K - (1 << 16) => K = k + (1 << 16)
// K1 = 85267 => k1 = 20091
// K2 = 35468 => k2 = -30068
// - The multiplication of a variable by a constant become the sum of the
// variable and the multiplication of that variable by the associated
// constant:
// (x * K) >> 16 = (x * (k + (1 << 16))) >> 16 = ((x * k ) >> 16) + x
const __m128i k1 = _mm_set1_epi16(20091);
const __m128i k2 = _mm_set1_epi16(-30068);
__m128i T0, T1, T2, T3;
// Load and concatenate the transform coefficients (we'll do two transforms
// in parallel). In the case of only one transform, the second half of the
// vectors will just contain random value we'll never use nor store.
__m128i in0, in1, in2, in3;
{
in0 = _mm_loadl_epi64((__m128i*)&in[0]);
in1 = _mm_loadl_epi64((__m128i*)&in[4]);
in2 = _mm_loadl_epi64((__m128i*)&in[8]);
in3 = _mm_loadl_epi64((__m128i*)&in[12]);
// a00 a10 a20 a30 x x x x
// a01 a11 a21 a31 x x x x
// a02 a12 a22 a32 x x x x
// a03 a13 a23 a33 x x x x
if (do_two) {
const __m128i inB0 = _mm_loadl_epi64((__m128i*)&in[16]);
const __m128i inB1 = _mm_loadl_epi64((__m128i*)&in[20]);
const __m128i inB2 = _mm_loadl_epi64((__m128i*)&in[24]);
const __m128i inB3 = _mm_loadl_epi64((__m128i*)&in[28]);
in0 = _mm_unpacklo_epi64(in0, inB0);
in1 = _mm_unpacklo_epi64(in1, inB1);
in2 = _mm_unpacklo_epi64(in2, inB2);
in3 = _mm_unpacklo_epi64(in3, inB3);
// a00 a10 a20 a30 b00 b10 b20 b30
// a01 a11 a21 a31 b01 b11 b21 b31
// a02 a12 a22 a32 b02 b12 b22 b32
// a03 a13 a23 a33 b03 b13 b23 b33
}
}
// Vertical pass and subsequent transpose.
{
// First pass, c and d calculations are longer because of the "trick"
// multiplications.
const __m128i a = _mm_add_epi16(in0, in2);
const __m128i b = _mm_sub_epi16(in0, in2);
// c = MUL(in1, K2) - MUL(in3, K1) = MUL(in1, k2) - MUL(in3, k1) + in1 - in3
const __m128i c1 = _mm_mulhi_epi16(in1, k2);
const __m128i c2 = _mm_mulhi_epi16(in3, k1);
const __m128i c3 = _mm_sub_epi16(in1, in3);
const __m128i c4 = _mm_sub_epi16(c1, c2);
const __m128i c = _mm_add_epi16(c3, c4);
// d = MUL(in1, K1) + MUL(in3, K2) = MUL(in1, k1) + MUL(in3, k2) + in1 + in3
const __m128i d1 = _mm_mulhi_epi16(in1, k1);
const __m128i d2 = _mm_mulhi_epi16(in3, k2);
const __m128i d3 = _mm_add_epi16(in1, in3);
const __m128i d4 = _mm_add_epi16(d1, d2);
const __m128i d = _mm_add_epi16(d3, d4);
// Second pass.
const __m128i tmp0 = _mm_add_epi16(a, d);
const __m128i tmp1 = _mm_add_epi16(b, c);
const __m128i tmp2 = _mm_sub_epi16(b, c);
const __m128i tmp3 = _mm_sub_epi16(a, d);
// Transpose the two 4x4.
// a00 a01 a02 a03 b00 b01 b02 b03
// a10 a11 a12 a13 b10 b11 b12 b13
// a20 a21 a22 a23 b20 b21 b22 b23
// a30 a31 a32 a33 b30 b31 b32 b33
const __m128i transpose0_0 = _mm_unpacklo_epi16(tmp0, tmp1);
const __m128i transpose0_1 = _mm_unpacklo_epi16(tmp2, tmp3);
const __m128i transpose0_2 = _mm_unpackhi_epi16(tmp0, tmp1);
const __m128i transpose0_3 = _mm_unpackhi_epi16(tmp2, tmp3);
// a00 a10 a01 a11 a02 a12 a03 a13
// a20 a30 a21 a31 a22 a32 a23 a33
// b00 b10 b01 b11 b02 b12 b03 b13
// b20 b30 b21 b31 b22 b32 b23 b33
const __m128i transpose1_0 = _mm_unpacklo_epi32(transpose0_0, transpose0_1);
const __m128i transpose1_1 = _mm_unpacklo_epi32(transpose0_2, transpose0_3);
const __m128i transpose1_2 = _mm_unpackhi_epi32(transpose0_0, transpose0_1);
const __m128i transpose1_3 = _mm_unpackhi_epi32(transpose0_2, transpose0_3);
// a00 a10 a20 a30 a01 a11 a21 a31
// b00 b10 b20 b30 b01 b11 b21 b31
// a02 a12 a22 a32 a03 a13 a23 a33
// b02 b12 a22 b32 b03 b13 b23 b33
T0 = _mm_unpacklo_epi64(transpose1_0, transpose1_1);
T1 = _mm_unpackhi_epi64(transpose1_0, transpose1_1);
T2 = _mm_unpacklo_epi64(transpose1_2, transpose1_3);
T3 = _mm_unpackhi_epi64(transpose1_2, transpose1_3);
// a00 a10 a20 a30 b00 b10 b20 b30
// a01 a11 a21 a31 b01 b11 b21 b31
// a02 a12 a22 a32 b02 b12 b22 b32
// a03 a13 a23 a33 b03 b13 b23 b33
}
// Horizontal pass and subsequent transpose.
{
// First pass, c and d calculations are longer because of the "trick"
// multiplications.
const __m128i four = _mm_set1_epi16(4);
const __m128i dc = _mm_add_epi16(T0, four);
const __m128i a = _mm_add_epi16(dc, T2);
const __m128i b = _mm_sub_epi16(dc, T2);
// c = MUL(T1, K2) - MUL(T3, K1) = MUL(T1, k2) - MUL(T3, k1) + T1 - T3
const __m128i c1 = _mm_mulhi_epi16(T1, k2);
const __m128i c2 = _mm_mulhi_epi16(T3, k1);
const __m128i c3 = _mm_sub_epi16(T1, T3);
const __m128i c4 = _mm_sub_epi16(c1, c2);
const __m128i c = _mm_add_epi16(c3, c4);
// d = MUL(T1, K1) + MUL(T3, K2) = MUL(T1, k1) + MUL(T3, k2) + T1 + T3
const __m128i d1 = _mm_mulhi_epi16(T1, k1);
const __m128i d2 = _mm_mulhi_epi16(T3, k2);
const __m128i d3 = _mm_add_epi16(T1, T3);
const __m128i d4 = _mm_add_epi16(d1, d2);
const __m128i d = _mm_add_epi16(d3, d4);
// Second pass.
const __m128i tmp0 = _mm_add_epi16(a, d);
const __m128i tmp1 = _mm_add_epi16(b, c);
const __m128i tmp2 = _mm_sub_epi16(b, c);
const __m128i tmp3 = _mm_sub_epi16(a, d);
const __m128i shifted0 = _mm_srai_epi16(tmp0, 3);
const __m128i shifted1 = _mm_srai_epi16(tmp1, 3);
const __m128i shifted2 = _mm_srai_epi16(tmp2, 3);
const __m128i shifted3 = _mm_srai_epi16(tmp3, 3);
// Transpose the two 4x4.
// a00 a01 a02 a03 b00 b01 b02 b03
// a10 a11 a12 a13 b10 b11 b12 b13
// a20 a21 a22 a23 b20 b21 b22 b23
// a30 a31 a32 a33 b30 b31 b32 b33
const __m128i transpose0_0 = _mm_unpacklo_epi16(shifted0, shifted1);
const __m128i transpose0_1 = _mm_unpacklo_epi16(shifted2, shifted3);
const __m128i transpose0_2 = _mm_unpackhi_epi16(shifted0, shifted1);
const __m128i transpose0_3 = _mm_unpackhi_epi16(shifted2, shifted3);
// a00 a10 a01 a11 a02 a12 a03 a13
// a20 a30 a21 a31 a22 a32 a23 a33
// b00 b10 b01 b11 b02 b12 b03 b13
// b20 b30 b21 b31 b22 b32 b23 b33
const __m128i transpose1_0 = _mm_unpacklo_epi32(transpose0_0, transpose0_1);
const __m128i transpose1_1 = _mm_unpacklo_epi32(transpose0_2, transpose0_3);
const __m128i transpose1_2 = _mm_unpackhi_epi32(transpose0_0, transpose0_1);
const __m128i transpose1_3 = _mm_unpackhi_epi32(transpose0_2, transpose0_3);
// a00 a10 a20 a30 a01 a11 a21 a31
// b00 b10 b20 b30 b01 b11 b21 b31
// a02 a12 a22 a32 a03 a13 a23 a33
// b02 b12 a22 b32 b03 b13 b23 b33
T0 = _mm_unpacklo_epi64(transpose1_0, transpose1_1);
T1 = _mm_unpackhi_epi64(transpose1_0, transpose1_1);
T2 = _mm_unpacklo_epi64(transpose1_2, transpose1_3);
T3 = _mm_unpackhi_epi64(transpose1_2, transpose1_3);
// a00 a10 a20 a30 b00 b10 b20 b30
// a01 a11 a21 a31 b01 b11 b21 b31
// a02 a12 a22 a32 b02 b12 b22 b32
// a03 a13 a23 a33 b03 b13 b23 b33
}
// Add inverse transform to 'dst' and store.
{
const __m128i zero = _mm_setzero_si128();
// Load the reference(s).
__m128i dst0, dst1, dst2, dst3;
if (do_two) {
// Load eight bytes/pixels per line.
dst0 = _mm_loadl_epi64((__m128i*)(dst + 0 * BPS));
dst1 = _mm_loadl_epi64((__m128i*)(dst + 1 * BPS));
dst2 = _mm_loadl_epi64((__m128i*)(dst + 2 * BPS));
dst3 = _mm_loadl_epi64((__m128i*)(dst + 3 * BPS));
} else {
// Load four bytes/pixels per line.
dst0 = _mm_cvtsi32_si128(*(int*)(dst + 0 * BPS));
dst1 = _mm_cvtsi32_si128(*(int*)(dst + 1 * BPS));
dst2 = _mm_cvtsi32_si128(*(int*)(dst + 2 * BPS));
dst3 = _mm_cvtsi32_si128(*(int*)(dst + 3 * BPS));
}
// Convert to 16b.
dst0 = _mm_unpacklo_epi8(dst0, zero);
dst1 = _mm_unpacklo_epi8(dst1, zero);
dst2 = _mm_unpacklo_epi8(dst2, zero);
dst3 = _mm_unpacklo_epi8(dst3, zero);
// Add the inverse transform(s).
dst0 = _mm_add_epi16(dst0, T0);
dst1 = _mm_add_epi16(dst1, T1);
dst2 = _mm_add_epi16(dst2, T2);
dst3 = _mm_add_epi16(dst3, T3);
// Unsigned saturate to 8b.
dst0 = _mm_packus_epi16(dst0, dst0);
dst1 = _mm_packus_epi16(dst1, dst1);
dst2 = _mm_packus_epi16(dst2, dst2);
dst3 = _mm_packus_epi16(dst3, dst3);
// Store the results.
if (do_two) {
// Store eight bytes/pixels per line.
_mm_storel_epi64((__m128i*)(dst + 0 * BPS), dst0);
_mm_storel_epi64((__m128i*)(dst + 1 * BPS), dst1);
_mm_storel_epi64((__m128i*)(dst + 2 * BPS), dst2);
_mm_storel_epi64((__m128i*)(dst + 3 * BPS), dst3);
} else {
// Store four bytes/pixels per line.
*(int*)(dst + 0 * BPS) = _mm_cvtsi128_si32(dst0);
*(int*)(dst + 1 * BPS) = _mm_cvtsi128_si32(dst1);
*(int*)(dst + 2 * BPS) = _mm_cvtsi128_si32(dst2);
*(int*)(dst + 3 * BPS) = _mm_cvtsi128_si32(dst3);
}
}
}
#if defined(USE_TRANSFORM_AC3)
#define MUL(a, b) (((a) * (b)) >> 16)
static void TransformAC3(const int16_t* in, uint8_t* dst) {
static const int kC1 = 20091 + (1 << 16);
static const int kC2 = 35468;
const __m128i A = _mm_set1_epi16(in[0] + 4);
const __m128i c4 = _mm_set1_epi16(MUL(in[4], kC2));
const __m128i d4 = _mm_set1_epi16(MUL(in[4], kC1));
const int c1 = MUL(in[1], kC2);
const int d1 = MUL(in[1], kC1);
const __m128i CD = _mm_set_epi16(0, 0, 0, 0, -d1, -c1, c1, d1);
const __m128i B = _mm_adds_epi16(A, CD);
const __m128i m0 = _mm_adds_epi16(B, d4);
const __m128i m1 = _mm_adds_epi16(B, c4);
const __m128i m2 = _mm_subs_epi16(B, c4);
const __m128i m3 = _mm_subs_epi16(B, d4);
const __m128i zero = _mm_setzero_si128();
// Load the source pixels.
__m128i dst0 = _mm_cvtsi32_si128(*(int*)(dst + 0 * BPS));
__m128i dst1 = _mm_cvtsi32_si128(*(int*)(dst + 1 * BPS));
__m128i dst2 = _mm_cvtsi32_si128(*(int*)(dst + 2 * BPS));
__m128i dst3 = _mm_cvtsi32_si128(*(int*)(dst + 3 * BPS));
// Convert to 16b.
dst0 = _mm_unpacklo_epi8(dst0, zero);
dst1 = _mm_unpacklo_epi8(dst1, zero);
dst2 = _mm_unpacklo_epi8(dst2, zero);
dst3 = _mm_unpacklo_epi8(dst3, zero);
// Add the inverse transform.
dst0 = _mm_adds_epi16(dst0, _mm_srai_epi16(m0, 3));
dst1 = _mm_adds_epi16(dst1, _mm_srai_epi16(m1, 3));
dst2 = _mm_adds_epi16(dst2, _mm_srai_epi16(m2, 3));
dst3 = _mm_adds_epi16(dst3, _mm_srai_epi16(m3, 3));
// Unsigned saturate to 8b.
dst0 = _mm_packus_epi16(dst0, dst0);
dst1 = _mm_packus_epi16(dst1, dst1);
dst2 = _mm_packus_epi16(dst2, dst2);
dst3 = _mm_packus_epi16(dst3, dst3);
// Store the results.
*(int*)(dst + 0 * BPS) = _mm_cvtsi128_si32(dst0);
*(int*)(dst + 1 * BPS) = _mm_cvtsi128_si32(dst1);
*(int*)(dst + 2 * BPS) = _mm_cvtsi128_si32(dst2);
*(int*)(dst + 3 * BPS) = _mm_cvtsi128_si32(dst3);
}
#undef MUL
#endif // USE_TRANSFORM_AC3
//------------------------------------------------------------------------------
// Loop Filter (Paragraph 15)
// Compute abs(p - q) = subs(p - q) OR subs(q - p)
#define MM_ABS(p, q) _mm_or_si128( \
_mm_subs_epu8((q), (p)), \
_mm_subs_epu8((p), (q)))
// Shift each byte of "x" by 3 bits while preserving by the sign bit.
static WEBP_INLINE void SignedShift8b(__m128i* const x) {
const __m128i zero = _mm_setzero_si128();
const __m128i signs = _mm_cmpgt_epi8(zero, *x);
const __m128i lo_0 = _mm_unpacklo_epi8(*x, signs); // s8 -> s16 sign extend
const __m128i hi_0 = _mm_unpackhi_epi8(*x, signs);
const __m128i lo_1 = _mm_srai_epi16(lo_0, 3);
const __m128i hi_1 = _mm_srai_epi16(hi_0, 3);
*x = _mm_packs_epi16(lo_1, hi_1);
}
#define FLIP_SIGN_BIT2(a, b) { \
a = _mm_xor_si128(a, sign_bit); \
b = _mm_xor_si128(b, sign_bit); \
}
#define FLIP_SIGN_BIT4(a, b, c, d) { \
FLIP_SIGN_BIT2(a, b); \
FLIP_SIGN_BIT2(c, d); \
}
// input/output is uint8_t
static WEBP_INLINE void GetNotHEV(const __m128i* const p1,
const __m128i* const p0,
const __m128i* const q0,
const __m128i* const q1,
int hev_thresh, __m128i* const not_hev) {
const __m128i zero = _mm_setzero_si128();
const __m128i t_1 = MM_ABS(*p1, *p0);
const __m128i t_2 = MM_ABS(*q1, *q0);
const __m128i h = _mm_set1_epi8(hev_thresh);
const __m128i t_3 = _mm_subs_epu8(t_1, h); // abs(p1 - p0) - hev_tresh
const __m128i t_4 = _mm_subs_epu8(t_2, h); // abs(q1 - q0) - hev_tresh
*not_hev = _mm_or_si128(t_3, t_4);
*not_hev = _mm_cmpeq_epi8(*not_hev, zero); // not_hev <= t1 && not_hev <= t2
}
// input pixels are int8_t
static WEBP_INLINE void GetBaseDelta(const __m128i* const p1,
const __m128i* const p0,
const __m128i* const q0,
const __m128i* const q1,
__m128i* const delta) {
// beware of addition order, for saturation!
const __m128i p1_q1 = _mm_subs_epi8(*p1, *q1); // p1 - q1
const __m128i q0_p0 = _mm_subs_epi8(*q0, *p0); // q0 - p0
const __m128i s1 = _mm_adds_epi8(p1_q1, q0_p0); // p1 - q1 + 1 * (q0 - p0)
const __m128i s2 = _mm_adds_epi8(q0_p0, s1); // p1 - q1 + 2 * (q0 - p0)
const __m128i s3 = _mm_adds_epi8(q0_p0, s2); // p1 - q1 + 3 * (q0 - p0)
*delta = s3;
}
// input and output are int8_t
static WEBP_INLINE void DoSimpleFilter(__m128i* const p0, __m128i* const q0,
const __m128i* const fl) {
const __m128i k3 = _mm_set1_epi8(3);
const __m128i k4 = _mm_set1_epi8(4);
__m128i v3 = _mm_adds_epi8(*fl, k3);
__m128i v4 = _mm_adds_epi8(*fl, k4);
SignedShift8b(&v4); // v4 >> 3
SignedShift8b(&v3); // v3 >> 3
*q0 = _mm_subs_epi8(*q0, v4); // q0 -= v4
*p0 = _mm_adds_epi8(*p0, v3); // p0 += v3
}
// Updates values of 2 pixels at MB edge during complex filtering.
// Update operations:
// q = q - delta and p = p + delta; where delta = [(a_hi >> 7), (a_lo >> 7)]
// Pixels 'pi' and 'qi' are int8_t on input, uint8_t on output (sign flip).
static WEBP_INLINE void Update2Pixels(__m128i* const pi, __m128i* const qi,
const __m128i* const a0_lo,
const __m128i* const a0_hi) {
const __m128i a1_lo = _mm_srai_epi16(*a0_lo, 7);
const __m128i a1_hi = _mm_srai_epi16(*a0_hi, 7);
const __m128i delta = _mm_packs_epi16(a1_lo, a1_hi);
const __m128i sign_bit = _mm_set1_epi8(0x80);
*pi = _mm_adds_epi8(*pi, delta);
*qi = _mm_subs_epi8(*qi, delta);
FLIP_SIGN_BIT2(*pi, *qi);
}
// input pixels are uint8_t
static WEBP_INLINE void NeedsFilter(const __m128i* const p1,
const __m128i* const p0,
const __m128i* const q0,
const __m128i* const q1,
int thresh, __m128i* const mask) {
const __m128i m_thresh = _mm_set1_epi8(thresh);
const __m128i t1 = MM_ABS(*p1, *q1); // abs(p1 - q1)
const __m128i kFE = _mm_set1_epi8(0xFE);
const __m128i t2 = _mm_and_si128(t1, kFE); // set lsb of each byte to zero
const __m128i t3 = _mm_srli_epi16(t2, 1); // abs(p1 - q1) / 2
const __m128i t4 = MM_ABS(*p0, *q0); // abs(p0 - q0)
const __m128i t5 = _mm_adds_epu8(t4, t4); // abs(p0 - q0) * 2
const __m128i t6 = _mm_adds_epu8(t5, t3); // abs(p0-q0)*2 + abs(p1-q1)/2
const __m128i t7 = _mm_subs_epu8(t6, m_thresh); // mask <= m_thresh
*mask = _mm_cmpeq_epi8(t7, _mm_setzero_si128());
}
//------------------------------------------------------------------------------
// Edge filtering functions
// Applies filter on 2 pixels (p0 and q0)
static WEBP_INLINE void DoFilter2(__m128i* const p1, __m128i* const p0,
__m128i* const q0, __m128i* const q1,
int thresh) {
__m128i a, mask;
const __m128i sign_bit = _mm_set1_epi8(0x80);
// convert p1/q1 to int8_t (for GetBaseDelta)
const __m128i p1s = _mm_xor_si128(*p1, sign_bit);
const __m128i q1s = _mm_xor_si128(*q1, sign_bit);
NeedsFilter(p1, p0, q0, q1, thresh, &mask);
FLIP_SIGN_BIT2(*p0, *q0);
GetBaseDelta(&p1s, p0, q0, &q1s, &a);
a = _mm_and_si128(a, mask); // mask filter values we don't care about
DoSimpleFilter(p0, q0, &a);
FLIP_SIGN_BIT2(*p0, *q0);
}
// Applies filter on 4 pixels (p1, p0, q0 and q1)
static WEBP_INLINE void DoFilter4(__m128i* const p1, __m128i* const p0,
__m128i* const q0, __m128i* const q1,
const __m128i* const mask, int hev_thresh) {
const __m128i sign_bit = _mm_set1_epi8(0x80);
const __m128i k64 = _mm_set1_epi8(0x40);
const __m128i zero = _mm_setzero_si128();
__m128i not_hev;
__m128i t1, t2, t3;
// compute hev mask
GetNotHEV(p1, p0, q0, q1, hev_thresh, &not_hev);
// convert to signed values
FLIP_SIGN_BIT4(*p1, *p0, *q0, *q1);
t1 = _mm_subs_epi8(*p1, *q1); // p1 - q1
t1 = _mm_andnot_si128(not_hev, t1); // hev(p1 - q1)
t2 = _mm_subs_epi8(*q0, *p0); // q0 - p0
t1 = _mm_adds_epi8(t1, t2); // hev(p1 - q1) + 1 * (q0 - p0)
t1 = _mm_adds_epi8(t1, t2); // hev(p1 - q1) + 2 * (q0 - p0)
t1 = _mm_adds_epi8(t1, t2); // hev(p1 - q1) + 3 * (q0 - p0)
t1 = _mm_and_si128(t1, *mask); // mask filter values we don't care about
t2 = _mm_set1_epi8(3);
t3 = _mm_set1_epi8(4);
t2 = _mm_adds_epi8(t1, t2); // 3 * (q0 - p0) + (p1 - q1) + 3
t3 = _mm_adds_epi8(t1, t3); // 3 * (q0 - p0) + (p1 - q1) + 4
SignedShift8b(&t2); // (3 * (q0 - p0) + hev(p1 - q1) + 3) >> 3
SignedShift8b(&t3); // (3 * (q0 - p0) + hev(p1 - q1) + 4) >> 3
*p0 = _mm_adds_epi8(*p0, t2); // p0 += t2
*q0 = _mm_subs_epi8(*q0, t3); // q0 -= t3
FLIP_SIGN_BIT2(*p0, *q0);
// this is equivalent to signed (a + 1) >> 1 calculation
t2 = _mm_add_epi8(t3, sign_bit);
t3 = _mm_avg_epu8(t2, zero);
t3 = _mm_sub_epi8(t3, k64);
t3 = _mm_and_si128(not_hev, t3); // if !hev
*q1 = _mm_subs_epi8(*q1, t3); // q1 -= t3
*p1 = _mm_adds_epi8(*p1, t3); // p1 += t3
FLIP_SIGN_BIT2(*p1, *q1);
}
// Applies filter on 6 pixels (p2, p1, p0, q0, q1 and q2)
static WEBP_INLINE void DoFilter6(__m128i* const p2, __m128i* const p1,
__m128i* const p0, __m128i* const q0,
__m128i* const q1, __m128i* const q2,
const __m128i* const mask, int hev_thresh) {
const __m128i zero = _mm_setzero_si128();
const __m128i sign_bit = _mm_set1_epi8(0x80);
__m128i a, not_hev;
// compute hev mask
GetNotHEV(p1, p0, q0, q1, hev_thresh, &not_hev);
FLIP_SIGN_BIT4(*p1, *p0, *q0, *q1);
FLIP_SIGN_BIT2(*p2, *q2);
GetBaseDelta(p1, p0, q0, q1, &a);
{ // do simple filter on pixels with hev
const __m128i m = _mm_andnot_si128(not_hev, *mask);
const __m128i f = _mm_and_si128(a, m);
DoSimpleFilter(p0, q0, &f);
}
{ // do strong filter on pixels with not hev
const __m128i k9 = _mm_set1_epi16(0x0900);
const __m128i k63 = _mm_set1_epi16(63);
const __m128i m = _mm_and_si128(not_hev, *mask);
const __m128i f = _mm_and_si128(a, m);
const __m128i f_lo = _mm_unpacklo_epi8(zero, f);
const __m128i f_hi = _mm_unpackhi_epi8(zero, f);
const __m128i f9_lo = _mm_mulhi_epi16(f_lo, k9); // Filter (lo) * 9
const __m128i f9_hi = _mm_mulhi_epi16(f_hi, k9); // Filter (hi) * 9
const __m128i a2_lo = _mm_add_epi16(f9_lo, k63); // Filter * 9 + 63
const __m128i a2_hi = _mm_add_epi16(f9_hi, k63); // Filter * 9 + 63
const __m128i a1_lo = _mm_add_epi16(a2_lo, f9_lo); // Filter * 18 + 63
const __m128i a1_hi = _mm_add_epi16(a2_hi, f9_hi); // Filter * 18 + 63
const __m128i a0_lo = _mm_add_epi16(a1_lo, f9_lo); // Filter * 27 + 63
const __m128i a0_hi = _mm_add_epi16(a1_hi, f9_hi); // Filter * 27 + 63
Update2Pixels(p2, q2, &a2_lo, &a2_hi);
Update2Pixels(p1, q1, &a1_lo, &a1_hi);
Update2Pixels(p0, q0, &a0_lo, &a0_hi);
}
}
// reads 8 rows across a vertical edge.
//
// TODO(somnath): Investigate _mm_shuffle* also see if it can be broken into
// two Load4x4() to avoid code duplication.
static WEBP_INLINE void Load8x4(const uint8_t* const b, int stride,
__m128i* const p, __m128i* const q) {
__m128i t1, t2;
// Load 0th, 1st, 4th and 5th rows
__m128i r0 = _mm_cvtsi32_si128(*((int*)&b[0 * stride])); // 03 02 01 00
__m128i r1 = _mm_cvtsi32_si128(*((int*)&b[1 * stride])); // 13 12 11 10
__m128i r4 = _mm_cvtsi32_si128(*((int*)&b[4 * stride])); // 43 42 41 40
__m128i r5 = _mm_cvtsi32_si128(*((int*)&b[5 * stride])); // 53 52 51 50
r0 = _mm_unpacklo_epi32(r0, r4); // 43 42 41 40 03 02 01 00
r1 = _mm_unpacklo_epi32(r1, r5); // 53 52 51 50 13 12 11 10
// t1 = 53 43 52 42 51 41 50 40 13 03 12 02 11 01 10 00
t1 = _mm_unpacklo_epi8(r0, r1);
// Load 2nd, 3rd, 6th and 7th rows
r0 = _mm_cvtsi32_si128(*((int*)&b[2 * stride])); // 23 22 21 22
r1 = _mm_cvtsi32_si128(*((int*)&b[3 * stride])); // 33 32 31 30
r4 = _mm_cvtsi32_si128(*((int*)&b[6 * stride])); // 63 62 61 60
r5 = _mm_cvtsi32_si128(*((int*)&b[7 * stride])); // 73 72 71 70
r0 = _mm_unpacklo_epi32(r0, r4); // 63 62 61 60 23 22 21 20
r1 = _mm_unpacklo_epi32(r1, r5); // 73 72 71 70 33 32 31 30
// t2 = 73 63 72 62 71 61 70 60 33 23 32 22 31 21 30 20
t2 = _mm_unpacklo_epi8(r0, r1);
// t1 = 33 23 13 03 32 22 12 02 31 21 11 01 30 20 10 00
// t2 = 73 63 53 43 72 62 52 42 71 61 51 41 70 60 50 40
r0 = t1;
t1 = _mm_unpacklo_epi16(t1, t2);
t2 = _mm_unpackhi_epi16(r0, t2);
// *p = 71 61 51 41 31 21 11 01 70 60 50 40 30 20 10 00
// *q = 73 63 53 43 33 23 13 03 72 62 52 42 32 22 12 02
*p = _mm_unpacklo_epi32(t1, t2);
*q = _mm_unpackhi_epi32(t1, t2);
}
static WEBP_INLINE void Load16x4(const uint8_t* const r0,
const uint8_t* const r8,
int stride,
__m128i* const p1, __m128i* const p0,
__m128i* const q0, __m128i* const q1) {
__m128i t1, t2;
// Assume the pixels around the edge (|) are numbered as follows
// 00 01 | 02 03
// 10 11 | 12 13
// ... | ...
// e0 e1 | e2 e3
// f0 f1 | f2 f3
//
// r0 is pointing to the 0th row (00)
// r8 is pointing to the 8th row (80)
// Load
// p1 = 71 61 51 41 31 21 11 01 70 60 50 40 30 20 10 00
// q0 = 73 63 53 43 33 23 13 03 72 62 52 42 32 22 12 02
// p0 = f1 e1 d1 c1 b1 a1 91 81 f0 e0 d0 c0 b0 a0 90 80
// q1 = f3 e3 d3 c3 b3 a3 93 83 f2 e2 d2 c2 b2 a2 92 82
Load8x4(r0, stride, p1, q0);
Load8x4(r8, stride, p0, q1);
t1 = *p1;
t2 = *q0;
// p1 = f0 e0 d0 c0 b0 a0 90 80 70 60 50 40 30 20 10 00
// p0 = f1 e1 d1 c1 b1 a1 91 81 71 61 51 41 31 21 11 01
// q0 = f2 e2 d2 c2 b2 a2 92 82 72 62 52 42 32 22 12 02
// q1 = f3 e3 d3 c3 b3 a3 93 83 73 63 53 43 33 23 13 03
*p1 = _mm_unpacklo_epi64(t1, *p0);
*p0 = _mm_unpackhi_epi64(t1, *p0);
*q0 = _mm_unpacklo_epi64(t2, *q1);
*q1 = _mm_unpackhi_epi64(t2, *q1);
}
static WEBP_INLINE void Store4x4(__m128i* const x, uint8_t* dst, int stride) {
int i;
for (i = 0; i < 4; ++i, dst += stride) {
*((int32_t*)dst) = _mm_cvtsi128_si32(*x);
*x = _mm_srli_si128(*x, 4);
}
}
// Transpose back and store
static WEBP_INLINE void Store16x4(const __m128i* const p1,
const __m128i* const p0,
const __m128i* const q0,
const __m128i* const q1,
uint8_t* r0, uint8_t* r8,
int stride) {
__m128i t1, p1_s, p0_s, q0_s, q1_s;
// p0 = 71 70 61 60 51 50 41 40 31 30 21 20 11 10 01 00
// p1 = f1 f0 e1 e0 d1 d0 c1 c0 b1 b0 a1 a0 91 90 81 80
t1 = *p0;
p0_s = _mm_unpacklo_epi8(*p1, t1);
p1_s = _mm_unpackhi_epi8(*p1, t1);
// q0 = 73 72 63 62 53 52 43 42 33 32 23 22 13 12 03 02
// q1 = f3 f2 e3 e2 d3 d2 c3 c2 b3 b2 a3 a2 93 92 83 82
t1 = *q0;
q0_s = _mm_unpacklo_epi8(t1, *q1);
q1_s = _mm_unpackhi_epi8(t1, *q1);
// p0 = 33 32 31 30 23 22 21 20 13 12 11 10 03 02 01 00
// q0 = 73 72 71 70 63 62 61 60 53 52 51 50 43 42 41 40
t1 = p0_s;
p0_s = _mm_unpacklo_epi16(t1, q0_s);
q0_s = _mm_unpackhi_epi16(t1, q0_s);
// p1 = b3 b2 b1 b0 a3 a2 a1 a0 93 92 91 90 83 82 81 80
// q1 = f3 f2 f1 f0 e3 e2 e1 e0 d3 d2 d1 d0 c3 c2 c1 c0
t1 = p1_s;
p1_s = _mm_unpacklo_epi16(t1, q1_s);
q1_s = _mm_unpackhi_epi16(t1, q1_s);
Store4x4(&p0_s, r0, stride);
r0 += 4 * stride;
Store4x4(&q0_s, r0, stride);
Store4x4(&p1_s, r8, stride);
r8 += 4 * stride;
Store4x4(&q1_s, r8, stride);
}
//------------------------------------------------------------------------------
// Simple In-loop filtering (Paragraph 15.2)
static void SimpleVFilter16(uint8_t* p, int stride, int thresh) {
// Load
__m128i p1 = _mm_loadu_si128((__m128i*)&p[-2 * stride]);
__m128i p0 = _mm_loadu_si128((__m128i*)&p[-stride]);
__m128i q0 = _mm_loadu_si128((__m128i*)&p[0]);
__m128i q1 = _mm_loadu_si128((__m128i*)&p[stride]);
DoFilter2(&p1, &p0, &q0, &q1, thresh);
// Store
_mm_storeu_si128((__m128i*)&p[-stride], p0);
_mm_storeu_si128((__m128i*)&p[0], q0);
}
static void SimpleHFilter16(uint8_t* p, int stride, int thresh) {
__m128i p1, p0, q0, q1;
p -= 2; // beginning of p1
Load16x4(p, p + 8 * stride, stride, &p1, &p0, &q0, &q1);
DoFilter2(&p1, &p0, &q0, &q1, thresh);
Store16x4(&p1, &p0, &q0, &q1, p, p + 8 * stride, stride);
}
static void SimpleVFilter16i(uint8_t* p, int stride, int thresh) {
int k;
for (k = 3; k > 0; --k) {
p += 4 * stride;
SimpleVFilter16(p, stride, thresh);
}
}
static void SimpleHFilter16i(uint8_t* p, int stride, int thresh) {
int k;
for (k = 3; k > 0; --k) {
p += 4;
SimpleHFilter16(p, stride, thresh);
}
}
//------------------------------------------------------------------------------
// Complex In-loop filtering (Paragraph 15.3)
#define MAX_DIFF1(p3, p2, p1, p0, m) do { \
m = MM_ABS(p1, p0); \
m = _mm_max_epu8(m, MM_ABS(p3, p2)); \
m = _mm_max_epu8(m, MM_ABS(p2, p1)); \
} while (0)
#define MAX_DIFF2(p3, p2, p1, p0, m) do { \
m = _mm_max_epu8(m, MM_ABS(p1, p0)); \
m = _mm_max_epu8(m, MM_ABS(p3, p2)); \
m = _mm_max_epu8(m, MM_ABS(p2, p1)); \
} while (0)
#define LOAD_H_EDGES4(p, stride, e1, e2, e3, e4) { \
e1 = _mm_loadu_si128((__m128i*)&(p)[0 * stride]); \
e2 = _mm_loadu_si128((__m128i*)&(p)[1 * stride]); \
e3 = _mm_loadu_si128((__m128i*)&(p)[2 * stride]); \
e4 = _mm_loadu_si128((__m128i*)&(p)[3 * stride]); \
}
#define LOADUV_H_EDGE(p, u, v, stride) do { \
const __m128i U = _mm_loadl_epi64((__m128i*)&(u)[(stride)]); \
const __m128i V = _mm_loadl_epi64((__m128i*)&(v)[(stride)]); \
p = _mm_unpacklo_epi64(U, V); \
} while (0)
#define LOADUV_H_EDGES4(u, v, stride, e1, e2, e3, e4) { \
LOADUV_H_EDGE(e1, u, v, 0 * stride); \
LOADUV_H_EDGE(e2, u, v, 1 * stride); \
LOADUV_H_EDGE(e3, u, v, 2 * stride); \
LOADUV_H_EDGE(e4, u, v, 3 * stride); \
}
#define STOREUV(p, u, v, stride) { \
_mm_storel_epi64((__m128i*)&u[(stride)], p); \
p = _mm_srli_si128(p, 8); \
_mm_storel_epi64((__m128i*)&v[(stride)], p); \
}
static WEBP_INLINE void ComplexMask(const __m128i* const p1,
const __m128i* const p0,
const __m128i* const q0,
const __m128i* const q1,
int thresh, int ithresh,
__m128i* const mask) {
const __m128i it = _mm_set1_epi8(ithresh);
const __m128i diff = _mm_subs_epu8(*mask, it);
const __m128i thresh_mask = _mm_cmpeq_epi8(diff, _mm_setzero_si128());
__m128i filter_mask;
NeedsFilter(p1, p0, q0, q1, thresh, &filter_mask);
*mask = _mm_and_si128(thresh_mask, filter_mask);
}
// on macroblock edges
static void VFilter16(uint8_t* p, int stride,
int thresh, int ithresh, int hev_thresh) {
__m128i t1;
__m128i mask;
__m128i p2, p1, p0, q0, q1, q2;
// Load p3, p2, p1, p0
LOAD_H_EDGES4(p - 4 * stride, stride, t1, p2, p1, p0);
MAX_DIFF1(t1, p2, p1, p0, mask);
// Load q0, q1, q2, q3
LOAD_H_EDGES4(p, stride, q0, q1, q2, t1);
MAX_DIFF2(t1, q2, q1, q0, mask);
ComplexMask(&p1, &p0, &q0, &q1, thresh, ithresh, &mask);
DoFilter6(&p2, &p1, &p0, &q0, &q1, &q2, &mask, hev_thresh);
// Store
_mm_storeu_si128((__m128i*)&p[-3 * stride], p2);
_mm_storeu_si128((__m128i*)&p[-2 * stride], p1);
_mm_storeu_si128((__m128i*)&p[-1 * stride], p0);
_mm_storeu_si128((__m128i*)&p[+0 * stride], q0);
_mm_storeu_si128((__m128i*)&p[+1 * stride], q1);
_mm_storeu_si128((__m128i*)&p[+2 * stride], q2);
}
static void HFilter16(uint8_t* p, int stride,
int thresh, int ithresh, int hev_thresh) {
__m128i mask;
__m128i p3, p2, p1, p0, q0, q1, q2, q3;
uint8_t* const b = p - 4;
Load16x4(b, b + 8 * stride, stride, &p3, &p2, &p1, &p0); // p3, p2, p1, p0
MAX_DIFF1(p3, p2, p1, p0, mask);
Load16x4(p, p + 8 * stride, stride, &q0, &q1, &q2, &q3); // q0, q1, q2, q3
MAX_DIFF2(q3, q2, q1, q0, mask);
ComplexMask(&p1, &p0, &q0, &q1, thresh, ithresh, &mask);
DoFilter6(&p2, &p1, &p0, &q0, &q1, &q2, &mask, hev_thresh);
Store16x4(&p3, &p2, &p1, &p0, b, b + 8 * stride, stride);
Store16x4(&q0, &q1, &q2, &q3, p, p + 8 * stride, stride);
}
// on three inner edges
static void VFilter16i(uint8_t* p, int stride,
int thresh, int ithresh, int hev_thresh) {
int k;
__m128i p3, p2, p1, p0; // loop invariants
LOAD_H_EDGES4(p, stride, p3, p2, p1, p0); // prologue
for (k = 3; k > 0; --k) {
__m128i mask, tmp1, tmp2;
uint8_t* const b = p + 2 * stride; // beginning of p1
p += 4 * stride;
MAX_DIFF1(p3, p2, p1, p0, mask); // compute partial mask
LOAD_H_EDGES4(p, stride, p3, p2, tmp1, tmp2);
MAX_DIFF2(p3, p2, tmp1, tmp2, mask);
// p3 and p2 are not just temporary variables here: they will be
// re-used for next span. And q2/q3 will become p1/p0 accordingly.
ComplexMask(&p1, &p0, &p3, &p2, thresh, ithresh, &mask);
DoFilter4(&p1, &p0, &p3, &p2, &mask, hev_thresh);
// Store
_mm_storeu_si128((__m128i*)&b[0 * stride], p1);
_mm_storeu_si128((__m128i*)&b[1 * stride], p0);
_mm_storeu_si128((__m128i*)&b[2 * stride], p3);
_mm_storeu_si128((__m128i*)&b[3 * stride], p2);
// rotate samples
p1 = tmp1;
p0 = tmp2;
}
}
static void HFilter16i(uint8_t* p, int stride,
int thresh, int ithresh, int hev_thresh) {
int k;
__m128i p3, p2, p1, p0; // loop invariants
Load16x4(p, p + 8 * stride, stride, &p3, &p2, &p1, &p0); // prologue
for (k = 3; k > 0; --k) {
__m128i mask, tmp1, tmp2;
uint8_t* const b = p + 2; // beginning of p1
p += 4; // beginning of q0 (and next span)
MAX_DIFF1(p3, p2, p1, p0, mask); // compute partial mask
Load16x4(p, p + 8 * stride, stride, &p3, &p2, &tmp1, &tmp2);
MAX_DIFF2(p3, p2, tmp1, tmp2, mask);
ComplexMask(&p1, &p0, &p3, &p2, thresh, ithresh, &mask);
DoFilter4(&p1, &p0, &p3, &p2, &mask, hev_thresh);
Store16x4(&p1, &p0, &p3, &p2, b, b + 8 * stride, stride);
// rotate samples
p1 = tmp1;
p0 = tmp2;
}
}
// 8-pixels wide variant, for chroma filtering
static void VFilter8(uint8_t* u, uint8_t* v, int stride,
int thresh, int ithresh, int hev_thresh) {
__m128i mask;
__m128i t1, p2, p1, p0, q0, q1, q2;
// Load p3, p2, p1, p0
LOADUV_H_EDGES4(u - 4 * stride, v - 4 * stride, stride, t1, p2, p1, p0);
MAX_DIFF1(t1, p2, p1, p0, mask);
// Load q0, q1, q2, q3
LOADUV_H_EDGES4(u, v, stride, q0, q1, q2, t1);
MAX_DIFF2(t1, q2, q1, q0, mask);
ComplexMask(&p1, &p0, &q0, &q1, thresh, ithresh, &mask);
DoFilter6(&p2, &p1, &p0, &q0, &q1, &q2, &mask, hev_thresh);
// Store
STOREUV(p2, u, v, -3 * stride);
STOREUV(p1, u, v, -2 * stride);
STOREUV(p0, u, v, -1 * stride);
STOREUV(q0, u, v, 0 * stride);
STOREUV(q1, u, v, 1 * stride);
STOREUV(q2, u, v, 2 * stride);
}
static void HFilter8(uint8_t* u, uint8_t* v, int stride,
int thresh, int ithresh, int hev_thresh) {
__m128i mask;
__m128i p3, p2, p1, p0, q0, q1, q2, q3;
uint8_t* const tu = u - 4;
uint8_t* const tv = v - 4;
Load16x4(tu, tv, stride, &p3, &p2, &p1, &p0); // p3, p2, p1, p0
MAX_DIFF1(p3, p2, p1, p0, mask);
Load16x4(u, v, stride, &q0, &q1, &q2, &q3); // q0, q1, q2, q3
MAX_DIFF2(q3, q2, q1, q0, mask);
ComplexMask(&p1, &p0, &q0, &q1, thresh, ithresh, &mask);
DoFilter6(&p2, &p1, &p0, &q0, &q1, &q2, &mask, hev_thresh);
Store16x4(&p3, &p2, &p1, &p0, tu, tv, stride);
Store16x4(&q0, &q1, &q2, &q3, u, v, stride);
}
static void VFilter8i(uint8_t* u, uint8_t* v, int stride,
int thresh, int ithresh, int hev_thresh) {
__m128i mask;
__m128i t1, t2, p1, p0, q0, q1;
// Load p3, p2, p1, p0
LOADUV_H_EDGES4(u, v, stride, t2, t1, p1, p0);
MAX_DIFF1(t2, t1, p1, p0, mask);
u += 4 * stride;
v += 4 * stride;
// Load q0, q1, q2, q3
LOADUV_H_EDGES4(u, v, stride, q0, q1, t1, t2);
MAX_DIFF2(t2, t1, q1, q0, mask);
ComplexMask(&p1, &p0, &q0, &q1, thresh, ithresh, &mask);
DoFilter4(&p1, &p0, &q0, &q1, &mask, hev_thresh);
// Store
STOREUV(p1, u, v, -2 * stride);
STOREUV(p0, u, v, -1 * stride);
STOREUV(q0, u, v, 0 * stride);
STOREUV(q1, u, v, 1 * stride);
}
static void HFilter8i(uint8_t* u, uint8_t* v, int stride,
int thresh, int ithresh, int hev_thresh) {
__m128i mask;
__m128i t1, t2, p1, p0, q0, q1;
Load16x4(u, v, stride, &t2, &t1, &p1, &p0); // p3, p2, p1, p0
MAX_DIFF1(t2, t1, p1, p0, mask);
u += 4; // beginning of q0
v += 4;
Load16x4(u, v, stride, &q0, &q1, &t1, &t2); // q0, q1, q2, q3
MAX_DIFF2(t2, t1, q1, q0, mask);
ComplexMask(&p1, &p0, &q0, &q1, thresh, ithresh, &mask);
DoFilter4(&p1, &p0, &q0, &q1, &mask, hev_thresh);
u -= 2; // beginning of p1
v -= 2;
Store16x4(&p1, &p0, &q0, &q1, u, v, stride);
}
#endif // WEBP_USE_SSE2
//------------------------------------------------------------------------------
// Entry point
extern void VP8DspInitSSE2(void);
void VP8DspInitSSE2(void) {
#if defined(WEBP_USE_SSE2)
VP8Transform = Transform;
#if defined(USE_TRANSFORM_AC3)
VP8TransformAC3 = TransformAC3;
#endif
VP8VFilter16 = VFilter16;
VP8HFilter16 = HFilter16;
VP8VFilter8 = VFilter8;
VP8HFilter8 = HFilter8;
VP8VFilter16i = VFilter16i;
VP8HFilter16i = HFilter16i;
VP8VFilter8i = VFilter8i;
VP8HFilter8i = HFilter8i;
VP8SimpleVFilter16 = SimpleVFilter16;
VP8SimpleHFilter16 = SimpleHFilter16;
VP8SimpleVFilter16i = SimpleVFilter16i;
VP8SimpleHFilter16i = SimpleHFilter16i;
#endif // WEBP_USE_SSE2
}

293
src/dsp/dsp.h Normal file
View File

@ -0,0 +1,293 @@
// Copyright 2011 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.
// -----------------------------------------------------------------------------
//
// Speed-critical functions.
//
// Author: Skal (pascal.massimino@gmail.com)
#ifndef WEBP_DSP_DSP_H_
#define WEBP_DSP_DSP_H_
#ifdef HAVE_CONFIG_H
#include "../webp/config.h"
#endif
#include "../webp/types.h"
#ifdef __cplusplus
extern "C" {
#endif
//------------------------------------------------------------------------------
// CPU detection
#if defined(__GNUC__)
# define LOCAL_GCC_VERSION ((__GNUC__ << 8) | __GNUC_MINOR__)
# 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
#endif
// WEBP_HAVE_* are used to indicate the presence of the instruction set in dsp
// files without intrinsics, allowing the corresponding Init() to be called.
// Files containing intrinsics will need to be built targeting the instruction
// set so should succeed on one of the earlier tests.
#if defined(__SSE2__) || defined(WEBP_MSC_SSE2) || defined(WEBP_HAVE_SSE2)
#define WEBP_USE_SSE2
#endif
#if defined(__AVX2__) || defined(WEBP_HAVE_AVX2)
#define WEBP_USE_AVX2
#endif
#if defined(__ANDROID__) && defined(__ARM_ARCH_7A__)
#define WEBP_ANDROID_NEON // Android targets that might support NEON
#endif
#if defined(__ARM_NEON__) || defined(WEBP_ANDROID_NEON) || defined(__aarch64__)
#define WEBP_USE_NEON
#endif
#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 {
kSSE2,
kSSE3,
kAVX,
kAVX2,
kNEON,
kMIPS32
} CPUFeature;
// returns true if the CPU supports the feature.
typedef int (*VP8CPUInfo)(CPUFeature feature);
extern VP8CPUInfo VP8GetCPUInfo;
//------------------------------------------------------------------------------
// Encoding
// Transforms
// VP8Idct: Does one of two inverse transforms. If do_two is set, the transforms
// will be done for (ref, in, dst) and (ref + 4, in + 16, dst + 4).
typedef void (*VP8Idct)(const uint8_t* ref, const int16_t* in, uint8_t* dst,
int do_two);
typedef void (*VP8Fdct)(const uint8_t* src, const uint8_t* ref, int16_t* out);
typedef void (*VP8WHT)(const int16_t* in, int16_t* out);
extern VP8Idct VP8ITransform;
extern VP8Fdct VP8FTransform;
extern VP8WHT VP8FTransformWHT;
// Predictions
// *dst is the destination block. *top and *left can be NULL.
typedef void (*VP8IntraPreds)(uint8_t *dst, const uint8_t* left,
const uint8_t* top);
typedef void (*VP8Intra4Preds)(uint8_t *dst, const uint8_t* top);
extern VP8Intra4Preds VP8EncPredLuma4;
extern VP8IntraPreds VP8EncPredLuma16;
extern VP8IntraPreds VP8EncPredChroma8;
typedef int (*VP8Metric)(const uint8_t* pix, const uint8_t* ref);
extern VP8Metric VP8SSE16x16, VP8SSE16x8, VP8SSE8x8, VP8SSE4x4;
typedef int (*VP8WMetric)(const uint8_t* pix, const uint8_t* ref,
const uint16_t* const weights);
extern VP8WMetric VP8TDisto4x4, VP8TDisto16x16;
typedef void (*VP8BlockCopy)(const uint8_t* src, uint8_t* dst);
extern VP8BlockCopy VP8Copy4x4;
// Quantization
struct VP8Matrix; // forward declaration
typedef int (*VP8QuantizeBlock)(int16_t in[16], int16_t out[16],
const struct VP8Matrix* const mtx);
extern VP8QuantizeBlock VP8EncQuantizeBlock;
// specific to 2nd transform:
typedef int (*VP8QuantizeBlockWHT)(int16_t in[16], int16_t out[16],
const struct VP8Matrix* const mtx);
extern VP8QuantizeBlockWHT VP8EncQuantizeBlockWHT;
// Collect histogram for susceptibility calculation and accumulate in histo[].
struct VP8Histogram;
typedef void (*VP8CHisto)(const uint8_t* ref, const uint8_t* pred,
int start_block, int end_block,
struct VP8Histogram* const histo);
extern const int VP8DspScan[16 + 4 + 4];
extern VP8CHisto VP8CollectHistogram;
void VP8EncDspInit(void); // must be called before using any of the above
//------------------------------------------------------------------------------
// Decoding
typedef void (*VP8DecIdct)(const int16_t* coeffs, uint8_t* dst);
// when doing two transforms, coeffs is actually int16_t[2][16].
typedef void (*VP8DecIdct2)(const int16_t* coeffs, uint8_t* dst, int do_two);
extern VP8DecIdct2 VP8Transform;
extern VP8DecIdct VP8TransformAC3;
extern VP8DecIdct VP8TransformUV;
extern VP8DecIdct VP8TransformDC;
extern VP8DecIdct VP8TransformDCUV;
extern VP8WHT VP8TransformWHT;
// *dst is the destination block, with stride BPS. Boundary samples are
// assumed accessible when needed.
typedef void (*VP8PredFunc)(uint8_t* dst);
extern const VP8PredFunc VP8PredLuma16[/* NUM_B_DC_MODES */];
extern const VP8PredFunc VP8PredChroma8[/* NUM_B_DC_MODES */];
extern const VP8PredFunc VP8PredLuma4[/* NUM_BMODES */];
// clipping tables (for filtering)
extern const int8_t* const VP8ksclip1; // clips [-1020, 1020] to [-128, 127]
extern const int8_t* const VP8ksclip2; // clips [-112, 112] to [-16, 15]
extern const uint8_t* const VP8kclip1; // clips [-255,511] to [0,255]
extern const uint8_t* const VP8kabs0; // abs(x) for x in [-255,255]
void VP8InitClipTables(void); // must be called first
// simple filter (only for luma)
typedef void (*VP8SimpleFilterFunc)(uint8_t* p, int stride, int thresh);
extern VP8SimpleFilterFunc VP8SimpleVFilter16;
extern VP8SimpleFilterFunc VP8SimpleHFilter16;
extern VP8SimpleFilterFunc VP8SimpleVFilter16i; // filter 3 inner edges
extern VP8SimpleFilterFunc VP8SimpleHFilter16i;
// regular filter (on both macroblock edges and inner edges)
typedef void (*VP8LumaFilterFunc)(uint8_t* luma, int stride,
int thresh, int ithresh, int hev_t);
typedef void (*VP8ChromaFilterFunc)(uint8_t* u, uint8_t* v, int stride,
int thresh, int ithresh, int hev_t);
// on outer edge
extern VP8LumaFilterFunc VP8VFilter16;
extern VP8LumaFilterFunc VP8HFilter16;
extern VP8ChromaFilterFunc VP8VFilter8;
extern VP8ChromaFilterFunc VP8HFilter8;
// on inner edge
extern VP8LumaFilterFunc VP8VFilter16i; // filtering 3 inner edges altogether
extern VP8LumaFilterFunc VP8HFilter16i;
extern VP8ChromaFilterFunc VP8VFilter8i; // filtering u and v altogether
extern VP8ChromaFilterFunc VP8HFilter8i;
// must be called before anything using the above
void VP8DspInit(void);
//------------------------------------------------------------------------------
// WebP I/O
#define FANCY_UPSAMPLING // undefined to remove fancy upsampling support
// Convert a pair of y/u/v lines together to the output rgb/a colorspace.
// bottom_y can be NULL if only one line of output is needed (at top/bottom).
typedef void (*WebPUpsampleLinePairFunc)(
const uint8_t* top_y, const uint8_t* bottom_y,
const uint8_t* top_u, const uint8_t* top_v,
const uint8_t* cur_u, const uint8_t* cur_v,
uint8_t* top_dst, uint8_t* bottom_dst, int len);
#ifdef FANCY_UPSAMPLING
// Fancy upsampling functions to convert YUV to RGB(A) modes
extern WebPUpsampleLinePairFunc WebPUpsamplers[/* MODE_LAST */];
#endif // FANCY_UPSAMPLING
// Per-row point-sampling methods.
typedef void (*WebPSamplerRowFunc)(const uint8_t* y,
const uint8_t* u, const uint8_t* v,
uint8_t* dst, int len);
// Generic function to apply 'WebPSamplerRowFunc' to the whole plane:
void WebPSamplerProcessPlane(const uint8_t* y, int y_stride,
const uint8_t* u, const uint8_t* v, int uv_stride,
uint8_t* dst, int dst_stride,
int width, int height, WebPSamplerRowFunc func);
// Sampling functions to convert rows of YUV to RGB(A)
extern WebPSamplerRowFunc WebPSamplers[/* MODE_LAST */];
// General function for converting two lines of ARGB or RGBA.
// 'alpha_is_last' should be true if 0xff000000 is stored in memory as
// as 0x00, 0x00, 0x00, 0xff (little endian).
WebPUpsampleLinePairFunc WebPGetLinePairConverter(int alpha_is_last);
// YUV444->RGB converters
typedef void (*WebPYUV444Converter)(const uint8_t* y,
const uint8_t* u, const uint8_t* v,
uint8_t* dst, int len);
extern const WebPYUV444Converter WebPYUV444Converters[/* MODE_LAST */];
// Must be called before using the WebPUpsamplers[] (and for premultiplied
// colorspaces like rgbA, rgbA4444, etc)
void WebPInitUpsamplers(void);
// Must be called before using WebPSamplers[]
void WebPInitSamplers(void);
//------------------------------------------------------------------------------
// Utilities for processing transparent channel.
// Apply alpha pre-multiply on an rgba, bgra or argb plane of size w * h.
// alpha_first should be 0 for argb, 1 for rgba or bgra (where alpha is last).
extern void (*WebPApplyAlphaMultiply)(
uint8_t* rgba, int alpha_first, int w, int h, int stride);
// Same, buf specifically for RGBA4444 format
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.
// Pre-Multiply or Un-Multiply (if 'inverse' is true) argb values in a row.
extern void (*WebPMultARGBRow)(uint32_t* const ptr, int width, int inverse);
// Same a WebPMultARGBRow(), but for several rows.
void WebPMultARGBRows(uint8_t* ptr, int stride, int width, int num_rows,
int inverse);
// Same for a row of single values, with side alpha values.
extern void (*WebPMultRow)(uint8_t* const ptr, const uint8_t* const alpha,
int width, int inverse);
// Same a WebPMultRow(), but for several 'num_rows' rows.
void WebPMultRows(uint8_t* ptr, int stride,
const uint8_t* alpha, int alpha_stride,
int width, int num_rows, int inverse);
// To be called first before using the above.
void WebPInitAlphaProcessing(void);
#ifdef __cplusplus
} // extern "C"
#endif
#endif /* WEBP_DSP_DSP_H_ */

View File

@ -1,22 +1,65 @@
// Copyright 2011 Google Inc.
// Copyright 2011 Google Inc. All Rights Reserved.
//
// This code is licensed under the same terms as WebM:
// Software License Agreement: http://www.webmproject.org/license/software/
// Additional IP Rights Grant: http://www.webmproject.org/license/additional/
// 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.
// -----------------------------------------------------------------------------
//
// speed-critical functions.
// Speed-critical encoding functions.
//
// Author: Skal (pascal.massimino@gmail.com)
#include <assert.h>
#include "vp8enci.h"
#include <stdlib.h> // for abs()
#if defined(__cplusplus) || defined(c_plusplus)
extern "C" {
#endif
#include "./dsp.h"
#include "../enc/vp8enci.h"
//-----------------------------------------------------------------------------
static WEBP_INLINE uint8_t clip_8b(int v) {
return (!(v & ~0xff)) ? v : (v < 0) ? 0 : 255;
}
static WEBP_INLINE int clip_max(int v, int max) {
return (v > max) ? max : v;
}
//------------------------------------------------------------------------------
// Compute susceptibility based on DCT-coeff histograms:
// the higher, the "easier" the macroblock is to compress.
const int VP8DspScan[16 + 4 + 4] = {
// Luma
0 + 0 * BPS, 4 + 0 * BPS, 8 + 0 * BPS, 12 + 0 * BPS,
0 + 4 * BPS, 4 + 4 * BPS, 8 + 4 * BPS, 12 + 4 * BPS,
0 + 8 * BPS, 4 + 8 * BPS, 8 + 8 * BPS, 12 + 8 * BPS,
0 + 12 * BPS, 4 + 12 * BPS, 8 + 12 * BPS, 12 + 12 * BPS,
0 + 0 * BPS, 4 + 0 * BPS, 0 + 4 * BPS, 4 + 4 * BPS, // U
8 + 0 * BPS, 12 + 0 * BPS, 8 + 4 * BPS, 12 + 4 * BPS // V
};
static void CollectHistogram(const uint8_t* ref, const uint8_t* pred,
int start_block, int end_block,
VP8Histogram* const histo) {
int j;
for (j = start_block; j < end_block; ++j) {
int k;
int16_t out[16];
VP8FTransform(ref + VP8DspScan[j], pred + VP8DspScan[j], out);
// Convert coefficients to bin.
for (k = 0; k < 16; ++k) {
const int v = abs(out[k]) >> 3; // TODO(skal): add rounding?
const int clipped_value = clip_max(v, MAX_COEFF_THRESH);
histo->distribution[clipped_value]++;
}
}
}
//------------------------------------------------------------------------------
// run-time tables (~4k)
static uint8_t clip1[255 + 510 + 1]; // clips [-255,510] to [0,255]
@ -29,17 +72,14 @@ static void InitTables(void) {
if (!tables_ok) {
int i;
for (i = -255; i <= 255 + 255; ++i) {
clip1[255 + i] = (i < 0) ? 0 : (i > 255) ? 255 : i;
clip1[255 + i] = clip_8b(i);
}
tables_ok = 1;
}
}
static inline uint8_t clip_8b(int v) {
return (!(v & ~0xff)) ? v : v < 0 ? 0 : 255;
}
//-----------------------------------------------------------------------------
//------------------------------------------------------------------------------
// Transforms (Paragraph 14.4)
#define STORE(x, y, v) \
@ -49,7 +89,8 @@ static const int kC1 = 20091 + (1 << 16);
static const int kC2 = 35468;
#define MUL(a, b) (((a) * (b)) >> 16)
static void ITransform(const uint8_t* ref, const int16_t* in, uint8_t* dst) {
static WEBP_INLINE void ITransformOne(const uint8_t* ref, const int16_t* in,
uint8_t* dst) {
int C[4 * 4], *tmp;
int i;
tmp = C;
@ -81,113 +122,90 @@ static void ITransform(const uint8_t* ref, const int16_t* in, uint8_t* dst) {
}
}
static void ITransform(const uint8_t* ref, const int16_t* in, uint8_t* dst,
int do_two) {
ITransformOne(ref, in, dst);
if (do_two) {
ITransformOne(ref + 4, in + 16, dst + 4);
}
}
static void FTransform(const uint8_t* src, const uint8_t* ref, int16_t* out) {
int i;
int tmp[16];
for (i = 0; i < 4; ++i, src += BPS, ref += BPS) {
const int d0 = src[0] - ref[0];
const int d0 = src[0] - ref[0]; // 9bit dynamic range ([-255,255])
const int d1 = src[1] - ref[1];
const int d2 = src[2] - ref[2];
const int d3 = src[3] - ref[3];
const int a0 = (d0 + d3) << 3;
const int a1 = (d1 + d2) << 3;
const int a2 = (d1 - d2) << 3;
const int a3 = (d0 - d3) << 3;
tmp[0 + i * 4] = (a0 + a1);
tmp[1 + i * 4] = (a2 * 2217 + a3 * 5352 + 14500) >> 12;
tmp[2 + i * 4] = (a0 - a1);
tmp[3 + i * 4] = (a3 * 2217 - a2 * 5352 + 7500) >> 12;
const int a0 = (d0 + d3); // 10b [-510,510]
const int a1 = (d1 + d2);
const int a2 = (d1 - d2);
const int a3 = (d0 - d3);
tmp[0 + i * 4] = (a0 + a1) * 8; // 14b [-8160,8160]
tmp[1 + i * 4] = (a2 * 2217 + a3 * 5352 + 1812) >> 9; // [-7536,7542]
tmp[2 + i * 4] = (a0 - a1) * 8;
tmp[3 + i * 4] = (a3 * 2217 - a2 * 5352 + 937) >> 9;
}
for (i = 0; i < 4; ++i) {
const int a0 = (tmp[0 + i] + tmp[12 + i]);
const int a0 = (tmp[0 + i] + tmp[12 + i]); // 15b
const int a1 = (tmp[4 + i] + tmp[ 8 + i]);
const int a2 = (tmp[4 + i] - tmp[ 8 + i]);
const int a3 = (tmp[0 + i] - tmp[12 + i]);
out[0 + i] = (a0 + a1 + 7) >> 4;
out[0 + i] = (a0 + a1 + 7) >> 4; // 12b
out[4 + i] = ((a2 * 2217 + a3 * 5352 + 12000) >> 16) + (a3 != 0);
out[8 + i] = (a0 - a1 + 7) >> 4;
out[12+ i] = ((a3 * 2217 - a2 * 5352 + 51000) >> 16);
}
}
static void ITransformWHT(const int16_t* in, int16_t* out) {
int tmp[16];
int i;
for (i = 0; i < 4; ++i) {
const int a0 = in[0 + i] + in[12 + i];
const int a1 = in[4 + i] + in[ 8 + i];
const int a2 = in[4 + i] - in[ 8 + i];
const int a3 = in[0 + i] - in[12 + i];
tmp[0 + i] = a0 + a1;
tmp[8 + i] = a0 - a1;
tmp[4 + i] = a3 + a2;
tmp[12 + i] = a3 - a2;
}
for (i = 0; i < 4; ++i) {
const int dc = tmp[0 + i * 4] + 3; // w/ rounder
const int a0 = dc + tmp[3 + i * 4];
const int a1 = tmp[1 + i * 4] + tmp[2 + i * 4];
const int a2 = tmp[1 + i * 4] - tmp[2 + i * 4];
const int a3 = dc - tmp[3 + i * 4];
out[ 0] = (a0 + a1) >> 3;
out[16] = (a3 + a2) >> 3;
out[32] = (a0 - a1) >> 3;
out[48] = (a3 - a2) >> 3;
out += 64;
}
}
static void FTransformWHT(const int16_t* in, int16_t* out) {
int tmp[16];
// input is 12b signed
int32_t tmp[16];
int i;
for (i = 0; i < 4; ++i, in += 64) {
const int a0 = (in[0 * 16] + in[2 * 16]) << 2;
const int a1 = (in[1 * 16] + in[3 * 16]) << 2;
const int a2 = (in[1 * 16] - in[3 * 16]) << 2;
const int a3 = (in[0 * 16] - in[2 * 16]) << 2;
tmp[0 + i * 4] = (a0 + a1) + (a0 != 0);
const int a0 = (in[0 * 16] + in[2 * 16]); // 13b
const int a1 = (in[1 * 16] + in[3 * 16]);
const int a2 = (in[1 * 16] - in[3 * 16]);
const int a3 = (in[0 * 16] - in[2 * 16]);
tmp[0 + i * 4] = a0 + a1; // 14b
tmp[1 + i * 4] = a3 + a2;
tmp[2 + i * 4] = a3 - a2;
tmp[3 + i * 4] = a0 - a1;
}
for (i = 0; i < 4; ++i) {
const int a0 = (tmp[0 + i] + tmp[8 + i]);
const int a0 = (tmp[0 + i] + tmp[8 + i]); // 15b
const int a1 = (tmp[4 + i] + tmp[12+ i]);
const int a2 = (tmp[4 + i] - tmp[12+ i]);
const int a3 = (tmp[0 + i] - tmp[8 + i]);
const int b0 = a0 + a1;
const int b0 = a0 + a1; // 16b
const int b1 = a3 + a2;
const int b2 = a3 - a2;
const int b3 = a0 - a1;
out[ 0 + i] = (b0 + (b0 > 0) + 3) >> 3;
out[ 4 + i] = (b1 + (b1 > 0) + 3) >> 3;
out[ 8 + i] = (b2 + (b2 > 0) + 3) >> 3;
out[12 + i] = (b3 + (b3 > 0) + 3) >> 3;
out[ 0 + i] = b0 >> 1; // 15b
out[ 4 + i] = b1 >> 1;
out[ 8 + i] = b2 >> 1;
out[12 + i] = b3 >> 1;
}
}
// default C implementations:
VP8Idct VP8ITransform = ITransform;
VP8Fdct VP8FTransform = FTransform;
VP8WHT VP8ITransformWHT = ITransformWHT;
VP8WHT VP8FTransformWHT = FTransformWHT;
#undef MUL
#undef STORE
//-----------------------------------------------------------------------------
//------------------------------------------------------------------------------
// Intra predictions
#define OUT(x, y) dst[(x) + (y) * BPS]
#define DST(x, y) dst[(x) + (y) * BPS]
static inline void Fill(uint8_t* dst, int value, int size) {
static WEBP_INLINE void Fill(uint8_t* dst, int value, int size) {
int j;
for (j = 0; j < size; ++j) {
memset(dst + j * BPS, value, size);
}
}
static inline void VerticalPred(uint8_t* dst, const uint8_t* top, int size) {
static WEBP_INLINE void VerticalPred(uint8_t* dst,
const uint8_t* top, int size) {
int j;
if (top) {
for (j = 0; j < size; ++j) memcpy(dst + j * BPS, top, size);
@ -196,7 +214,8 @@ static inline void VerticalPred(uint8_t* dst, const uint8_t* top, int size) {
}
}
static inline void HorizontalPred(uint8_t* dst, const uint8_t* left, int size) {
static WEBP_INLINE void HorizontalPred(uint8_t* dst,
const uint8_t* left, int size) {
if (left) {
int j;
for (j = 0; j < size; ++j) {
@ -207,8 +226,8 @@ static inline void HorizontalPred(uint8_t* dst, const uint8_t* left, int size) {
}
}
static inline void TrueMotion(uint8_t* dst, const uint8_t* left,
const uint8_t* top, int size) {
static WEBP_INLINE void TrueMotion(uint8_t* dst, const uint8_t* left,
const uint8_t* top, int size) {
int y;
if (left) {
if (top) {
@ -237,9 +256,9 @@ static inline void TrueMotion(uint8_t* dst, const uint8_t* left,
}
}
static inline void DCMode(uint8_t* dst, const uint8_t* left,
const uint8_t* top,
int size, int round, int shift) {
static WEBP_INLINE void DCMode(uint8_t* dst, const uint8_t* left,
const uint8_t* top,
int size, int round, int shift) {
int DC = 0;
int j;
if (top) {
@ -260,7 +279,7 @@ static inline void DCMode(uint8_t* dst, const uint8_t* left,
Fill(dst, DC, size);
}
//-----------------------------------------------------------------------------
//------------------------------------------------------------------------------
// Chroma 8x8 prediction (paragraph 12.2)
static void IntraChromaPreds(uint8_t* dst, const uint8_t* left,
@ -280,7 +299,7 @@ static void IntraChromaPreds(uint8_t* dst, const uint8_t* left,
TrueMotion(C8TM8 + dst, left, top, 8);
}
//-----------------------------------------------------------------------------
//------------------------------------------------------------------------------
// luma 16x16 prediction (paragraph 12.3)
static void Intra16Preds(uint8_t* dst,
@ -291,7 +310,7 @@ static void Intra16Preds(uint8_t* dst,
TrueMotion(I16TM16 + dst, left, top, 16);
}
//-----------------------------------------------------------------------------
//------------------------------------------------------------------------------
// luma 4x4 prediction
#define AVG3(a, b, c) (((a) + 2 * (b) + (c) + 2) >> 2)
@ -339,13 +358,13 @@ static void RD4(uint8_t* dst, const uint8_t* top) {
const int B = top[1];
const int C = top[2];
const int D = top[3];
OUT(0, 3) = AVG3(J, K, L);
OUT(0, 2) = OUT(1, 3) = AVG3(I, J, K);
OUT(0, 1) = OUT(1, 2) = OUT(2, 3) = AVG3(X, I, J);
OUT(0, 0) = OUT(1, 1) = OUT(2, 2) = OUT(3, 3) = AVG3(A, X, I);
OUT(1, 0) = OUT(2, 1) = OUT(3, 2) = AVG3(B, A, X);
OUT(2, 0) = OUT(3, 1) = AVG3(C, B, A);
OUT(3, 0) = AVG3(D, C, B);
DST(0, 3) = AVG3(J, K, L);
DST(0, 2) = DST(1, 3) = AVG3(I, J, K);
DST(0, 1) = DST(1, 2) = DST(2, 3) = AVG3(X, I, J);
DST(0, 0) = DST(1, 1) = DST(2, 2) = DST(3, 3) = AVG3(A, X, I);
DST(1, 0) = DST(2, 1) = DST(3, 2) = AVG3(B, A, X);
DST(2, 0) = DST(3, 1) = AVG3(C, B, A);
DST(3, 0) = AVG3(D, C, B);
}
static void LD4(uint8_t* dst, const uint8_t* top) {
@ -357,13 +376,13 @@ static void LD4(uint8_t* dst, const uint8_t* top) {
const int F = top[5];
const int G = top[6];
const int H = top[7];
OUT(0, 0) = AVG3(A, B, C);
OUT(1, 0) = OUT(0, 1) = AVG3(B, C, D);
OUT(2, 0) = OUT(1, 1) = OUT(0, 2) = AVG3(C, D, E);
OUT(3, 0) = OUT(2, 1) = OUT(1, 2) = OUT(0, 3) = AVG3(D, E, F);
OUT(3, 1) = OUT(2, 2) = OUT(1, 3) = AVG3(E, F, G);
OUT(3, 2) = OUT(2, 3) = AVG3(F, G, H);
OUT(3, 3) = AVG3(G, H, H);
DST(0, 0) = AVG3(A, B, C);
DST(1, 0) = DST(0, 1) = AVG3(B, C, D);
DST(2, 0) = DST(1, 1) = DST(0, 2) = AVG3(C, D, E);
DST(3, 0) = DST(2, 1) = DST(1, 2) = DST(0, 3) = AVG3(D, E, F);
DST(3, 1) = DST(2, 2) = DST(1, 3) = AVG3(E, F, G);
DST(3, 2) = DST(2, 3) = AVG3(F, G, H);
DST(3, 3) = AVG3(G, H, H);
}
static void VR4(uint8_t* dst, const uint8_t* top) {
@ -375,17 +394,17 @@ static void VR4(uint8_t* dst, const uint8_t* top) {
const int B = top[1];
const int C = top[2];
const int D = top[3];
OUT(0, 0) = OUT(1, 2) = AVG2(X, A);
OUT(1, 0) = OUT(2, 2) = AVG2(A, B);
OUT(2, 0) = OUT(3, 2) = AVG2(B, C);
OUT(3, 0) = AVG2(C, D);
DST(0, 0) = DST(1, 2) = AVG2(X, A);
DST(1, 0) = DST(2, 2) = AVG2(A, B);
DST(2, 0) = DST(3, 2) = AVG2(B, C);
DST(3, 0) = AVG2(C, D);
OUT(0, 3) = AVG3(K, J, I);
OUT(0, 2) = AVG3(J, I, X);
OUT(0, 1) = OUT(1, 3) = AVG3(I, X, A);
OUT(1, 1) = OUT(2, 3) = AVG3(X, A, B);
OUT(2, 1) = OUT(3, 3) = AVG3(A, B, C);
OUT(3, 1) = AVG3(B, C, D);
DST(0, 3) = AVG3(K, J, I);
DST(0, 2) = AVG3(J, I, X);
DST(0, 1) = DST(1, 3) = AVG3(I, X, A);
DST(1, 1) = DST(2, 3) = AVG3(X, A, B);
DST(2, 1) = DST(3, 3) = AVG3(A, B, C);
DST(3, 1) = AVG3(B, C, D);
}
static void VL4(uint8_t* dst, const uint8_t* top) {
@ -397,17 +416,17 @@ static void VL4(uint8_t* dst, const uint8_t* top) {
const int F = top[5];
const int G = top[6];
const int H = top[7];
OUT(0, 0) = AVG2(A, B);
OUT(1, 0) = OUT(0, 2) = AVG2(B, C);
OUT(2, 0) = OUT(1, 2) = AVG2(C, D);
OUT(3, 0) = OUT(2, 2) = AVG2(D, E);
DST(0, 0) = AVG2(A, B);
DST(1, 0) = DST(0, 2) = AVG2(B, C);
DST(2, 0) = DST(1, 2) = AVG2(C, D);
DST(3, 0) = DST(2, 2) = AVG2(D, E);
OUT(0, 1) = AVG3(A, B, C);
OUT(1, 1) = OUT(0, 3) = AVG3(B, C, D);
OUT(2, 1) = OUT(1, 3) = AVG3(C, D, E);
OUT(3, 1) = OUT(2, 3) = AVG3(D, E, F);
OUT(3, 2) = AVG3(E, F, G);
OUT(3, 3) = AVG3(F, G, H);
DST(0, 1) = AVG3(A, B, C);
DST(1, 1) = DST(0, 3) = AVG3(B, C, D);
DST(2, 1) = DST(1, 3) = AVG3(C, D, E);
DST(3, 1) = DST(2, 3) = AVG3(D, E, F);
DST(3, 2) = AVG3(E, F, G);
DST(3, 3) = AVG3(F, G, H);
}
static void HU4(uint8_t* dst, const uint8_t* top) {
@ -415,14 +434,14 @@ static void HU4(uint8_t* dst, const uint8_t* top) {
const int J = top[-3];
const int K = top[-4];
const int L = top[-5];
OUT(0, 0) = AVG2(I, J);
OUT(2, 0) = OUT(0, 1) = AVG2(J, K);
OUT(2, 1) = OUT(0, 2) = AVG2(K, L);
OUT(1, 0) = AVG3(I, J, K);
OUT(3, 0) = OUT(1, 1) = AVG3(J, K, L);
OUT(3, 1) = OUT(1, 2) = AVG3(K, L, L);
OUT(3, 2) = OUT(2, 2) =
OUT(0, 3) = OUT(1, 3) = OUT(2, 3) = OUT(3, 3) = L;
DST(0, 0) = AVG2(I, J);
DST(2, 0) = DST(0, 1) = AVG2(J, K);
DST(2, 1) = DST(0, 2) = AVG2(K, L);
DST(1, 0) = AVG3(I, J, K);
DST(3, 0) = DST(1, 1) = AVG3(J, K, L);
DST(3, 1) = DST(1, 2) = AVG3(K, L, L);
DST(3, 2) = DST(2, 2) =
DST(0, 3) = DST(1, 3) = DST(2, 3) = DST(3, 3) = L;
}
static void HD4(uint8_t* dst, const uint8_t* top) {
@ -435,17 +454,17 @@ static void HD4(uint8_t* dst, const uint8_t* top) {
const int B = top[1];
const int C = top[2];
OUT(0, 0) = OUT(2, 1) = AVG2(I, X);
OUT(0, 1) = OUT(2, 2) = AVG2(J, I);
OUT(0, 2) = OUT(2, 3) = AVG2(K, J);
OUT(0, 3) = AVG2(L, K);
DST(0, 0) = DST(2, 1) = AVG2(I, X);
DST(0, 1) = DST(2, 2) = AVG2(J, I);
DST(0, 2) = DST(2, 3) = AVG2(K, J);
DST(0, 3) = AVG2(L, K);
OUT(3, 0) = AVG3(A, B, C);
OUT(2, 0) = AVG3(X, A, B);
OUT(1, 0) = OUT(3, 1) = AVG3(I, X, A);
OUT(1, 1) = OUT(3, 2) = AVG3(J, I, X);
OUT(1, 2) = OUT(3, 3) = AVG3(K, J, I);
OUT(1, 3) = AVG3(L, K, J);
DST(3, 0) = AVG3(A, B, C);
DST(2, 0) = AVG3(X, A, B);
DST(1, 0) = DST(3, 1) = AVG3(I, X, A);
DST(1, 1) = DST(3, 2) = AVG3(J, I, X);
DST(1, 2) = DST(3, 3) = AVG3(K, J, I);
DST(1, 3) = AVG3(L, K, J);
}
static void TM4(uint8_t* dst, const uint8_t* top) {
@ -460,6 +479,7 @@ static void TM4(uint8_t* dst, const uint8_t* top) {
}
}
#undef DST
#undef AVG3
#undef AVG2
@ -478,15 +498,11 @@ static void Intra4Preds(uint8_t* dst, const uint8_t* top) {
HU4(I4HU4 + dst, top);
}
// default C implementations
VP8Intra4Preds VP8EncPredLuma4 = Intra4Preds;
VP8IntraPreds VP8EncPredLuma16 = Intra16Preds;
VP8IntraPreds VP8EncPredChroma8 = IntraChromaPreds;
//-----------------------------------------------------------------------------
//------------------------------------------------------------------------------
// Metric
static inline int GetSSE(const uint8_t* a, const uint8_t* b, int w, int h) {
static WEBP_INLINE int GetSSE(const uint8_t* a, const uint8_t* b,
int w, int h) {
int count = 0;
int y, x;
for (y = 0; y < h; ++y) {
@ -513,59 +529,53 @@ static int SSE4x4(const uint8_t* a, const uint8_t* b) {
return GetSSE(a, b, 4, 4);
}
// default C implementations
VP8Metric VP8SSE16x16 = SSE16x16;
VP8Metric VP8SSE8x8 = SSE8x8;
VP8Metric VP8SSE16x8 = SSE16x8;
VP8Metric VP8SSE4x4 = SSE4x4;
//-----------------------------------------------------------------------------
//------------------------------------------------------------------------------
// Texture distortion
//
// We try to match the spectral content (weighted) between source and
// reconstructed samples.
// Hadamard transform
static void TTransform(const uint8_t* in, int16_t* out) {
// Returns the weighted sum of the absolute value of transformed coefficients.
static int TTransform(const uint8_t* in, const uint16_t* w) {
int sum = 0;
int tmp[16];
int i;
// horizontal pass
for (i = 0; i < 4; ++i, in += BPS) {
const int a0 = (in[0] + in[2]) << 2;
const int a1 = (in[1] + in[3]) << 2;
const int a2 = (in[1] - in[3]) << 2;
const int a3 = (in[0] - in[2]) << 2;
tmp[0 + i * 4] = a0 + a1 + (a0 != 0);
const int a0 = in[0] + in[2];
const int a1 = in[1] + in[3];
const int a2 = in[1] - in[3];
const int a3 = in[0] - in[2];
tmp[0 + i * 4] = a0 + a1;
tmp[1 + i * 4] = a3 + a2;
tmp[2 + i * 4] = a3 - a2;
tmp[3 + i * 4] = a0 - a1;
}
for (i = 0; i < 4; ++i) {
const int a0 = (tmp[0 + i] + tmp[8 + i]);
const int a1 = (tmp[4 + i] + tmp[12+ i]);
const int a2 = (tmp[4 + i] - tmp[12+ i]);
const int a3 = (tmp[0 + i] - tmp[8 + i]);
// vertical pass
for (i = 0; i < 4; ++i, ++w) {
const int a0 = tmp[0 + i] + tmp[8 + i];
const int a1 = tmp[4 + i] + tmp[12+ i];
const int a2 = tmp[4 + i] - tmp[12+ i];
const int a3 = tmp[0 + i] - tmp[8 + i];
const int b0 = a0 + a1;
const int b1 = a3 + a2;
const int b2 = a3 - a2;
const int b3 = a0 - a1;
out[ 0 + i] = (b0 + (b0 < 0) + 3) >> 3;
out[ 4 + i] = (b1 + (b1 < 0) + 3) >> 3;
out[ 8 + i] = (b2 + (b2 < 0) + 3) >> 3;
out[12 + i] = (b3 + (b3 < 0) + 3) >> 3;
sum += w[ 0] * abs(b0);
sum += w[ 4] * abs(b1);
sum += w[ 8] * abs(b2);
sum += w[12] * abs(b3);
}
return sum;
}
static int Disto4x4(const uint8_t* const a, const uint8_t* const b,
const uint16_t* const w) {
int16_t tmp1[16], tmp2[16];
int k;
int D;
TTransform(a, tmp1);
TTransform(b, tmp2);
D = 0;
for (k = 0; k < 16; ++k)
D += w[k] * (abs(tmp2[k]) - abs(tmp1[k]));
return (abs(D) + 8) >> 4;
const int sum1 = TTransform(a, w);
const int sum2 = TTransform(b, w);
return abs(sum2 - sum1) >> 5;
}
static int Disto16x16(const uint8_t* const a, const uint8_t* const b,
@ -580,30 +590,33 @@ static int Disto16x16(const uint8_t* const a, const uint8_t* const b,
return D;
}
VP8WMetric VP8TDisto4x4 = Disto4x4;
VP8WMetric VP8TDisto16x16 = Disto16x16;
//-----------------------------------------------------------------------------
//------------------------------------------------------------------------------
// Quantization
//
static const uint8_t kZigzag[16] = {
0, 1, 4, 8, 5, 2, 3, 6, 9, 12, 13, 10, 7, 11, 14, 15
};
// Simple quantization
static int QuantizeBlock(int16_t in[16], int16_t out[16],
int n, const VP8Matrix* const mtx) {
const VP8Matrix* const mtx) {
int last = -1;
for (; n < 16; ++n) {
const int j = VP8Zigzag[n];
int n;
for (n = 0; n < 16; ++n) {
const int j = kZigzag[n];
const int sign = (in[j] < 0);
int coeff = (sign ? -in[j] : in[j]) + mtx->sharpen_[j];
if (coeff > 2047) coeff = 2047;
const uint32_t coeff = (sign ? -in[j] : in[j]) + mtx->sharpen_[j];
if (coeff > mtx->zthresh_[j]) {
const int Q = mtx->q_[j];
const int iQ = mtx->iq_[j];
const int B = mtx->bias_[j];
out[n] = QUANTDIV(coeff, iQ, B);
if (sign) out[n] = -out[n];
in[j] = out[n] * Q;
if (out[n]) last = n;
const uint32_t Q = mtx->q_[j];
const uint32_t iQ = mtx->iq_[j];
const uint32_t B = mtx->bias_[j];
int level = QUANTDIV(coeff, iQ, B);
if (level > MAX_LEVEL) level = MAX_LEVEL;
if (sign) level = -level;
in[j] = level * Q;
out[n] = level;
if (level) last = n;
} else {
out[n] = 0;
in[j] = 0;
@ -612,13 +625,36 @@ static int QuantizeBlock(int16_t in[16], int16_t out[16],
return (last >= 0);
}
// default C implementation
VP8QuantizeBlock VP8EncQuantizeBlock = QuantizeBlock;
static int QuantizeBlockWHT(int16_t in[16], int16_t out[16],
const VP8Matrix* const mtx) {
int n, last = -1;
for (n = 0; n < 16; ++n) {
const int j = kZigzag[n];
const int sign = (in[j] < 0);
const uint32_t coeff = sign ? -in[j] : in[j];
assert(mtx->sharpen_[j] == 0);
if (coeff > mtx->zthresh_[j]) {
const uint32_t Q = mtx->q_[j];
const uint32_t iQ = mtx->iq_[j];
const uint32_t B = mtx->bias_[j];
int level = QUANTDIV(coeff, iQ, B);
if (level > MAX_LEVEL) level = MAX_LEVEL;
if (sign) level = -level;
in[j] = level * Q;
out[n] = level;
if (level) last = n;
} else {
out[n] = 0;
in[j] = 0;
}
}
return (last >= 0);
}
//-----------------------------------------------------------------------------
//------------------------------------------------------------------------------
// Block copy
static inline void Copy(const uint8_t* src, uint8_t* dst, int size) {
static WEBP_INLINE void Copy(const uint8_t* src, uint8_t* dst, int size) {
int y;
for (y = 0; y < size; ++y) {
memcpy(dst, src, size);
@ -628,20 +664,78 @@ static inline void Copy(const uint8_t* src, uint8_t* dst, int size) {
}
static void Copy4x4(const uint8_t* src, uint8_t* dst) { Copy(src, dst, 4); }
static void Copy8x8(const uint8_t* src, uint8_t* dst) { Copy(src, dst, 8); }
static void Copy16x16(const uint8_t* src, uint8_t* dst) { Copy(src, dst, 16); }
// default C implementations
VP8BlockCopy VP8Copy4x4 = Copy4x4;
VP8BlockCopy VP8Copy8x8 = Copy8x8;
VP8BlockCopy VP8Copy16x16 = Copy16x16;
//------------------------------------------------------------------------------
// Initialization
//-----------------------------------------------------------------------------
// Speed-critical function pointers. We have to initialize them to the default
// implementations within VP8EncDspInit().
VP8CHisto VP8CollectHistogram;
VP8Idct VP8ITransform;
VP8Fdct VP8FTransform;
VP8WHT VP8FTransformWHT;
VP8Intra4Preds VP8EncPredLuma4;
VP8IntraPreds VP8EncPredLuma16;
VP8IntraPreds VP8EncPredChroma8;
VP8Metric VP8SSE16x16;
VP8Metric VP8SSE8x8;
VP8Metric VP8SSE16x8;
VP8Metric VP8SSE4x4;
VP8WMetric VP8TDisto4x4;
VP8WMetric VP8TDisto16x16;
VP8QuantizeBlock VP8EncQuantizeBlock;
VP8QuantizeBlockWHT VP8EncQuantizeBlockWHT;
VP8BlockCopy VP8Copy4x4;
extern void VP8EncDspInitSSE2(void);
extern void VP8EncDspInitAVX2(void);
extern void VP8EncDspInitNEON(void);
extern void VP8EncDspInitMIPS32(void);
void VP8EncDspInit(void) {
VP8DspInit(); // common inverse transforms
InitTables();
// default C implementations
VP8CollectHistogram = CollectHistogram;
VP8ITransform = ITransform;
VP8FTransform = FTransform;
VP8FTransformWHT = FTransformWHT;
VP8EncPredLuma4 = Intra4Preds;
VP8EncPredLuma16 = Intra16Preds;
VP8EncPredChroma8 = IntraChromaPreds;
VP8SSE16x16 = SSE16x16;
VP8SSE8x8 = SSE8x8;
VP8SSE16x8 = SSE16x8;
VP8SSE4x4 = SSE4x4;
VP8TDisto4x4 = Disto4x4;
VP8TDisto16x16 = Disto16x16;
VP8EncQuantizeBlock = QuantizeBlock;
VP8EncQuantizeBlockWHT = QuantizeBlockWHT;
VP8Copy4x4 = Copy4x4;
// If defined, use CPUInfo() to overwrite some pointers with faster versions.
if (VP8GetCPUInfo != NULL) {
#if defined(WEBP_USE_SSE2)
if (VP8GetCPUInfo(kSSE2)) {
VP8EncDspInitSSE2();
}
#endif
#if defined(WEBP_USE_AVX2)
if (VP8GetCPUInfo(kAVX2)) {
VP8EncDspInitAVX2();
}
#endif
#if defined(WEBP_USE_NEON)
if (VP8GetCPUInfo(kNEON)) {
VP8EncDspInitNEON();
}
#endif
#if defined(WEBP_USE_MIPS32)
if (VP8GetCPUInfo(kMIPS32)) {
VP8EncDspInitMIPS32();
}
#endif
}
}
#if defined(__cplusplus) || defined(c_plusplus)
} // extern "C"
#endif

24
src/dsp/enc_avx2.c Normal file
View File

@ -0,0 +1,24 @@
// 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.
// -----------------------------------------------------------------------------
//
// AVX2 version of speed-critical encoding functions.
#include "./dsp.h"
#if defined(WEBP_USE_AVX2)
#endif // WEBP_USE_AVX2
//------------------------------------------------------------------------------
// Entry point
extern void VP8EncDspInitAVX2(void);
void VP8EncDspInitAVX2(void) {
}

767
src/dsp/enc_mips32.c Normal file
View File

@ -0,0 +1,767 @@
// 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.
// -----------------------------------------------------------------------------
//
// MIPS version of speed-critical encoding functions.
//
// Author(s): Djordje Pesut (djordje.pesut@imgtec.com)
// Jovan Zelincevic (jovan.zelincevic@imgtec.com)
// Slobodan Prijic (slobodan.prijic@imgtec.com)
#include "./dsp.h"
#if defined(WEBP_USE_MIPS32)
#include "../enc/vp8enci.h"
#include "../enc/cost.h"
static const int kC1 = 20091 + (1 << 16);
static const int kC2 = 35468;
// macro for one vertical pass in ITransformOne
// MUL macro inlined
// temp0..temp15 holds tmp[0]..tmp[15]
// A..D - offsets in bytes to load from in buffer
// TEMP0..TEMP3 - registers for corresponding tmp elements
// TEMP4..TEMP5 - temporary registers
#define VERTICAL_PASS(A, B, C, D, TEMP4, TEMP0, TEMP1, TEMP2, TEMP3) \
"lh %[temp16], "#A"(%[temp20]) \n\t" \
"lh %[temp18], "#B"(%[temp20]) \n\t" \
"lh %[temp17], "#C"(%[temp20]) \n\t" \
"lh %[temp19], "#D"(%[temp20]) \n\t" \
"addu %["#TEMP4"], %[temp16], %[temp18] \n\t" \
"subu %[temp16], %[temp16], %[temp18] \n\t" \
"mul %["#TEMP0"], %[temp17], %[kC2] \n\t" \
"mul %[temp18], %[temp19], %[kC1] \n\t" \
"mul %[temp17], %[temp17], %[kC1] \n\t" \
"mul %[temp19], %[temp19], %[kC2] \n\t" \
"sra %["#TEMP0"], %["#TEMP0"], 16 \n\n" \
"sra %[temp18], %[temp18], 16 \n\n" \
"sra %[temp17], %[temp17], 16 \n\n" \
"sra %[temp19], %[temp19], 16 \n\n" \
"subu %["#TEMP2"], %["#TEMP0"], %[temp18] \n\t" \
"addu %["#TEMP3"], %[temp17], %[temp19] \n\t" \
"addu %["#TEMP0"], %["#TEMP4"], %["#TEMP3"] \n\t" \
"addu %["#TEMP1"], %[temp16], %["#TEMP2"] \n\t" \
"subu %["#TEMP2"], %[temp16], %["#TEMP2"] \n\t" \
"subu %["#TEMP3"], %["#TEMP4"], %["#TEMP3"] \n\t"
// macro for one horizontal pass in ITransformOne
// MUL and STORE macros inlined
// a = clip_8b(a) is replaced with: a = max(a, 0); a = min(a, 255)
// temp0..temp15 holds tmp[0]..tmp[15]
// A..D - offsets in bytes to load from ref and store to dst buffer
// TEMP0, TEMP4, TEMP8 and TEMP12 - registers for corresponding tmp elements
#define HORIZONTAL_PASS(A, B, C, D, TEMP0, TEMP4, TEMP8, TEMP12) \
"addiu %["#TEMP0"], %["#TEMP0"], 4 \n\t" \
"addu %[temp16], %["#TEMP0"], %["#TEMP8"] \n\t" \
"subu %[temp17], %["#TEMP0"], %["#TEMP8"] \n\t" \
"mul %["#TEMP0"], %["#TEMP4"], %[kC2] \n\t" \
"mul %["#TEMP8"], %["#TEMP12"], %[kC1] \n\t" \
"mul %["#TEMP4"], %["#TEMP4"], %[kC1] \n\t" \
"mul %["#TEMP12"], %["#TEMP12"], %[kC2] \n\t" \
"sra %["#TEMP0"], %["#TEMP0"], 16 \n\t" \
"sra %["#TEMP8"], %["#TEMP8"], 16 \n\t" \
"sra %["#TEMP4"], %["#TEMP4"], 16 \n\t" \
"sra %["#TEMP12"], %["#TEMP12"], 16 \n\t" \
"subu %[temp18], %["#TEMP0"], %["#TEMP8"] \n\t" \
"addu %[temp19], %["#TEMP4"], %["#TEMP12"] \n\t" \
"addu %["#TEMP0"], %[temp16], %[temp19] \n\t" \
"addu %["#TEMP4"], %[temp17], %[temp18] \n\t" \
"subu %["#TEMP8"], %[temp17], %[temp18] \n\t" \
"subu %["#TEMP12"], %[temp16], %[temp19] \n\t" \
"lw %[temp20], 0(%[args]) \n\t" \
"sra %["#TEMP0"], %["#TEMP0"], 3 \n\t" \
"sra %["#TEMP4"], %["#TEMP4"], 3 \n\t" \
"sra %["#TEMP8"], %["#TEMP8"], 3 \n\t" \
"sra %["#TEMP12"], %["#TEMP12"], 3 \n\t" \
"lbu %[temp16], "#A"(%[temp20]) \n\t" \
"lbu %[temp17], "#B"(%[temp20]) \n\t" \
"lbu %[temp18], "#C"(%[temp20]) \n\t" \
"lbu %[temp19], "#D"(%[temp20]) \n\t" \
"addu %["#TEMP0"], %[temp16], %["#TEMP0"] \n\t" \
"addu %["#TEMP4"], %[temp17], %["#TEMP4"] \n\t" \
"addu %["#TEMP8"], %[temp18], %["#TEMP8"] \n\t" \
"addu %["#TEMP12"], %[temp19], %["#TEMP12"] \n\t" \
"slt %[temp16], %["#TEMP0"], $zero \n\t" \
"slt %[temp17], %["#TEMP4"], $zero \n\t" \
"slt %[temp18], %["#TEMP8"], $zero \n\t" \
"slt %[temp19], %["#TEMP12"], $zero \n\t" \
"movn %["#TEMP0"], $zero, %[temp16] \n\t" \
"movn %["#TEMP4"], $zero, %[temp17] \n\t" \
"movn %["#TEMP8"], $zero, %[temp18] \n\t" \
"movn %["#TEMP12"], $zero, %[temp19] \n\t" \
"addiu %[temp20], $zero, 255 \n\t" \
"slt %[temp16], %["#TEMP0"], %[temp20] \n\t" \
"slt %[temp17], %["#TEMP4"], %[temp20] \n\t" \
"slt %[temp18], %["#TEMP8"], %[temp20] \n\t" \
"slt %[temp19], %["#TEMP12"], %[temp20] \n\t" \
"movz %["#TEMP0"], %[temp20], %[temp16] \n\t" \
"movz %["#TEMP4"], %[temp20], %[temp17] \n\t" \
"lw %[temp16], 8(%[args]) \n\t" \
"movz %["#TEMP8"], %[temp20], %[temp18] \n\t" \
"movz %["#TEMP12"], %[temp20], %[temp19] \n\t" \
"sb %["#TEMP0"], "#A"(%[temp16]) \n\t" \
"sb %["#TEMP4"], "#B"(%[temp16]) \n\t" \
"sb %["#TEMP8"], "#C"(%[temp16]) \n\t" \
"sb %["#TEMP12"], "#D"(%[temp16]) \n\t"
// Does one or two inverse transforms.
static WEBP_INLINE void ITransformOne(const uint8_t* ref, const int16_t* in,
uint8_t* dst) {
int temp0, temp1, temp2, temp3, temp4, temp5, temp6;
int temp7, temp8, temp9, temp10, temp11, temp12, temp13;
int temp14, temp15, temp16, temp17, temp18, temp19, temp20;
const int* args[3] = {(const int*)ref, (const int*)in, (const int*)dst};
__asm__ volatile(
"lw %[temp20], 4(%[args]) \n\t"
VERTICAL_PASS(0, 16, 8, 24, temp4, temp0, temp1, temp2, temp3)
VERTICAL_PASS(2, 18, 10, 26, temp8, temp4, temp5, temp6, temp7)
VERTICAL_PASS(4, 20, 12, 28, temp12, temp8, temp9, temp10, temp11)
VERTICAL_PASS(6, 22, 14, 30, temp20, temp12, temp13, temp14, temp15)
HORIZONTAL_PASS( 0, 1, 2, 3, temp0, temp4, temp8, temp12)
HORIZONTAL_PASS(16, 17, 18, 19, temp1, temp5, temp9, temp13)
HORIZONTAL_PASS(32, 33, 34, 35, temp2, temp6, temp10, temp14)
HORIZONTAL_PASS(48, 49, 50, 51, temp3, temp7, temp11, temp15)
: [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2),
[temp3]"=&r"(temp3), [temp4]"=&r"(temp4), [temp5]"=&r"(temp5),
[temp6]"=&r"(temp6), [temp7]"=&r"(temp7), [temp8]"=&r"(temp8),
[temp9]"=&r"(temp9), [temp10]"=&r"(temp10), [temp11]"=&r"(temp11),
[temp12]"=&r"(temp12), [temp13]"=&r"(temp13), [temp14]"=&r"(temp14),
[temp15]"=&r"(temp15), [temp16]"=&r"(temp16), [temp17]"=&r"(temp17),
[temp18]"=&r"(temp18), [temp19]"=&r"(temp19), [temp20]"=&r"(temp20)
: [args]"r"(args), [kC1]"r"(kC1), [kC2]"r"(kC2)
: "memory", "hi", "lo"
);
}
static void ITransform(const uint8_t* ref, const int16_t* in,
uint8_t* dst, int do_two) {
ITransformOne(ref, in, dst);
if (do_two) {
ITransformOne(ref + 4, in + 16, dst + 4);
}
}
#undef VERTICAL_PASS
#undef HORIZONTAL_PASS
// macro for one pass through for loop in QuantizeBlock
// QUANTDIV macro inlined
// J - offset in bytes (kZigzag[n] * 2)
// K - offset in bytes (kZigzag[n] * 4)
// N - offset in bytes (n * 2)
#define QUANTIZE_ONE(J, K, N) \
"lh %[temp0], "#J"(%[ppin]) \n\t" \
"lhu %[temp1], "#J"(%[ppsharpen]) \n\t" \
"lw %[temp2], "#K"(%[ppzthresh]) \n\t" \
"sra %[sign], %[temp0], 15 \n\t" \
"xor %[coeff], %[temp0], %[sign] \n\t" \
"subu %[coeff], %[coeff], %[sign] \n\t" \
"addu %[coeff], %[coeff], %[temp1] \n\t" \
"slt %[temp4], %[temp2], %[coeff] \n\t" \
"addiu %[temp5], $zero, 0 \n\t" \
"addiu %[level], $zero, 0 \n\t" \
"beqz %[temp4], 2f \n\t" \
"lhu %[temp1], "#J"(%[ppiq]) \n\t" \
"lw %[temp2], "#K"(%[ppbias]) \n\t" \
"lhu %[temp3], "#J"(%[ppq]) \n\t" \
"mul %[level], %[coeff], %[temp1] \n\t" \
"addu %[level], %[level], %[temp2] \n\t" \
"sra %[level], %[level], 17 \n\t" \
"slt %[temp4], %[max_level], %[level] \n\t" \
"movn %[level], %[max_level], %[temp4] \n\t" \
"xor %[level], %[level], %[sign] \n\t" \
"subu %[level], %[level], %[sign] \n\t" \
"mul %[temp5], %[level], %[temp3] \n\t" \
"2: \n\t" \
"sh %[temp5], "#J"(%[ppin]) \n\t" \
"sh %[level], "#N"(%[pout]) \n\t"
static int QuantizeBlock(int16_t in[16], int16_t out[16],
const VP8Matrix* const mtx) {
int temp0, temp1, temp2, temp3, temp4, temp5;
int sign, coeff, level, i;
int max_level = MAX_LEVEL;
int16_t* ppin = &in[0];
int16_t* pout = &out[0];
const uint16_t* ppsharpen = &mtx->sharpen_[0];
const uint32_t* ppzthresh = &mtx->zthresh_[0];
const uint16_t* ppq = &mtx->q_[0];
const uint16_t* ppiq = &mtx->iq_[0];
const uint32_t* ppbias = &mtx->bias_[0];
__asm__ volatile(
QUANTIZE_ONE( 0, 0, 0)
QUANTIZE_ONE( 2, 4, 2)
QUANTIZE_ONE( 8, 16, 4)
QUANTIZE_ONE(16, 32, 6)
QUANTIZE_ONE(10, 20, 8)
QUANTIZE_ONE( 4, 8, 10)
QUANTIZE_ONE( 6, 12, 12)
QUANTIZE_ONE(12, 24, 14)
QUANTIZE_ONE(18, 36, 16)
QUANTIZE_ONE(24, 48, 18)
QUANTIZE_ONE(26, 52, 20)
QUANTIZE_ONE(20, 40, 22)
QUANTIZE_ONE(14, 28, 24)
QUANTIZE_ONE(22, 44, 26)
QUANTIZE_ONE(28, 56, 28)
QUANTIZE_ONE(30, 60, 30)
: [temp0]"=&r"(temp0), [temp1]"=&r"(temp1),
[temp2]"=&r"(temp2), [temp3]"=&r"(temp3),
[temp4]"=&r"(temp4), [temp5]"=&r"(temp5),
[sign]"=&r"(sign), [coeff]"=&r"(coeff),
[level]"=&r"(level)
: [pout]"r"(pout), [ppin]"r"(ppin),
[ppiq]"r"(ppiq), [max_level]"r"(max_level),
[ppbias]"r"(ppbias), [ppzthresh]"r"(ppzthresh),
[ppsharpen]"r"(ppsharpen), [ppq]"r"(ppq)
: "memory", "hi", "lo"
);
// moved out from macro to increase possibility for earlier breaking
for (i = 15; i >= 0; i--) {
if (out[i]) return 1;
}
return 0;
}
#undef QUANTIZE_ONE
// macro for one horizontal pass in Disto4x4 (TTransform)
// two calls of function TTransform are merged into single one
// A..D - offsets in bytes to load from a and b buffers
// E..H - offsets in bytes to store first results to tmp buffer
// E1..H1 - offsets in bytes to store second results to tmp buffer
#define HORIZONTAL_PASS(A, B, C, D, E, F, G, H, E1, F1, G1, H1) \
"lbu %[temp0], "#A"(%[a]) \n\t" \
"lbu %[temp1], "#B"(%[a]) \n\t" \
"lbu %[temp2], "#C"(%[a]) \n\t" \
"lbu %[temp3], "#D"(%[a]) \n\t" \
"lbu %[temp4], "#A"(%[b]) \n\t" \
"lbu %[temp5], "#B"(%[b]) \n\t" \
"lbu %[temp6], "#C"(%[b]) \n\t" \
"lbu %[temp7], "#D"(%[b]) \n\t" \
"addu %[temp8], %[temp0], %[temp2] \n\t" \
"subu %[temp0], %[temp0], %[temp2] \n\t" \
"addu %[temp2], %[temp1], %[temp3] \n\t" \
"subu %[temp1], %[temp1], %[temp3] \n\t" \
"addu %[temp3], %[temp4], %[temp6] \n\t" \
"subu %[temp4], %[temp4], %[temp6] \n\t" \
"addu %[temp6], %[temp5], %[temp7] \n\t" \
"subu %[temp5], %[temp5], %[temp7] \n\t" \
"addu %[temp7], %[temp8], %[temp2] \n\t" \
"subu %[temp2], %[temp8], %[temp2] \n\t" \
"addu %[temp8], %[temp0], %[temp1] \n\t" \
"subu %[temp0], %[temp0], %[temp1] \n\t" \
"addu %[temp1], %[temp3], %[temp6] \n\t" \
"subu %[temp3], %[temp3], %[temp6] \n\t" \
"addu %[temp6], %[temp4], %[temp5] \n\t" \
"subu %[temp4], %[temp4], %[temp5] \n\t" \
"sw %[temp7], "#E"(%[tmp]) \n\t" \
"sw %[temp2], "#H"(%[tmp]) \n\t" \
"sw %[temp8], "#F"(%[tmp]) \n\t" \
"sw %[temp0], "#G"(%[tmp]) \n\t" \
"sw %[temp1], "#E1"(%[tmp]) \n\t" \
"sw %[temp3], "#H1"(%[tmp]) \n\t" \
"sw %[temp6], "#F1"(%[tmp]) \n\t" \
"sw %[temp4], "#G1"(%[tmp]) \n\t"
// macro for one vertical pass in Disto4x4 (TTransform)
// two calls of function TTransform are merged into single one
// since only one accu is available in mips32r1 instruction set
// first is done second call of function TTransform and after
// that first one.
// const int sum1 = TTransform(a, w);
// const int sum2 = TTransform(b, w);
// return abs(sum2 - sum1) >> 5;
// (sum2 - sum1) is calculated with madds (sub2) and msubs (sub1)
// A..D - offsets in bytes to load first results from tmp buffer
// A1..D1 - offsets in bytes to load second results from tmp buffer
// E..H - offsets in bytes to load from w buffer
#define VERTICAL_PASS(A, B, C, D, A1, B1, C1, D1, E, F, G, H) \
"lw %[temp0], "#A1"(%[tmp]) \n\t" \
"lw %[temp1], "#C1"(%[tmp]) \n\t" \
"lw %[temp2], "#B1"(%[tmp]) \n\t" \
"lw %[temp3], "#D1"(%[tmp]) \n\t" \
"addu %[temp8], %[temp0], %[temp1] \n\t" \
"subu %[temp0], %[temp0], %[temp1] \n\t" \
"addu %[temp1], %[temp2], %[temp3] \n\t" \
"subu %[temp2], %[temp2], %[temp3] \n\t" \
"addu %[temp3], %[temp8], %[temp1] \n\t" \
"subu %[temp8], %[temp8], %[temp1] \n\t" \
"addu %[temp1], %[temp0], %[temp2] \n\t" \
"subu %[temp0], %[temp0], %[temp2] \n\t" \
"sra %[temp4], %[temp3], 31 \n\t" \
"sra %[temp5], %[temp1], 31 \n\t" \
"sra %[temp6], %[temp0], 31 \n\t" \
"sra %[temp7], %[temp8], 31 \n\t" \
"xor %[temp3], %[temp3], %[temp4] \n\t" \
"xor %[temp1], %[temp1], %[temp5] \n\t" \
"xor %[temp0], %[temp0], %[temp6] \n\t" \
"xor %[temp8], %[temp8], %[temp7] \n\t" \
"subu %[temp3], %[temp3], %[temp4] \n\t" \
"subu %[temp1], %[temp1], %[temp5] \n\t" \
"subu %[temp0], %[temp0], %[temp6] \n\t" \
"subu %[temp8], %[temp8], %[temp7] \n\t" \
"lhu %[temp4], "#E"(%[w]) \n\t" \
"lhu %[temp5], "#F"(%[w]) \n\t" \
"lhu %[temp6], "#G"(%[w]) \n\t" \
"lhu %[temp7], "#H"(%[w]) \n\t" \
"madd %[temp4], %[temp3] \n\t" \
"madd %[temp5], %[temp1] \n\t" \
"madd %[temp6], %[temp0] \n\t" \
"madd %[temp7], %[temp8] \n\t" \
"lw %[temp0], "#A"(%[tmp]) \n\t" \
"lw %[temp1], "#C"(%[tmp]) \n\t" \
"lw %[temp2], "#B"(%[tmp]) \n\t" \
"lw %[temp3], "#D"(%[tmp]) \n\t" \
"addu %[temp8], %[temp0], %[temp1] \n\t" \
"subu %[temp0], %[temp0], %[temp1] \n\t" \
"addu %[temp1], %[temp2], %[temp3] \n\t" \
"subu %[temp2], %[temp2], %[temp3] \n\t" \
"addu %[temp3], %[temp8], %[temp1] \n\t" \
"subu %[temp1], %[temp8], %[temp1] \n\t" \
"addu %[temp8], %[temp0], %[temp2] \n\t" \
"subu %[temp0], %[temp0], %[temp2] \n\t" \
"sra %[temp2], %[temp3], 31 \n\t" \
"xor %[temp3], %[temp3], %[temp2] \n\t" \
"subu %[temp3], %[temp3], %[temp2] \n\t" \
"msub %[temp4], %[temp3] \n\t" \
"sra %[temp2], %[temp8], 31 \n\t" \
"sra %[temp3], %[temp0], 31 \n\t" \
"sra %[temp4], %[temp1], 31 \n\t" \
"xor %[temp8], %[temp8], %[temp2] \n\t" \
"xor %[temp0], %[temp0], %[temp3] \n\t" \
"xor %[temp1], %[temp1], %[temp4] \n\t" \
"subu %[temp8], %[temp8], %[temp2] \n\t" \
"subu %[temp0], %[temp0], %[temp3] \n\t" \
"subu %[temp1], %[temp1], %[temp4] \n\t" \
"msub %[temp5], %[temp8] \n\t" \
"msub %[temp6], %[temp0] \n\t" \
"msub %[temp7], %[temp1] \n\t"
static int Disto4x4(const uint8_t* const a, const uint8_t* const b,
const uint16_t* const w) {
int tmp[32];
int temp0, temp1, temp2, temp3, temp4, temp5, temp6, temp7, temp8;
__asm__ volatile(
HORIZONTAL_PASS( 0, 1, 2, 3, 0, 4, 8, 12, 64, 68, 72, 76)
HORIZONTAL_PASS(16, 17, 18, 19, 16, 20, 24, 28, 80, 84, 88, 92)
HORIZONTAL_PASS(32, 33, 34, 35, 32, 36, 40, 44, 96, 100, 104, 108)
HORIZONTAL_PASS(48, 49, 50, 51, 48, 52, 56, 60, 112, 116, 120, 124)
"mthi $zero \n\t"
"mtlo $zero \n\t"
VERTICAL_PASS( 0, 16, 32, 48, 64, 80, 96, 112, 0, 8, 16, 24)
VERTICAL_PASS( 4, 20, 36, 52, 68, 84, 100, 116, 2, 10, 18, 26)
VERTICAL_PASS( 8, 24, 40, 56, 72, 88, 104, 120, 4, 12, 20, 28)
VERTICAL_PASS(12, 28, 44, 60, 76, 92, 108, 124, 6, 14, 22, 30)
"mflo %[temp0] \n\t"
"sra %[temp1], %[temp0], 31 \n\t"
"xor %[temp0], %[temp0], %[temp1] \n\t"
"subu %[temp0], %[temp0], %[temp1] \n\t"
"sra %[temp0], %[temp0], 5 \n\t"
: [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2),
[temp3]"=&r"(temp3), [temp4]"=&r"(temp4), [temp5]"=&r"(temp5),
[temp6]"=&r"(temp6), [temp7]"=&r"(temp7), [temp8]"=&r"(temp8)
: [a]"r"(a), [b]"r"(b), [w]"r"(w), [tmp]"r"(tmp)
: "memory", "hi", "lo"
);
return temp0;
}
#undef VERTICAL_PASS
#undef HORIZONTAL_PASS
static int Disto16x16(const uint8_t* const a, const uint8_t* const b,
const uint16_t* const w) {
int D = 0;
int x, y;
for (y = 0; y < 16 * BPS; y += 4 * BPS) {
for (x = 0; x < 16; x += 4) {
D += Disto4x4(a + x + y, b + x + y, w);
}
}
return D;
}
// macro for one horizontal pass in FTransform
// temp0..temp15 holds tmp[0]..tmp[15]
// A..D - offsets in bytes to load from src and ref buffers
// TEMP0..TEMP3 - registers for corresponding tmp elements
#define HORIZONTAL_PASS(A, B, C, D, TEMP0, TEMP1, TEMP2, TEMP3) \
"lw %["#TEMP1"], 0(%[args]) \n\t" \
"lw %["#TEMP2"], 4(%[args]) \n\t" \
"lbu %[temp16], "#A"(%["#TEMP1"]) \n\t" \
"lbu %[temp17], "#A"(%["#TEMP2"]) \n\t" \
"lbu %[temp18], "#B"(%["#TEMP1"]) \n\t" \
"lbu %[temp19], "#B"(%["#TEMP2"]) \n\t" \
"subu %[temp20], %[temp16], %[temp17] \n\t" \
"lbu %[temp16], "#C"(%["#TEMP1"]) \n\t" \
"lbu %[temp17], "#C"(%["#TEMP2"]) \n\t" \
"subu %["#TEMP0"], %[temp18], %[temp19] \n\t" \
"lbu %[temp18], "#D"(%["#TEMP1"]) \n\t" \
"lbu %[temp19], "#D"(%["#TEMP2"]) \n\t" \
"subu %["#TEMP1"], %[temp16], %[temp17] \n\t" \
"subu %["#TEMP2"], %[temp18], %[temp19] \n\t" \
"addu %["#TEMP3"], %[temp20], %["#TEMP2"] \n\t" \
"subu %["#TEMP2"], %[temp20], %["#TEMP2"] \n\t" \
"addu %[temp20], %["#TEMP0"], %["#TEMP1"] \n\t" \
"subu %["#TEMP0"], %["#TEMP0"], %["#TEMP1"] \n\t" \
"mul %[temp16], %["#TEMP2"], %[c5352] \n\t" \
"mul %[temp17], %["#TEMP2"], %[c2217] \n\t" \
"mul %[temp18], %["#TEMP0"], %[c5352] \n\t" \
"mul %[temp19], %["#TEMP0"], %[c2217] \n\t" \
"addu %["#TEMP1"], %["#TEMP3"], %[temp20] \n\t" \
"subu %[temp20], %["#TEMP3"], %[temp20] \n\t" \
"sll %["#TEMP0"], %["#TEMP1"], 3 \n\t" \
"sll %["#TEMP2"], %[temp20], 3 \n\t" \
"addiu %[temp16], %[temp16], 1812 \n\t" \
"addiu %[temp17], %[temp17], 937 \n\t" \
"addu %[temp16], %[temp16], %[temp19] \n\t" \
"subu %[temp17], %[temp17], %[temp18] \n\t" \
"sra %["#TEMP1"], %[temp16], 9 \n\t" \
"sra %["#TEMP3"], %[temp17], 9 \n\t"
// macro for one vertical pass in FTransform
// temp0..temp15 holds tmp[0]..tmp[15]
// A..D - offsets in bytes to store to out buffer
// TEMP0, TEMP4, TEMP8 and TEMP12 - registers for corresponding tmp elements
#define VERTICAL_PASS(A, B, C, D, TEMP0, TEMP4, TEMP8, TEMP12) \
"addu %[temp16], %["#TEMP0"], %["#TEMP12"] \n\t" \
"subu %[temp19], %["#TEMP0"], %["#TEMP12"] \n\t" \
"addu %[temp17], %["#TEMP4"], %["#TEMP8"] \n\t" \
"subu %[temp18], %["#TEMP4"], %["#TEMP8"] \n\t" \
"mul %["#TEMP8"], %[temp19], %[c2217] \n\t" \
"mul %["#TEMP12"], %[temp18], %[c2217] \n\t" \
"mul %["#TEMP4"], %[temp19], %[c5352] \n\t" \
"mul %[temp18], %[temp18], %[c5352] \n\t" \
"addiu %[temp16], %[temp16], 7 \n\t" \
"addu %["#TEMP0"], %[temp16], %[temp17] \n\t" \
"sra %["#TEMP0"], %["#TEMP0"], 4 \n\t" \
"addu %["#TEMP12"], %["#TEMP12"], %["#TEMP4"] \n\t" \
"subu %["#TEMP4"], %[temp16], %[temp17] \n\t" \
"sra %["#TEMP4"], %["#TEMP4"], 4 \n\t" \
"addiu %["#TEMP8"], %["#TEMP8"], 30000 \n\t" \
"addiu %["#TEMP12"], %["#TEMP12"], 12000 \n\t" \
"addiu %["#TEMP8"], %["#TEMP8"], 21000 \n\t" \
"subu %["#TEMP8"], %["#TEMP8"], %[temp18] \n\t" \
"sra %["#TEMP12"], %["#TEMP12"], 16 \n\t" \
"sra %["#TEMP8"], %["#TEMP8"], 16 \n\t" \
"addiu %[temp16], %["#TEMP12"], 1 \n\t" \
"movn %["#TEMP12"], %[temp16], %[temp19] \n\t" \
"sh %["#TEMP0"], "#A"(%[temp20]) \n\t" \
"sh %["#TEMP4"], "#C"(%[temp20]) \n\t" \
"sh %["#TEMP8"], "#D"(%[temp20]) \n\t" \
"sh %["#TEMP12"], "#B"(%[temp20]) \n\t"
static void FTransform(const uint8_t* src, const uint8_t* ref, int16_t* out) {
int temp0, temp1, temp2, temp3, temp4, temp5, temp6, temp7, temp8;
int temp9, temp10, temp11, temp12, temp13, temp14, temp15, temp16;
int temp17, temp18, temp19, temp20;
const int c2217 = 2217;
const int c5352 = 5352;
const int* const args[3] =
{ (const int*)src, (const int*)ref, (const int*)out };
__asm__ volatile(
HORIZONTAL_PASS( 0, 1, 2, 3, temp0, temp1, temp2, temp3)
HORIZONTAL_PASS(16, 17, 18, 19, temp4, temp5, temp6, temp7)
HORIZONTAL_PASS(32, 33, 34, 35, temp8, temp9, temp10, temp11)
HORIZONTAL_PASS(48, 49, 50, 51, temp12, temp13, temp14, temp15)
"lw %[temp20], 8(%[args]) \n\t"
VERTICAL_PASS(0, 8, 16, 24, temp0, temp4, temp8, temp12)
VERTICAL_PASS(2, 10, 18, 26, temp1, temp5, temp9, temp13)
VERTICAL_PASS(4, 12, 20, 28, temp2, temp6, temp10, temp14)
VERTICAL_PASS(6, 14, 22, 30, temp3, temp7, temp11, temp15)
: [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2),
[temp3]"=&r"(temp3), [temp4]"=&r"(temp4), [temp5]"=&r"(temp5),
[temp6]"=&r"(temp6), [temp7]"=&r"(temp7), [temp8]"=&r"(temp8),
[temp9]"=&r"(temp9), [temp10]"=&r"(temp10), [temp11]"=&r"(temp11),
[temp12]"=&r"(temp12), [temp13]"=&r"(temp13), [temp14]"=&r"(temp14),
[temp15]"=&r"(temp15), [temp16]"=&r"(temp16), [temp17]"=&r"(temp17),
[temp18]"=&r"(temp18), [temp19]"=&r"(temp19), [temp20]"=&r"(temp20)
: [args]"r"(args), [c2217]"r"(c2217), [c5352]"r"(c5352)
: "memory", "hi", "lo"
);
}
#undef VERTICAL_PASS
#undef HORIZONTAL_PASS
// Forward declaration.
extern int VP8GetResidualCostMIPS32(int ctx0, const VP8Residual* const res);
int VP8GetResidualCostMIPS32(int ctx0, const VP8Residual* const res) {
int n = res->first;
// should be prob[VP8EncBands[n]], but it's equivalent for n=0 or 1
int p0 = res->prob[n][ctx0][0];
const uint16_t* t = res->cost[n][ctx0];
int cost;
const int const_2 = 2;
const int const_255 = 255;
const int const_max_level = MAX_VARIABLE_LEVEL;
int res_cost;
int res_prob;
int res_coeffs;
int res_last;
int v_reg;
int b_reg;
int ctx_reg;
int cost_add, temp_1, temp_2, temp_3;
if (res->last < 0) {
return VP8BitCost(0, p0);
}
cost = (ctx0 == 0) ? VP8BitCost(1, p0) : 0;
res_cost = (int)res->cost;
res_prob = (int)res->prob;
res_coeffs = (int)res->coeffs;
res_last = (int)res->last;
__asm__ volatile(
".set push \n\t"
".set noreorder \n\t"
"sll %[temp_1], %[n], 1 \n\t"
"addu %[res_coeffs], %[res_coeffs], %[temp_1] \n\t"
"slt %[temp_2], %[n], %[res_last] \n\t"
"bnez %[temp_2], 1f \n\t"
" li %[cost_add], 0 \n\t"
"b 2f \n\t"
" nop \n\t"
"1: \n\t"
"lh %[v_reg], 0(%[res_coeffs]) \n\t"
"addu %[b_reg], %[n], %[VP8EncBands] \n\t"
"move %[temp_1], %[const_max_level] \n\t"
"addu %[cost], %[cost], %[cost_add] \n\t"
"negu %[temp_2], %[v_reg] \n\t"
"slti %[temp_3], %[v_reg], 0 \n\t"
"movn %[v_reg], %[temp_2], %[temp_3] \n\t"
"lbu %[b_reg], 1(%[b_reg]) \n\t"
"li %[cost_add], 0 \n\t"
"sltiu %[temp_3], %[v_reg], 2 \n\t"
"move %[ctx_reg], %[v_reg] \n\t"
"movz %[ctx_reg], %[const_2], %[temp_3] \n\t"
// cost += VP8LevelCost(t, v);
"slt %[temp_3], %[v_reg], %[const_max_level] \n\t"
"movn %[temp_1], %[v_reg], %[temp_3] \n\t"
"sll %[temp_2], %[v_reg], 1 \n\t"
"addu %[temp_2], %[temp_2], %[VP8LevelFixedCosts] \n\t"
"lhu %[temp_2], 0(%[temp_2]) \n\t"
"sll %[temp_1], %[temp_1], 1 \n\t"
"addu %[temp_1], %[temp_1], %[t] \n\t"
"lhu %[temp_3], 0(%[temp_1]) \n\t"
"addu %[cost], %[cost], %[temp_2] \n\t"
// t = res->cost[b][ctx];
"sll %[temp_1], %[ctx_reg], 7 \n\t"
"sll %[temp_2], %[ctx_reg], 3 \n\t"
"addu %[cost], %[cost], %[temp_3] \n\t"
"addu %[temp_1], %[temp_1], %[temp_2] \n\t"
"sll %[temp_2], %[b_reg], 3 \n\t"
"sll %[temp_3], %[b_reg], 5 \n\t"
"sub %[temp_2], %[temp_3], %[temp_2] \n\t"
"sll %[temp_3], %[temp_2], 4 \n\t"
"addu %[temp_1], %[temp_1], %[temp_3] \n\t"
"addu %[temp_2], %[temp_2], %[res_cost] \n\t"
"addiu %[n], %[n], 1 \n\t"
"addu %[t], %[temp_1], %[temp_2] \n\t"
"slt %[temp_1], %[n], %[res_last] \n\t"
"bnez %[temp_1], 1b \n\t"
" addiu %[res_coeffs], %[res_coeffs], 2 \n\t"
"2: \n\t"
".set pop \n\t"
: [cost]"+r"(cost), [t]"+r"(t), [n]"+r"(n), [v_reg]"=&r"(v_reg),
[ctx_reg]"=&r"(ctx_reg), [b_reg]"=&r"(b_reg), [cost_add]"=&r"(cost_add),
[temp_1]"=&r"(temp_1), [temp_2]"=&r"(temp_2), [temp_3]"=&r"(temp_3)
: [const_2]"r"(const_2), [const_255]"r"(const_255), [res_last]"r"(res_last),
[VP8EntropyCost]"r"(VP8EntropyCost), [VP8EncBands]"r"(VP8EncBands),
[const_max_level]"r"(const_max_level), [res_prob]"r"(res_prob),
[VP8LevelFixedCosts]"r"(VP8LevelFixedCosts), [res_coeffs]"r"(res_coeffs),
[res_cost]"r"(res_cost)
: "memory"
);
// Last coefficient is always non-zero
{
const int v = abs(res->coeffs[n]);
assert(v != 0);
cost += VP8LevelCost(t, v);
if (n < 15) {
const int b = VP8EncBands[n + 1];
const int ctx = (v == 1) ? 1 : 2;
const int last_p0 = res->prob[b][ctx][0];
cost += VP8BitCost(0, last_p0);
}
}
return cost;
}
#define GET_SSE_INNER(A, B, C, D) \
"lbu %[temp0], "#A"(%[a]) \n\t" \
"lbu %[temp1], "#A"(%[b]) \n\t" \
"lbu %[temp2], "#B"(%[a]) \n\t" \
"lbu %[temp3], "#B"(%[b]) \n\t" \
"lbu %[temp4], "#C"(%[a]) \n\t" \
"lbu %[temp5], "#C"(%[b]) \n\t" \
"lbu %[temp6], "#D"(%[a]) \n\t" \
"lbu %[temp7], "#D"(%[b]) \n\t" \
"subu %[temp0], %[temp0], %[temp1] \n\t" \
"subu %[temp2], %[temp2], %[temp3] \n\t" \
"subu %[temp4], %[temp4], %[temp5] \n\t" \
"subu %[temp6], %[temp6], %[temp7] \n\t" \
"madd %[temp0], %[temp0] \n\t" \
"madd %[temp2], %[temp2] \n\t" \
"madd %[temp4], %[temp4] \n\t" \
"madd %[temp6], %[temp6] \n\t"
#define GET_SSE(A, B, C, D) \
GET_SSE_INNER(A, A + 1, A + 2, A + 3) \
GET_SSE_INNER(B, B + 1, B + 2, B + 3) \
GET_SSE_INNER(C, C + 1, C + 2, C + 3) \
GET_SSE_INNER(D, D + 1, D + 2, D + 3)
static int SSE16x16(const uint8_t* a, const uint8_t* b) {
int count;
int temp0, temp1, temp2, temp3, temp4, temp5, temp6, temp7;
__asm__ volatile(
"mult $zero, $zero \n\t"
GET_SSE( 0, 4, 8, 12)
GET_SSE( 16, 20, 24, 28)
GET_SSE( 32, 36, 40, 44)
GET_SSE( 48, 52, 56, 60)
GET_SSE( 64, 68, 72, 76)
GET_SSE( 80, 84, 88, 92)
GET_SSE( 96, 100, 104, 108)
GET_SSE(112, 116, 120, 124)
GET_SSE(128, 132, 136, 140)
GET_SSE(144, 148, 152, 156)
GET_SSE(160, 164, 168, 172)
GET_SSE(176, 180, 184, 188)
GET_SSE(192, 196, 200, 204)
GET_SSE(208, 212, 216, 220)
GET_SSE(224, 228, 232, 236)
GET_SSE(240, 244, 248, 252)
"mflo %[count] \n\t"
: [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2),
[temp3]"=&r"(temp3), [temp4]"=&r"(temp4), [temp5]"=&r"(temp5),
[temp6]"=&r"(temp6), [temp7]"=&r"(temp7), [count]"=&r"(count)
: [a]"r"(a), [b]"r"(b)
: "memory", "hi" , "lo"
);
return count;
}
static int SSE16x8(const uint8_t* a, const uint8_t* b) {
int count;
int temp0, temp1, temp2, temp3, temp4, temp5, temp6, temp7;
__asm__ volatile(
"mult $zero, $zero \n\t"
GET_SSE( 0, 4, 8, 12)
GET_SSE( 16, 20, 24, 28)
GET_SSE( 32, 36, 40, 44)
GET_SSE( 48, 52, 56, 60)
GET_SSE( 64, 68, 72, 76)
GET_SSE( 80, 84, 88, 92)
GET_SSE( 96, 100, 104, 108)
GET_SSE(112, 116, 120, 124)
"mflo %[count] \n\t"
: [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2),
[temp3]"=&r"(temp3), [temp4]"=&r"(temp4), [temp5]"=&r"(temp5),
[temp6]"=&r"(temp6), [temp7]"=&r"(temp7), [count]"=&r"(count)
: [a]"r"(a), [b]"r"(b)
: "memory", "hi" , "lo"
);
return count;
}
static int SSE8x8(const uint8_t* a, const uint8_t* b) {
int count;
int temp0, temp1, temp2, temp3, temp4, temp5, temp6, temp7;
__asm__ volatile(
"mult $zero, $zero \n\t"
GET_SSE( 0, 4, 16, 20)
GET_SSE(32, 36, 48, 52)
GET_SSE(64, 68, 80, 84)
GET_SSE(96, 100, 112, 116)
"mflo %[count] \n\t"
: [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2),
[temp3]"=&r"(temp3), [temp4]"=&r"(temp4), [temp5]"=&r"(temp5),
[temp6]"=&r"(temp6), [temp7]"=&r"(temp7), [count]"=&r"(count)
: [a]"r"(a), [b]"r"(b)
: "memory", "hi" , "lo"
);
return count;
}
static int SSE4x4(const uint8_t* a, const uint8_t* b) {
int count;
int temp0, temp1, temp2, temp3, temp4, temp5, temp6, temp7;
__asm__ volatile(
"mult $zero, $zero \n\t"
GET_SSE(0, 16, 32, 48)
"mflo %[count] \n\t"
: [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2),
[temp3]"=&r"(temp3), [temp4]"=&r"(temp4), [temp5]"=&r"(temp5),
[temp6]"=&r"(temp6), [temp7]"=&r"(temp7), [count]"=&r"(count)
: [a]"r"(a), [b]"r"(b)
: "memory", "hi" , "lo"
);
return count;
}
#undef GET_SSE_MIPS32
#undef GET_SSE_MIPS32_INNER
#endif // WEBP_USE_MIPS32
//------------------------------------------------------------------------------
// Entry point
extern void VP8EncDspInitMIPS32(void);
void VP8EncDspInitMIPS32(void) {
#if defined(WEBP_USE_MIPS32)
VP8ITransform = ITransform;
VP8EncQuantizeBlock = QuantizeBlock;
VP8TDisto4x4 = Disto4x4;
VP8TDisto16x16 = Disto16x16;
VP8FTransform = FTransform;
VP8SSE16x16 = SSE16x16;
VP8SSE8x8 = SSE8x8;
VP8SSE16x8 = SSE16x8;
VP8SSE4x4 = SSE4x4;
#endif // WEBP_USE_MIPS32
}

1077
src/dsp/enc_neon.c Normal file

File diff suppressed because it is too large Load Diff

982
src/dsp/enc_sse2.c Normal file
View File

@ -0,0 +1,982 @@
// Copyright 2011 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.
// -----------------------------------------------------------------------------
//
// SSE2 version of speed-critical encoding functions.
//
// Author: Christian Duvivier (cduvivier@google.com)
#include "./dsp.h"
#if defined(WEBP_USE_SSE2)
#include <stdlib.h> // for abs()
#include <emmintrin.h>
#include "../enc/cost.h"
#include "../enc/vp8enci.h"
#include "../utils/utils.h"
//------------------------------------------------------------------------------
// Quite useful macro for debugging. Left here for convenience.
#if 0
#include <stdio.h>
static void PrintReg(const __m128i r, const char* const name, int size) {
int n;
union {
__m128i r;
uint8_t i8[16];
uint16_t i16[8];
uint32_t i32[4];
uint64_t i64[2];
} tmp;
tmp.r = r;
printf("%s\t: ", name);
if (size == 8) {
for (n = 0; n < 16; ++n) printf("%.2x ", tmp.i8[n]);
} else if (size == 16) {
for (n = 0; n < 8; ++n) printf("%.4x ", tmp.i16[n]);
} else if (size == 32) {
for (n = 0; n < 4; ++n) printf("%.8x ", tmp.i32[n]);
} else {
for (n = 0; n < 2; ++n) printf("%.16lx ", tmp.i64[n]);
}
printf("\n");
}
#endif
//------------------------------------------------------------------------------
// Compute susceptibility based on DCT-coeff histograms:
// the higher, the "easier" the macroblock is to compress.
static void CollectHistogram(const uint8_t* ref, const uint8_t* pred,
int start_block, int end_block,
VP8Histogram* const histo) {
const __m128i max_coeff_thresh = _mm_set1_epi16(MAX_COEFF_THRESH);
int j;
for (j = start_block; j < end_block; ++j) {
int16_t out[16];
int k;
VP8FTransform(ref + VP8DspScan[j], pred + VP8DspScan[j], out);
// Convert coefficients to bin (within out[]).
{
// Load.
const __m128i out0 = _mm_loadu_si128((__m128i*)&out[0]);
const __m128i out1 = _mm_loadu_si128((__m128i*)&out[8]);
// sign(out) = out >> 15 (0x0000 if positive, 0xffff if negative)
const __m128i sign0 = _mm_srai_epi16(out0, 15);
const __m128i sign1 = _mm_srai_epi16(out1, 15);
// abs(out) = (out ^ sign) - sign
const __m128i xor0 = _mm_xor_si128(out0, sign0);
const __m128i xor1 = _mm_xor_si128(out1, sign1);
const __m128i abs0 = _mm_sub_epi16(xor0, sign0);
const __m128i abs1 = _mm_sub_epi16(xor1, sign1);
// v = abs(out) >> 3
const __m128i v0 = _mm_srai_epi16(abs0, 3);
const __m128i v1 = _mm_srai_epi16(abs1, 3);
// bin = min(v, MAX_COEFF_THRESH)
const __m128i bin0 = _mm_min_epi16(v0, max_coeff_thresh);
const __m128i bin1 = _mm_min_epi16(v1, max_coeff_thresh);
// Store.
_mm_storeu_si128((__m128i*)&out[0], bin0);
_mm_storeu_si128((__m128i*)&out[8], bin1);
}
// Convert coefficients to bin.
for (k = 0; k < 16; ++k) {
histo->distribution[out[k]]++;
}
}
}
//------------------------------------------------------------------------------
// Transforms (Paragraph 14.4)
// Does one or two inverse transforms.
static void ITransform(const uint8_t* ref, const int16_t* in, uint8_t* dst,
int do_two) {
// This implementation makes use of 16-bit fixed point versions of two
// multiply constants:
// K1 = sqrt(2) * cos (pi/8) ~= 85627 / 2^16
// K2 = sqrt(2) * sin (pi/8) ~= 35468 / 2^16
//
// To be able to use signed 16-bit integers, we use the following trick to
// have constants within range:
// - Associated constants are obtained by subtracting the 16-bit fixed point
// version of one:
// k = K - (1 << 16) => K = k + (1 << 16)
// K1 = 85267 => k1 = 20091
// K2 = 35468 => k2 = -30068
// - The multiplication of a variable by a constant become the sum of the
// variable and the multiplication of that variable by the associated
// constant:
// (x * K) >> 16 = (x * (k + (1 << 16))) >> 16 = ((x * k ) >> 16) + x
const __m128i k1 = _mm_set1_epi16(20091);
const __m128i k2 = _mm_set1_epi16(-30068);
__m128i T0, T1, T2, T3;
// Load and concatenate the transform coefficients (we'll do two inverse
// transforms in parallel). In the case of only one inverse transform, the
// second half of the vectors will just contain random value we'll never
// use nor store.
__m128i in0, in1, in2, in3;
{
in0 = _mm_loadl_epi64((__m128i*)&in[0]);
in1 = _mm_loadl_epi64((__m128i*)&in[4]);
in2 = _mm_loadl_epi64((__m128i*)&in[8]);
in3 = _mm_loadl_epi64((__m128i*)&in[12]);
// a00 a10 a20 a30 x x x x
// a01 a11 a21 a31 x x x x
// a02 a12 a22 a32 x x x x
// a03 a13 a23 a33 x x x x
if (do_two) {
const __m128i inB0 = _mm_loadl_epi64((__m128i*)&in[16]);
const __m128i inB1 = _mm_loadl_epi64((__m128i*)&in[20]);
const __m128i inB2 = _mm_loadl_epi64((__m128i*)&in[24]);
const __m128i inB3 = _mm_loadl_epi64((__m128i*)&in[28]);
in0 = _mm_unpacklo_epi64(in0, inB0);
in1 = _mm_unpacklo_epi64(in1, inB1);
in2 = _mm_unpacklo_epi64(in2, inB2);
in3 = _mm_unpacklo_epi64(in3, inB3);
// a00 a10 a20 a30 b00 b10 b20 b30
// a01 a11 a21 a31 b01 b11 b21 b31
// a02 a12 a22 a32 b02 b12 b22 b32
// a03 a13 a23 a33 b03 b13 b23 b33
}
}
// Vertical pass and subsequent transpose.
{
// First pass, c and d calculations are longer because of the "trick"
// multiplications.
const __m128i a = _mm_add_epi16(in0, in2);
const __m128i b = _mm_sub_epi16(in0, in2);
// c = MUL(in1, K2) - MUL(in3, K1) = MUL(in1, k2) - MUL(in3, k1) + in1 - in3
const __m128i c1 = _mm_mulhi_epi16(in1, k2);
const __m128i c2 = _mm_mulhi_epi16(in3, k1);
const __m128i c3 = _mm_sub_epi16(in1, in3);
const __m128i c4 = _mm_sub_epi16(c1, c2);
const __m128i c = _mm_add_epi16(c3, c4);
// d = MUL(in1, K1) + MUL(in3, K2) = MUL(in1, k1) + MUL(in3, k2) + in1 + in3
const __m128i d1 = _mm_mulhi_epi16(in1, k1);
const __m128i d2 = _mm_mulhi_epi16(in3, k2);
const __m128i d3 = _mm_add_epi16(in1, in3);
const __m128i d4 = _mm_add_epi16(d1, d2);
const __m128i d = _mm_add_epi16(d3, d4);
// Second pass.
const __m128i tmp0 = _mm_add_epi16(a, d);
const __m128i tmp1 = _mm_add_epi16(b, c);
const __m128i tmp2 = _mm_sub_epi16(b, c);
const __m128i tmp3 = _mm_sub_epi16(a, d);
// Transpose the two 4x4.
// a00 a01 a02 a03 b00 b01 b02 b03
// a10 a11 a12 a13 b10 b11 b12 b13
// a20 a21 a22 a23 b20 b21 b22 b23
// a30 a31 a32 a33 b30 b31 b32 b33
const __m128i transpose0_0 = _mm_unpacklo_epi16(tmp0, tmp1);
const __m128i transpose0_1 = _mm_unpacklo_epi16(tmp2, tmp3);
const __m128i transpose0_2 = _mm_unpackhi_epi16(tmp0, tmp1);
const __m128i transpose0_3 = _mm_unpackhi_epi16(tmp2, tmp3);
// a00 a10 a01 a11 a02 a12 a03 a13
// a20 a30 a21 a31 a22 a32 a23 a33
// b00 b10 b01 b11 b02 b12 b03 b13
// b20 b30 b21 b31 b22 b32 b23 b33
const __m128i transpose1_0 = _mm_unpacklo_epi32(transpose0_0, transpose0_1);
const __m128i transpose1_1 = _mm_unpacklo_epi32(transpose0_2, transpose0_3);
const __m128i transpose1_2 = _mm_unpackhi_epi32(transpose0_0, transpose0_1);
const __m128i transpose1_3 = _mm_unpackhi_epi32(transpose0_2, transpose0_3);
// a00 a10 a20 a30 a01 a11 a21 a31
// b00 b10 b20 b30 b01 b11 b21 b31
// a02 a12 a22 a32 a03 a13 a23 a33
// b02 b12 a22 b32 b03 b13 b23 b33
T0 = _mm_unpacklo_epi64(transpose1_0, transpose1_1);
T1 = _mm_unpackhi_epi64(transpose1_0, transpose1_1);
T2 = _mm_unpacklo_epi64(transpose1_2, transpose1_3);
T3 = _mm_unpackhi_epi64(transpose1_2, transpose1_3);
// a00 a10 a20 a30 b00 b10 b20 b30
// a01 a11 a21 a31 b01 b11 b21 b31
// a02 a12 a22 a32 b02 b12 b22 b32
// a03 a13 a23 a33 b03 b13 b23 b33
}
// Horizontal pass and subsequent transpose.
{
// First pass, c and d calculations are longer because of the "trick"
// multiplications.
const __m128i four = _mm_set1_epi16(4);
const __m128i dc = _mm_add_epi16(T0, four);
const __m128i a = _mm_add_epi16(dc, T2);
const __m128i b = _mm_sub_epi16(dc, T2);
// c = MUL(T1, K2) - MUL(T3, K1) = MUL(T1, k2) - MUL(T3, k1) + T1 - T3
const __m128i c1 = _mm_mulhi_epi16(T1, k2);
const __m128i c2 = _mm_mulhi_epi16(T3, k1);
const __m128i c3 = _mm_sub_epi16(T1, T3);
const __m128i c4 = _mm_sub_epi16(c1, c2);
const __m128i c = _mm_add_epi16(c3, c4);
// d = MUL(T1, K1) + MUL(T3, K2) = MUL(T1, k1) + MUL(T3, k2) + T1 + T3
const __m128i d1 = _mm_mulhi_epi16(T1, k1);
const __m128i d2 = _mm_mulhi_epi16(T3, k2);
const __m128i d3 = _mm_add_epi16(T1, T3);
const __m128i d4 = _mm_add_epi16(d1, d2);
const __m128i d = _mm_add_epi16(d3, d4);
// Second pass.
const __m128i tmp0 = _mm_add_epi16(a, d);
const __m128i tmp1 = _mm_add_epi16(b, c);
const __m128i tmp2 = _mm_sub_epi16(b, c);
const __m128i tmp3 = _mm_sub_epi16(a, d);
const __m128i shifted0 = _mm_srai_epi16(tmp0, 3);
const __m128i shifted1 = _mm_srai_epi16(tmp1, 3);
const __m128i shifted2 = _mm_srai_epi16(tmp2, 3);
const __m128i shifted3 = _mm_srai_epi16(tmp3, 3);
// Transpose the two 4x4.
// a00 a01 a02 a03 b00 b01 b02 b03
// a10 a11 a12 a13 b10 b11 b12 b13
// a20 a21 a22 a23 b20 b21 b22 b23
// a30 a31 a32 a33 b30 b31 b32 b33
const __m128i transpose0_0 = _mm_unpacklo_epi16(shifted0, shifted1);
const __m128i transpose0_1 = _mm_unpacklo_epi16(shifted2, shifted3);
const __m128i transpose0_2 = _mm_unpackhi_epi16(shifted0, shifted1);
const __m128i transpose0_3 = _mm_unpackhi_epi16(shifted2, shifted3);
// a00 a10 a01 a11 a02 a12 a03 a13
// a20 a30 a21 a31 a22 a32 a23 a33
// b00 b10 b01 b11 b02 b12 b03 b13
// b20 b30 b21 b31 b22 b32 b23 b33
const __m128i transpose1_0 = _mm_unpacklo_epi32(transpose0_0, transpose0_1);
const __m128i transpose1_1 = _mm_unpacklo_epi32(transpose0_2, transpose0_3);
const __m128i transpose1_2 = _mm_unpackhi_epi32(transpose0_0, transpose0_1);
const __m128i transpose1_3 = _mm_unpackhi_epi32(transpose0_2, transpose0_3);
// a00 a10 a20 a30 a01 a11 a21 a31
// b00 b10 b20 b30 b01 b11 b21 b31
// a02 a12 a22 a32 a03 a13 a23 a33
// b02 b12 a22 b32 b03 b13 b23 b33
T0 = _mm_unpacklo_epi64(transpose1_0, transpose1_1);
T1 = _mm_unpackhi_epi64(transpose1_0, transpose1_1);
T2 = _mm_unpacklo_epi64(transpose1_2, transpose1_3);
T3 = _mm_unpackhi_epi64(transpose1_2, transpose1_3);
// a00 a10 a20 a30 b00 b10 b20 b30
// a01 a11 a21 a31 b01 b11 b21 b31
// a02 a12 a22 a32 b02 b12 b22 b32
// a03 a13 a23 a33 b03 b13 b23 b33
}
// Add inverse transform to 'ref' and store.
{
const __m128i zero = _mm_setzero_si128();
// Load the reference(s).
__m128i ref0, ref1, ref2, ref3;
if (do_two) {
// Load eight bytes/pixels per line.
ref0 = _mm_loadl_epi64((__m128i*)&ref[0 * BPS]);
ref1 = _mm_loadl_epi64((__m128i*)&ref[1 * BPS]);
ref2 = _mm_loadl_epi64((__m128i*)&ref[2 * BPS]);
ref3 = _mm_loadl_epi64((__m128i*)&ref[3 * BPS]);
} else {
// Load four bytes/pixels per line.
ref0 = _mm_cvtsi32_si128(*(int*)&ref[0 * BPS]);
ref1 = _mm_cvtsi32_si128(*(int*)&ref[1 * BPS]);
ref2 = _mm_cvtsi32_si128(*(int*)&ref[2 * BPS]);
ref3 = _mm_cvtsi32_si128(*(int*)&ref[3 * BPS]);
}
// Convert to 16b.
ref0 = _mm_unpacklo_epi8(ref0, zero);
ref1 = _mm_unpacklo_epi8(ref1, zero);
ref2 = _mm_unpacklo_epi8(ref2, zero);
ref3 = _mm_unpacklo_epi8(ref3, zero);
// Add the inverse transform(s).
ref0 = _mm_add_epi16(ref0, T0);
ref1 = _mm_add_epi16(ref1, T1);
ref2 = _mm_add_epi16(ref2, T2);
ref3 = _mm_add_epi16(ref3, T3);
// Unsigned saturate to 8b.
ref0 = _mm_packus_epi16(ref0, ref0);
ref1 = _mm_packus_epi16(ref1, ref1);
ref2 = _mm_packus_epi16(ref2, ref2);
ref3 = _mm_packus_epi16(ref3, ref3);
// Store the results.
if (do_two) {
// Store eight bytes/pixels per line.
_mm_storel_epi64((__m128i*)&dst[0 * BPS], ref0);
_mm_storel_epi64((__m128i*)&dst[1 * BPS], ref1);
_mm_storel_epi64((__m128i*)&dst[2 * BPS], ref2);
_mm_storel_epi64((__m128i*)&dst[3 * BPS], ref3);
} else {
// Store four bytes/pixels per line.
*((int32_t *)&dst[0 * BPS]) = _mm_cvtsi128_si32(ref0);
*((int32_t *)&dst[1 * BPS]) = _mm_cvtsi128_si32(ref1);
*((int32_t *)&dst[2 * BPS]) = _mm_cvtsi128_si32(ref2);
*((int32_t *)&dst[3 * BPS]) = _mm_cvtsi128_si32(ref3);
}
}
}
static void FTransform(const uint8_t* src, const uint8_t* ref, int16_t* out) {
const __m128i zero = _mm_setzero_si128();
const __m128i seven = _mm_set1_epi16(7);
const __m128i k937 = _mm_set1_epi32(937);
const __m128i k1812 = _mm_set1_epi32(1812);
const __m128i k51000 = _mm_set1_epi32(51000);
const __m128i k12000_plus_one = _mm_set1_epi32(12000 + (1 << 16));
const __m128i k5352_2217 = _mm_set_epi16(5352, 2217, 5352, 2217,
5352, 2217, 5352, 2217);
const __m128i k2217_5352 = _mm_set_epi16(2217, -5352, 2217, -5352,
2217, -5352, 2217, -5352);
const __m128i k88p = _mm_set_epi16(8, 8, 8, 8, 8, 8, 8, 8);
const __m128i k88m = _mm_set_epi16(-8, 8, -8, 8, -8, 8, -8, 8);
const __m128i k5352_2217p = _mm_set_epi16(2217, 5352, 2217, 5352,
2217, 5352, 2217, 5352);
const __m128i k5352_2217m = _mm_set_epi16(-5352, 2217, -5352, 2217,
-5352, 2217, -5352, 2217);
__m128i v01, v32;
// Difference between src and ref and initial transpose.
{
// Load src and convert to 16b.
const __m128i src0 = _mm_loadl_epi64((__m128i*)&src[0 * BPS]);
const __m128i src1 = _mm_loadl_epi64((__m128i*)&src[1 * BPS]);
const __m128i src2 = _mm_loadl_epi64((__m128i*)&src[2 * BPS]);
const __m128i src3 = _mm_loadl_epi64((__m128i*)&src[3 * BPS]);
const __m128i src_0 = _mm_unpacklo_epi8(src0, zero);
const __m128i src_1 = _mm_unpacklo_epi8(src1, zero);
const __m128i src_2 = _mm_unpacklo_epi8(src2, zero);
const __m128i src_3 = _mm_unpacklo_epi8(src3, zero);
// Load ref and convert to 16b.
const __m128i ref0 = _mm_loadl_epi64((__m128i*)&ref[0 * BPS]);
const __m128i ref1 = _mm_loadl_epi64((__m128i*)&ref[1 * BPS]);
const __m128i ref2 = _mm_loadl_epi64((__m128i*)&ref[2 * BPS]);
const __m128i ref3 = _mm_loadl_epi64((__m128i*)&ref[3 * BPS]);
const __m128i ref_0 = _mm_unpacklo_epi8(ref0, zero);
const __m128i ref_1 = _mm_unpacklo_epi8(ref1, zero);
const __m128i ref_2 = _mm_unpacklo_epi8(ref2, zero);
const __m128i ref_3 = _mm_unpacklo_epi8(ref3, zero);
// Compute difference. -> 00 01 02 03 00 00 00 00
const __m128i diff0 = _mm_sub_epi16(src_0, ref_0);
const __m128i diff1 = _mm_sub_epi16(src_1, ref_1);
const __m128i diff2 = _mm_sub_epi16(src_2, ref_2);
const __m128i diff3 = _mm_sub_epi16(src_3, ref_3);
// Unpack and shuffle
// 00 01 02 03 0 0 0 0
// 10 11 12 13 0 0 0 0
// 20 21 22 23 0 0 0 0
// 30 31 32 33 0 0 0 0
const __m128i shuf01 = _mm_unpacklo_epi32(diff0, diff1);
const __m128i shuf23 = _mm_unpacklo_epi32(diff2, diff3);
// 00 01 10 11 02 03 12 13
// 20 21 30 31 22 23 32 33
const __m128i shuf01_p =
_mm_shufflehi_epi16(shuf01, _MM_SHUFFLE(2, 3, 0, 1));
const __m128i shuf23_p =
_mm_shufflehi_epi16(shuf23, _MM_SHUFFLE(2, 3, 0, 1));
// 00 01 10 11 03 02 13 12
// 20 21 30 31 23 22 33 32
const __m128i s01 = _mm_unpacklo_epi64(shuf01_p, shuf23_p);
const __m128i s32 = _mm_unpackhi_epi64(shuf01_p, shuf23_p);
// 00 01 10 11 20 21 30 31
// 03 02 13 12 23 22 33 32
const __m128i a01 = _mm_add_epi16(s01, s32);
const __m128i a32 = _mm_sub_epi16(s01, s32);
// [d0 + d3 | d1 + d2 | ...] = [a0 a1 | a0' a1' | ... ]
// [d0 - d3 | d1 - d2 | ...] = [a3 a2 | a3' a2' | ... ]
const __m128i tmp0 = _mm_madd_epi16(a01, k88p); // [ (a0 + a1) << 3, ... ]
const __m128i tmp2 = _mm_madd_epi16(a01, k88m); // [ (a0 - a1) << 3, ... ]
const __m128i tmp1_1 = _mm_madd_epi16(a32, k5352_2217p);
const __m128i tmp3_1 = _mm_madd_epi16(a32, k5352_2217m);
const __m128i tmp1_2 = _mm_add_epi32(tmp1_1, k1812);
const __m128i tmp3_2 = _mm_add_epi32(tmp3_1, k937);
const __m128i tmp1 = _mm_srai_epi32(tmp1_2, 9);
const __m128i tmp3 = _mm_srai_epi32(tmp3_2, 9);
const __m128i s03 = _mm_packs_epi32(tmp0, tmp2);
const __m128i s12 = _mm_packs_epi32(tmp1, tmp3);
const __m128i s_lo = _mm_unpacklo_epi16(s03, s12); // 0 1 0 1 0 1...
const __m128i s_hi = _mm_unpackhi_epi16(s03, s12); // 2 3 2 3 2 3
const __m128i v23 = _mm_unpackhi_epi32(s_lo, s_hi);
v01 = _mm_unpacklo_epi32(s_lo, s_hi);
v32 = _mm_shuffle_epi32(v23, _MM_SHUFFLE(1, 0, 3, 2)); // 3 2 3 2 3 2..
}
// Second pass
{
// Same operations are done on the (0,3) and (1,2) pairs.
// a0 = v0 + v3
// a1 = v1 + v2
// a3 = v0 - v3
// a2 = v1 - v2
const __m128i a01 = _mm_add_epi16(v01, v32);
const __m128i a32 = _mm_sub_epi16(v01, v32);
const __m128i a11 = _mm_unpackhi_epi64(a01, a01);
const __m128i a22 = _mm_unpackhi_epi64(a32, a32);
const __m128i a01_plus_7 = _mm_add_epi16(a01, seven);
// d0 = (a0 + a1 + 7) >> 4;
// d2 = (a0 - a1 + 7) >> 4;
const __m128i c0 = _mm_add_epi16(a01_plus_7, a11);
const __m128i c2 = _mm_sub_epi16(a01_plus_7, a11);
const __m128i d0 = _mm_srai_epi16(c0, 4);
const __m128i d2 = _mm_srai_epi16(c2, 4);
// f1 = ((b3 * 5352 + b2 * 2217 + 12000) >> 16)
// f3 = ((b3 * 2217 - b2 * 5352 + 51000) >> 16)
const __m128i b23 = _mm_unpacklo_epi16(a22, a32);
const __m128i c1 = _mm_madd_epi16(b23, k5352_2217);
const __m128i c3 = _mm_madd_epi16(b23, k2217_5352);
const __m128i d1 = _mm_add_epi32(c1, k12000_plus_one);
const __m128i d3 = _mm_add_epi32(c3, k51000);
const __m128i e1 = _mm_srai_epi32(d1, 16);
const __m128i e3 = _mm_srai_epi32(d3, 16);
const __m128i f1 = _mm_packs_epi32(e1, e1);
const __m128i f3 = _mm_packs_epi32(e3, e3);
// f1 = f1 + (a3 != 0);
// The compare will return (0xffff, 0) for (==0, !=0). To turn that into the
// desired (0, 1), we add one earlier through k12000_plus_one.
// -> f1 = f1 + 1 - (a3 == 0)
const __m128i g1 = _mm_add_epi16(f1, _mm_cmpeq_epi16(a32, zero));
const __m128i d0_g1 = _mm_unpacklo_epi64(d0, g1);
const __m128i d2_f3 = _mm_unpacklo_epi64(d2, f3);
_mm_storeu_si128((__m128i*)&out[0], d0_g1);
_mm_storeu_si128((__m128i*)&out[8], d2_f3);
}
}
static void FTransformWHT(const int16_t* in, int16_t* out) {
int32_t tmp[16];
int i;
for (i = 0; i < 4; ++i, in += 64) {
const int a0 = (in[0 * 16] + in[2 * 16]);
const int a1 = (in[1 * 16] + in[3 * 16]);
const int a2 = (in[1 * 16] - in[3 * 16]);
const int a3 = (in[0 * 16] - in[2 * 16]);
tmp[0 + i * 4] = a0 + a1;
tmp[1 + i * 4] = a3 + a2;
tmp[2 + i * 4] = a3 - a2;
tmp[3 + i * 4] = a0 - a1;
}
{
const __m128i src0 = _mm_loadu_si128((__m128i*)&tmp[0]);
const __m128i src1 = _mm_loadu_si128((__m128i*)&tmp[4]);
const __m128i src2 = _mm_loadu_si128((__m128i*)&tmp[8]);
const __m128i src3 = _mm_loadu_si128((__m128i*)&tmp[12]);
const __m128i a0 = _mm_add_epi32(src0, src2);
const __m128i a1 = _mm_add_epi32(src1, src3);
const __m128i a2 = _mm_sub_epi32(src1, src3);
const __m128i a3 = _mm_sub_epi32(src0, src2);
const __m128i b0 = _mm_srai_epi32(_mm_add_epi32(a0, a1), 1);
const __m128i b1 = _mm_srai_epi32(_mm_add_epi32(a3, a2), 1);
const __m128i b2 = _mm_srai_epi32(_mm_sub_epi32(a3, a2), 1);
const __m128i b3 = _mm_srai_epi32(_mm_sub_epi32(a0, a1), 1);
const __m128i out0 = _mm_packs_epi32(b0, b1);
const __m128i out1 = _mm_packs_epi32(b2, b3);
_mm_storeu_si128((__m128i*)&out[0], out0);
_mm_storeu_si128((__m128i*)&out[8], out1);
}
}
//------------------------------------------------------------------------------
// Metric
static int SSE_Nx4(const uint8_t* a, const uint8_t* b,
int num_quads, int do_16) {
const __m128i zero = _mm_setzero_si128();
__m128i sum1 = zero;
__m128i sum2 = zero;
while (num_quads-- > 0) {
// Note: for the !do_16 case, we read 16 pixels instead of 8 but that's ok,
// thanks to buffer over-allocation to that effect.
const __m128i a0 = _mm_loadu_si128((__m128i*)&a[BPS * 0]);
const __m128i a1 = _mm_loadu_si128((__m128i*)&a[BPS * 1]);
const __m128i a2 = _mm_loadu_si128((__m128i*)&a[BPS * 2]);
const __m128i a3 = _mm_loadu_si128((__m128i*)&a[BPS * 3]);
const __m128i b0 = _mm_loadu_si128((__m128i*)&b[BPS * 0]);
const __m128i b1 = _mm_loadu_si128((__m128i*)&b[BPS * 1]);
const __m128i b2 = _mm_loadu_si128((__m128i*)&b[BPS * 2]);
const __m128i b3 = _mm_loadu_si128((__m128i*)&b[BPS * 3]);
// compute clip0(a-b) and clip0(b-a)
const __m128i a0p = _mm_subs_epu8(a0, b0);
const __m128i a0m = _mm_subs_epu8(b0, a0);
const __m128i a1p = _mm_subs_epu8(a1, b1);
const __m128i a1m = _mm_subs_epu8(b1, a1);
const __m128i a2p = _mm_subs_epu8(a2, b2);
const __m128i a2m = _mm_subs_epu8(b2, a2);
const __m128i a3p = _mm_subs_epu8(a3, b3);
const __m128i a3m = _mm_subs_epu8(b3, a3);
// compute |a-b| with 8b arithmetic as clip0(a-b) | clip0(b-a)
const __m128i diff0 = _mm_or_si128(a0p, a0m);
const __m128i diff1 = _mm_or_si128(a1p, a1m);
const __m128i diff2 = _mm_or_si128(a2p, a2m);
const __m128i diff3 = _mm_or_si128(a3p, a3m);
// unpack (only four operations, instead of eight)
const __m128i low0 = _mm_unpacklo_epi8(diff0, zero);
const __m128i low1 = _mm_unpacklo_epi8(diff1, zero);
const __m128i low2 = _mm_unpacklo_epi8(diff2, zero);
const __m128i low3 = _mm_unpacklo_epi8(diff3, zero);
// multiply with self
const __m128i low_madd0 = _mm_madd_epi16(low0, low0);
const __m128i low_madd1 = _mm_madd_epi16(low1, low1);
const __m128i low_madd2 = _mm_madd_epi16(low2, low2);
const __m128i low_madd3 = _mm_madd_epi16(low3, low3);
// collect in a cascading way
const __m128i low_sum0 = _mm_add_epi32(low_madd0, low_madd1);
const __m128i low_sum1 = _mm_add_epi32(low_madd2, low_madd3);
sum1 = _mm_add_epi32(sum1, low_sum0);
sum2 = _mm_add_epi32(sum2, low_sum1);
if (do_16) { // if necessary, process the higher 8 bytes similarly
const __m128i hi0 = _mm_unpackhi_epi8(diff0, zero);
const __m128i hi1 = _mm_unpackhi_epi8(diff1, zero);
const __m128i hi2 = _mm_unpackhi_epi8(diff2, zero);
const __m128i hi3 = _mm_unpackhi_epi8(diff3, zero);
const __m128i hi_madd0 = _mm_madd_epi16(hi0, hi0);
const __m128i hi_madd1 = _mm_madd_epi16(hi1, hi1);
const __m128i hi_madd2 = _mm_madd_epi16(hi2, hi2);
const __m128i hi_madd3 = _mm_madd_epi16(hi3, hi3);
const __m128i hi_sum0 = _mm_add_epi32(hi_madd0, hi_madd1);
const __m128i hi_sum1 = _mm_add_epi32(hi_madd2, hi_madd3);
sum1 = _mm_add_epi32(sum1, hi_sum0);
sum2 = _mm_add_epi32(sum2, hi_sum1);
}
a += 4 * BPS;
b += 4 * BPS;
}
{
int32_t tmp[4];
const __m128i sum = _mm_add_epi32(sum1, sum2);
_mm_storeu_si128((__m128i*)tmp, sum);
return (tmp[3] + tmp[2] + tmp[1] + tmp[0]);
}
}
static int SSE16x16(const uint8_t* a, const uint8_t* b) {
return SSE_Nx4(a, b, 4, 1);
}
static int SSE16x8(const uint8_t* a, const uint8_t* b) {
return SSE_Nx4(a, b, 2, 1);
}
static int SSE8x8(const uint8_t* a, const uint8_t* b) {
return SSE_Nx4(a, b, 2, 0);
}
static int SSE4x4(const uint8_t* a, const uint8_t* b) {
const __m128i zero = _mm_setzero_si128();
// Load values. Note that we read 8 pixels instead of 4,
// but the a/b buffers are over-allocated to that effect.
const __m128i a0 = _mm_loadl_epi64((__m128i*)&a[BPS * 0]);
const __m128i a1 = _mm_loadl_epi64((__m128i*)&a[BPS * 1]);
const __m128i a2 = _mm_loadl_epi64((__m128i*)&a[BPS * 2]);
const __m128i a3 = _mm_loadl_epi64((__m128i*)&a[BPS * 3]);
const __m128i b0 = _mm_loadl_epi64((__m128i*)&b[BPS * 0]);
const __m128i b1 = _mm_loadl_epi64((__m128i*)&b[BPS * 1]);
const __m128i b2 = _mm_loadl_epi64((__m128i*)&b[BPS * 2]);
const __m128i b3 = _mm_loadl_epi64((__m128i*)&b[BPS * 3]);
// Combine pair of lines and convert to 16b.
const __m128i a01 = _mm_unpacklo_epi32(a0, a1);
const __m128i a23 = _mm_unpacklo_epi32(a2, a3);
const __m128i b01 = _mm_unpacklo_epi32(b0, b1);
const __m128i b23 = _mm_unpacklo_epi32(b2, b3);
const __m128i a01s = _mm_unpacklo_epi8(a01, zero);
const __m128i a23s = _mm_unpacklo_epi8(a23, zero);
const __m128i b01s = _mm_unpacklo_epi8(b01, zero);
const __m128i b23s = _mm_unpacklo_epi8(b23, zero);
// Compute differences; (a-b)^2 = (abs(a-b))^2 = (sat8(a-b) + sat8(b-a))^2
// TODO(cduvivier): Dissassemble and figure out why this is fastest. We don't
// need absolute values, there is no need to do calculation
// in 8bit as we are already in 16bit, ... Yet this is what
// benchmarks the fastest!
const __m128i d0 = _mm_subs_epu8(a01s, b01s);
const __m128i d1 = _mm_subs_epu8(b01s, a01s);
const __m128i d2 = _mm_subs_epu8(a23s, b23s);
const __m128i d3 = _mm_subs_epu8(b23s, a23s);
// Square and add them all together.
const __m128i madd0 = _mm_madd_epi16(d0, d0);
const __m128i madd1 = _mm_madd_epi16(d1, d1);
const __m128i madd2 = _mm_madd_epi16(d2, d2);
const __m128i madd3 = _mm_madd_epi16(d3, d3);
const __m128i sum0 = _mm_add_epi32(madd0, madd1);
const __m128i sum1 = _mm_add_epi32(madd2, madd3);
const __m128i sum2 = _mm_add_epi32(sum0, sum1);
int32_t tmp[4];
_mm_storeu_si128((__m128i*)tmp, sum2);
return (tmp[3] + tmp[2] + tmp[1] + tmp[0]);
}
//------------------------------------------------------------------------------
// Texture distortion
//
// We try to match the spectral content (weighted) between source and
// reconstructed samples.
// Hadamard transform
// Returns the difference between the weighted sum of the absolute value of
// transformed coefficients.
static int TTransform(const uint8_t* inA, const uint8_t* inB,
const uint16_t* const w) {
int32_t sum[4];
__m128i tmp_0, tmp_1, tmp_2, tmp_3;
const __m128i zero = _mm_setzero_si128();
// Load, combine and transpose inputs.
{
const __m128i inA_0 = _mm_loadl_epi64((__m128i*)&inA[BPS * 0]);
const __m128i inA_1 = _mm_loadl_epi64((__m128i*)&inA[BPS * 1]);
const __m128i inA_2 = _mm_loadl_epi64((__m128i*)&inA[BPS * 2]);
const __m128i inA_3 = _mm_loadl_epi64((__m128i*)&inA[BPS * 3]);
const __m128i inB_0 = _mm_loadl_epi64((__m128i*)&inB[BPS * 0]);
const __m128i inB_1 = _mm_loadl_epi64((__m128i*)&inB[BPS * 1]);
const __m128i inB_2 = _mm_loadl_epi64((__m128i*)&inB[BPS * 2]);
const __m128i inB_3 = _mm_loadl_epi64((__m128i*)&inB[BPS * 3]);
// Combine inA and inB (we'll do two transforms in parallel).
const __m128i inAB_0 = _mm_unpacklo_epi8(inA_0, inB_0);
const __m128i inAB_1 = _mm_unpacklo_epi8(inA_1, inB_1);
const __m128i inAB_2 = _mm_unpacklo_epi8(inA_2, inB_2);
const __m128i inAB_3 = _mm_unpacklo_epi8(inA_3, inB_3);
// a00 b00 a01 b01 a02 b03 a03 b03 0 0 0 0 0 0 0 0
// a10 b10 a11 b11 a12 b12 a13 b13 0 0 0 0 0 0 0 0
// a20 b20 a21 b21 a22 b22 a23 b23 0 0 0 0 0 0 0 0
// a30 b30 a31 b31 a32 b32 a33 b33 0 0 0 0 0 0 0 0
// Transpose the two 4x4, discarding the filling zeroes.
const __m128i transpose0_0 = _mm_unpacklo_epi8(inAB_0, inAB_2);
const __m128i transpose0_1 = _mm_unpacklo_epi8(inAB_1, inAB_3);
// a00 a20 b00 b20 a01 a21 b01 b21 a02 a22 b02 b22 a03 a23 b03 b23
// a10 a30 b10 b30 a11 a31 b11 b31 a12 a32 b12 b32 a13 a33 b13 b33
const __m128i transpose1_0 = _mm_unpacklo_epi8(transpose0_0, transpose0_1);
const __m128i transpose1_1 = _mm_unpackhi_epi8(transpose0_0, transpose0_1);
// a00 a10 a20 a30 b00 b10 b20 b30 a01 a11 a21 a31 b01 b11 b21 b31
// a02 a12 a22 a32 b02 b12 b22 b32 a03 a13 a23 a33 b03 b13 b23 b33
// Convert to 16b.
tmp_0 = _mm_unpacklo_epi8(transpose1_0, zero);
tmp_1 = _mm_unpackhi_epi8(transpose1_0, zero);
tmp_2 = _mm_unpacklo_epi8(transpose1_1, zero);
tmp_3 = _mm_unpackhi_epi8(transpose1_1, zero);
// a00 a10 a20 a30 b00 b10 b20 b30
// a01 a11 a21 a31 b01 b11 b21 b31
// a02 a12 a22 a32 b02 b12 b22 b32
// a03 a13 a23 a33 b03 b13 b23 b33
}
// Horizontal pass and subsequent transpose.
{
// Calculate a and b (two 4x4 at once).
const __m128i a0 = _mm_add_epi16(tmp_0, tmp_2);
const __m128i a1 = _mm_add_epi16(tmp_1, tmp_3);
const __m128i a2 = _mm_sub_epi16(tmp_1, tmp_3);
const __m128i a3 = _mm_sub_epi16(tmp_0, tmp_2);
const __m128i b0 = _mm_add_epi16(a0, a1);
const __m128i b1 = _mm_add_epi16(a3, a2);
const __m128i b2 = _mm_sub_epi16(a3, a2);
const __m128i b3 = _mm_sub_epi16(a0, a1);
// a00 a01 a02 a03 b00 b01 b02 b03
// a10 a11 a12 a13 b10 b11 b12 b13
// a20 a21 a22 a23 b20 b21 b22 b23
// a30 a31 a32 a33 b30 b31 b32 b33
// Transpose the two 4x4.
const __m128i transpose0_0 = _mm_unpacklo_epi16(b0, b1);
const __m128i transpose0_1 = _mm_unpacklo_epi16(b2, b3);
const __m128i transpose0_2 = _mm_unpackhi_epi16(b0, b1);
const __m128i transpose0_3 = _mm_unpackhi_epi16(b2, b3);
// a00 a10 a01 a11 a02 a12 a03 a13
// a20 a30 a21 a31 a22 a32 a23 a33
// b00 b10 b01 b11 b02 b12 b03 b13
// b20 b30 b21 b31 b22 b32 b23 b33
const __m128i transpose1_0 = _mm_unpacklo_epi32(transpose0_0, transpose0_1);
const __m128i transpose1_1 = _mm_unpacklo_epi32(transpose0_2, transpose0_3);
const __m128i transpose1_2 = _mm_unpackhi_epi32(transpose0_0, transpose0_1);
const __m128i transpose1_3 = _mm_unpackhi_epi32(transpose0_2, transpose0_3);
// a00 a10 a20 a30 a01 a11 a21 a31
// b00 b10 b20 b30 b01 b11 b21 b31
// a02 a12 a22 a32 a03 a13 a23 a33
// b02 b12 a22 b32 b03 b13 b23 b33
tmp_0 = _mm_unpacklo_epi64(transpose1_0, transpose1_1);
tmp_1 = _mm_unpackhi_epi64(transpose1_0, transpose1_1);
tmp_2 = _mm_unpacklo_epi64(transpose1_2, transpose1_3);
tmp_3 = _mm_unpackhi_epi64(transpose1_2, transpose1_3);
// a00 a10 a20 a30 b00 b10 b20 b30
// a01 a11 a21 a31 b01 b11 b21 b31
// a02 a12 a22 a32 b02 b12 b22 b32
// a03 a13 a23 a33 b03 b13 b23 b33
}
// Vertical pass and difference of weighted sums.
{
// Load all inputs.
// TODO(cduvivier): Make variable declarations and allocations aligned so
// we can use _mm_load_si128 instead of _mm_loadu_si128.
const __m128i w_0 = _mm_loadu_si128((__m128i*)&w[0]);
const __m128i w_8 = _mm_loadu_si128((__m128i*)&w[8]);
// Calculate a and b (two 4x4 at once).
const __m128i a0 = _mm_add_epi16(tmp_0, tmp_2);
const __m128i a1 = _mm_add_epi16(tmp_1, tmp_3);
const __m128i a2 = _mm_sub_epi16(tmp_1, tmp_3);
const __m128i a3 = _mm_sub_epi16(tmp_0, tmp_2);
const __m128i b0 = _mm_add_epi16(a0, a1);
const __m128i b1 = _mm_add_epi16(a3, a2);
const __m128i b2 = _mm_sub_epi16(a3, a2);
const __m128i b3 = _mm_sub_epi16(a0, a1);
// Separate the transforms of inA and inB.
__m128i A_b0 = _mm_unpacklo_epi64(b0, b1);
__m128i A_b2 = _mm_unpacklo_epi64(b2, b3);
__m128i B_b0 = _mm_unpackhi_epi64(b0, b1);
__m128i B_b2 = _mm_unpackhi_epi64(b2, b3);
{
// sign(b) = b >> 15 (0x0000 if positive, 0xffff if negative)
const __m128i sign_A_b0 = _mm_srai_epi16(A_b0, 15);
const __m128i sign_A_b2 = _mm_srai_epi16(A_b2, 15);
const __m128i sign_B_b0 = _mm_srai_epi16(B_b0, 15);
const __m128i sign_B_b2 = _mm_srai_epi16(B_b2, 15);
// b = abs(b) = (b ^ sign) - sign
A_b0 = _mm_xor_si128(A_b0, sign_A_b0);
A_b2 = _mm_xor_si128(A_b2, sign_A_b2);
B_b0 = _mm_xor_si128(B_b0, sign_B_b0);
B_b2 = _mm_xor_si128(B_b2, sign_B_b2);
A_b0 = _mm_sub_epi16(A_b0, sign_A_b0);
A_b2 = _mm_sub_epi16(A_b2, sign_A_b2);
B_b0 = _mm_sub_epi16(B_b0, sign_B_b0);
B_b2 = _mm_sub_epi16(B_b2, sign_B_b2);
}
// weighted sums
A_b0 = _mm_madd_epi16(A_b0, w_0);
A_b2 = _mm_madd_epi16(A_b2, w_8);
B_b0 = _mm_madd_epi16(B_b0, w_0);
B_b2 = _mm_madd_epi16(B_b2, w_8);
A_b0 = _mm_add_epi32(A_b0, A_b2);
B_b0 = _mm_add_epi32(B_b0, B_b2);
// difference of weighted sums
A_b0 = _mm_sub_epi32(A_b0, B_b0);
_mm_storeu_si128((__m128i*)&sum[0], A_b0);
}
return sum[0] + sum[1] + sum[2] + sum[3];
}
static int Disto4x4(const uint8_t* const a, const uint8_t* const b,
const uint16_t* const w) {
const int diff_sum = TTransform(a, b, w);
return abs(diff_sum) >> 5;
}
static int Disto16x16(const uint8_t* const a, const uint8_t* const b,
const uint16_t* const w) {
int D = 0;
int x, y;
for (y = 0; y < 16 * BPS; y += 4 * BPS) {
for (x = 0; x < 16; x += 4) {
D += Disto4x4(a + x + y, b + x + y, w);
}
}
return D;
}
//------------------------------------------------------------------------------
// Quantization
//
static WEBP_INLINE int DoQuantizeBlock(int16_t in[16], int16_t out[16],
const uint16_t* const sharpen,
const VP8Matrix* const mtx) {
const __m128i max_coeff_2047 = _mm_set1_epi16(MAX_LEVEL);
const __m128i zero = _mm_setzero_si128();
__m128i coeff0, coeff8;
__m128i out0, out8;
__m128i packed_out;
// Load all inputs.
// TODO(cduvivier): Make variable declarations and allocations aligned so that
// we can use _mm_load_si128 instead of _mm_loadu_si128.
__m128i in0 = _mm_loadu_si128((__m128i*)&in[0]);
__m128i in8 = _mm_loadu_si128((__m128i*)&in[8]);
const __m128i iq0 = _mm_loadu_si128((__m128i*)&mtx->iq_[0]);
const __m128i iq8 = _mm_loadu_si128((__m128i*)&mtx->iq_[8]);
const __m128i q0 = _mm_loadu_si128((__m128i*)&mtx->q_[0]);
const __m128i q8 = _mm_loadu_si128((__m128i*)&mtx->q_[8]);
// extract sign(in) (0x0000 if positive, 0xffff if negative)
const __m128i sign0 = _mm_cmpgt_epi16(zero, in0);
const __m128i sign8 = _mm_cmpgt_epi16(zero, in8);
// coeff = abs(in) = (in ^ sign) - sign
coeff0 = _mm_xor_si128(in0, sign0);
coeff8 = _mm_xor_si128(in8, sign8);
coeff0 = _mm_sub_epi16(coeff0, sign0);
coeff8 = _mm_sub_epi16(coeff8, sign8);
// coeff = abs(in) + sharpen
if (sharpen != NULL) {
const __m128i sharpen0 = _mm_loadu_si128((__m128i*)&sharpen[0]);
const __m128i sharpen8 = _mm_loadu_si128((__m128i*)&sharpen[8]);
coeff0 = _mm_add_epi16(coeff0, sharpen0);
coeff8 = _mm_add_epi16(coeff8, sharpen8);
}
// out = (coeff * iQ + B) >> QFIX
{
// doing calculations with 32b precision (QFIX=17)
// out = (coeff * iQ)
const __m128i coeff_iQ0H = _mm_mulhi_epu16(coeff0, iq0);
const __m128i coeff_iQ0L = _mm_mullo_epi16(coeff0, iq0);
const __m128i coeff_iQ8H = _mm_mulhi_epu16(coeff8, iq8);
const __m128i coeff_iQ8L = _mm_mullo_epi16(coeff8, iq8);
__m128i out_00 = _mm_unpacklo_epi16(coeff_iQ0L, coeff_iQ0H);
__m128i out_04 = _mm_unpackhi_epi16(coeff_iQ0L, coeff_iQ0H);
__m128i out_08 = _mm_unpacklo_epi16(coeff_iQ8L, coeff_iQ8H);
__m128i out_12 = _mm_unpackhi_epi16(coeff_iQ8L, coeff_iQ8H);
// out = (coeff * iQ + B)
const __m128i bias_00 = _mm_loadu_si128((__m128i*)&mtx->bias_[0]);
const __m128i bias_04 = _mm_loadu_si128((__m128i*)&mtx->bias_[4]);
const __m128i bias_08 = _mm_loadu_si128((__m128i*)&mtx->bias_[8]);
const __m128i bias_12 = _mm_loadu_si128((__m128i*)&mtx->bias_[12]);
out_00 = _mm_add_epi32(out_00, bias_00);
out_04 = _mm_add_epi32(out_04, bias_04);
out_08 = _mm_add_epi32(out_08, bias_08);
out_12 = _mm_add_epi32(out_12, bias_12);
// out = QUANTDIV(coeff, iQ, B, QFIX)
out_00 = _mm_srai_epi32(out_00, QFIX);
out_04 = _mm_srai_epi32(out_04, QFIX);
out_08 = _mm_srai_epi32(out_08, QFIX);
out_12 = _mm_srai_epi32(out_12, QFIX);
// pack result as 16b
out0 = _mm_packs_epi32(out_00, out_04);
out8 = _mm_packs_epi32(out_08, out_12);
// if (coeff > 2047) coeff = 2047
out0 = _mm_min_epi16(out0, max_coeff_2047);
out8 = _mm_min_epi16(out8, max_coeff_2047);
}
// get sign back (if (sign[j]) out_n = -out_n)
out0 = _mm_xor_si128(out0, sign0);
out8 = _mm_xor_si128(out8, sign8);
out0 = _mm_sub_epi16(out0, sign0);
out8 = _mm_sub_epi16(out8, sign8);
// in = out * Q
in0 = _mm_mullo_epi16(out0, q0);
in8 = _mm_mullo_epi16(out8, q8);
_mm_storeu_si128((__m128i*)&in[0], in0);
_mm_storeu_si128((__m128i*)&in[8], in8);
// zigzag the output before storing it.
//
// The zigzag pattern can almost be reproduced with a small sequence of
// shuffles. After it, we only need to swap the 7th (ending up in third
// position instead of twelfth) and 8th values.
{
__m128i outZ0, outZ8;
outZ0 = _mm_shufflehi_epi16(out0, _MM_SHUFFLE(2, 1, 3, 0));
outZ0 = _mm_shuffle_epi32 (outZ0, _MM_SHUFFLE(3, 1, 2, 0));
outZ0 = _mm_shufflehi_epi16(outZ0, _MM_SHUFFLE(3, 1, 0, 2));
outZ8 = _mm_shufflelo_epi16(out8, _MM_SHUFFLE(3, 0, 2, 1));
outZ8 = _mm_shuffle_epi32 (outZ8, _MM_SHUFFLE(3, 1, 2, 0));
outZ8 = _mm_shufflelo_epi16(outZ8, _MM_SHUFFLE(1, 3, 2, 0));
_mm_storeu_si128((__m128i*)&out[0], outZ0);
_mm_storeu_si128((__m128i*)&out[8], outZ8);
packed_out = _mm_packs_epi16(outZ0, outZ8);
}
{
const int16_t outZ_12 = out[12];
const int16_t outZ_3 = out[3];
out[3] = outZ_12;
out[12] = outZ_3;
}
// detect if all 'out' values are zeroes or not
return (_mm_movemask_epi8(_mm_cmpeq_epi8(packed_out, zero)) != 0xffff);
}
static int QuantizeBlock(int16_t in[16], int16_t out[16],
const VP8Matrix* const mtx) {
return DoQuantizeBlock(in, out, &mtx->sharpen_[0], mtx);
}
static int QuantizeBlockWHT(int16_t in[16], int16_t out[16],
const VP8Matrix* const mtx) {
return DoQuantizeBlock(in, out, NULL, mtx);
}
// Forward declaration.
void VP8SetResidualCoeffsSSE2(const int16_t* const coeffs,
VP8Residual* const res);
void VP8SetResidualCoeffsSSE2(const int16_t* const coeffs,
VP8Residual* const res) {
const __m128i c0 = _mm_loadu_si128((const __m128i*)coeffs);
const __m128i c1 = _mm_loadu_si128((const __m128i*)(coeffs + 8));
// Use SSE to compare 8 values with a single instruction.
const __m128i zero = _mm_setzero_si128();
const __m128i m0 = _mm_cmpeq_epi16(c0, zero);
const __m128i m1 = _mm_cmpeq_epi16(c1, zero);
// Get the comparison results as a bitmask, consisting of two times 16 bits:
// two identical bits for each result. Concatenate both bitmasks to get a
// single 32 bit value. Negate the mask to get the position of entries that
// are not equal to zero. We don't need to mask out least significant bits
// according to res->first, since coeffs[0] is 0 if res->first > 0
const uint32_t mask =
~(((uint32_t)_mm_movemask_epi8(m1) << 16) | _mm_movemask_epi8(m0));
// The position of the most significant non-zero bit indicates the position of
// the last non-zero value. Divide the result by two because __movemask_epi8
// operates on 8 bit values instead of 16 bit values.
assert(res->first == 0 || coeffs[0] == 0);
res->last = mask ? (BitsLog2Floor(mask) >> 1) : -1;
res->coeffs = coeffs;
}
#endif // WEBP_USE_SSE2
//------------------------------------------------------------------------------
// Entry point
extern void VP8EncDspInitSSE2(void);
void VP8EncDspInitSSE2(void) {
#if defined(WEBP_USE_SSE2)
VP8CollectHistogram = CollectHistogram;
VP8EncQuantizeBlock = QuantizeBlock;
VP8EncQuantizeBlockWHT = QuantizeBlockWHT;
VP8ITransform = ITransform;
VP8FTransform = FTransform;
VP8FTransformWHT = FTransformWHT;
VP8SSE16x16 = SSE16x16;
VP8SSE16x8 = SSE16x8;
VP8SSE8x8 = SSE8x8;
VP8SSE4x4 = SSE4x4;
VP8TDisto4x4 = Disto4x4;
VP8TDisto16x16 = Disto16x16;
#endif // WEBP_USE_SSE2
}

1639
src/dsp/lossless.c Normal file

File diff suppressed because it is too large Load Diff

249
src/dsp/lossless.h Normal file
View File

@ -0,0 +1,249 @@
// Copyright 2012 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.
// -----------------------------------------------------------------------------
//
// Image transforms and color space conversion methods for lossless decoder.
//
// Authors: Vikas Arora (vikaas.arora@gmail.com)
// Jyrki Alakuijala (jyrki@google.com)
#ifndef WEBP_DSP_LOSSLESS_H_
#define WEBP_DSP_LOSSLESS_H_
#include "../webp/types.h"
#include "../webp/decode.h"
#include "../enc/histogram.h"
#include "../utils/utils.h"
#ifdef __cplusplus
extern "C" {
#endif
//------------------------------------------------------------------------------
// Signatures and generic function-pointers
typedef uint32_t (*VP8LPredictorFunc)(uint32_t left, const uint32_t* const top);
extern VP8LPredictorFunc VP8LPredictors[16];
typedef void (*VP8LProcessBlueAndRedFunc)(uint32_t* argb_data, int num_pixels);
extern VP8LProcessBlueAndRedFunc VP8LSubtractGreenFromBlueAndRed;
extern VP8LProcessBlueAndRedFunc VP8LAddGreenToBlueAndRed;
typedef struct {
// Note: the members are uint8_t, so that any negative values are
// automatically converted to "mod 256" values.
uint8_t green_to_red_;
uint8_t green_to_blue_;
uint8_t red_to_blue_;
} VP8LMultipliers;
typedef void (*VP8LTransformColorFunc)(const VP8LMultipliers* const m,
uint32_t* argb_data, int num_pixels);
extern VP8LTransformColorFunc VP8LTransformColor;
extern VP8LTransformColorFunc VP8LTransformColorInverse;
typedef void (*VP8LConvertFunc)(const uint32_t* src, int num_pixels,
uint8_t* dst);
extern VP8LConvertFunc VP8LConvertBGRAToRGB;
extern VP8LConvertFunc VP8LConvertBGRAToRGBA;
extern VP8LConvertFunc VP8LConvertBGRAToRGBA4444;
extern VP8LConvertFunc VP8LConvertBGRAToRGB565;
extern VP8LConvertFunc VP8LConvertBGRAToBGR;
// Expose some C-only fallback functions
void VP8LTransformColor_C(const VP8LMultipliers* const m,
uint32_t* data, int num_pixels);
void VP8LTransformColorInverse_C(const VP8LMultipliers* const m,
uint32_t* data, int num_pixels);
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);
void VP8LConvertBGRAToRGB565_C(const uint32_t* src,
int num_pixels, uint8_t* dst);
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);
//------------------------------------------------------------------------------
// Image transforms.
struct VP8LTransform; // Defined in dec/vp8li.h.
// Performs inverse transform of data given transform information, start and end
// rows. Transform will be applied to rows [row_start, row_end[.
// The *in and *out pointers refer to source and destination data respectively
// corresponding to the intermediate row (row_start).
void VP8LInverseTransform(const struct VP8LTransform* const transform,
int row_start, int row_end,
const uint32_t* const in, uint32_t* const out);
// Similar to the static method ColorIndexInverseTransform() that is part of
// lossless.c, but used only for alpha decoding. It takes uint8_t (rather than
// uint32_t) arguments for 'src' and 'dst'.
void VP8LColorIndexInverseTransformAlpha(
const struct VP8LTransform* const transform, int y_start, int y_end,
const uint8_t* src, uint8_t* dst);
void VP8LResidualImage(int width, int height, int bits,
uint32_t* const argb, uint32_t* const argb_scratch,
uint32_t* const image);
void VP8LColorSpaceTransform(int width, int height, int bits, int quality,
uint32_t* const argb, uint32_t* image);
//------------------------------------------------------------------------------
// Color space conversion.
// Converts from BGRA to other color spaces.
void VP8LConvertFromBGRA(const uint32_t* const in_data, int num_pixels,
WEBP_CSP_MODE out_colorspace, uint8_t* const rgba);
//------------------------------------------------------------------------------
// Misc methods.
// Computes sampled size of 'size' when sampling using 'sampling bits'.
static WEBP_INLINE uint32_t VP8LSubSampleSize(uint32_t size,
uint32_t sampling_bits) {
return (size + (1 << sampling_bits) - 1) >> sampling_bits;
}
// -----------------------------------------------------------------------------
// Faster logarithm for integers. Small values use a look-up table.
#define LOG_LOOKUP_IDX_MAX 256
extern const float kLog2Table[LOG_LOOKUP_IDX_MAX];
extern const float kSLog2Table[LOG_LOOKUP_IDX_MAX];
typedef float (*VP8LFastLog2SlowFunc)(uint32_t v);
extern VP8LFastLog2SlowFunc VP8LFastLog2Slow;
extern VP8LFastLog2SlowFunc VP8LFastSLog2Slow;
static WEBP_INLINE float VP8LFastLog2(uint32_t v) {
return (v < LOG_LOOKUP_IDX_MAX) ? kLog2Table[v] : VP8LFastLog2Slow(v);
}
// Fast calculation of v * log2(v) for integer input.
static WEBP_INLINE float VP8LFastSLog2(uint32_t v) {
return (v < LOG_LOOKUP_IDX_MAX) ? kSLog2Table[v] : VP8LFastSLog2Slow(v);
}
// -----------------------------------------------------------------------------
// Huffman-cost related functions.
typedef double (*VP8LCostFunc)(const uint32_t* population, int length);
typedef double (*VP8LCostCombinedFunc)(const uint32_t* X, const uint32_t* Y,
int length);
extern VP8LCostFunc VP8LExtraCost;
extern VP8LCostCombinedFunc VP8LExtraCostCombined;
typedef struct { // small struct to hold counters
int counts[2]; // index: 0=zero steak, 1=non-zero streak
int streaks[2][2]; // [zero/non-zero][streak<3 / streak>=3]
} VP8LStreaks;
typedef VP8LStreaks (*VP8LCostCountFunc)(const uint32_t* population,
int length);
typedef VP8LStreaks (*VP8LCostCombinedCountFunc)(const uint32_t* X,
const uint32_t* Y, int length);
extern VP8LCostCountFunc VP8LHuffmanCostCount;
extern VP8LCostCombinedCountFunc VP8LHuffmanCostCombinedCount;
typedef void (*VP8LHistogramAddFunc)(const VP8LHistogram* const a,
const VP8LHistogram* const b,
VP8LHistogram* const out);
extern VP8LHistogramAddFunc VP8LHistogramAdd;
// -----------------------------------------------------------------------------
// PrefixEncode()
static WEBP_INLINE int VP8LBitsLog2Ceiling(uint32_t n) {
const int log_floor = BitsLog2Floor(n);
if (n == (n & ~(n - 1))) // zero or a power of two.
return log_floor;
else
return log_floor + 1;
}
// Splitting of distance and length codes into prefixes and
// extra bits. The prefixes are encoded with an entropy code
// while the extra bits are stored just as normal bits.
static WEBP_INLINE void VP8LPrefixEncodeBitsNoLUT(int distance, int* const code,
int* const extra_bits) {
const int highest_bit = BitsLog2Floor(--distance);
const int second_highest_bit = (distance >> (highest_bit - 1)) & 1;
*extra_bits = highest_bit - 1;
*code = 2 * highest_bit + second_highest_bit;
}
static WEBP_INLINE void VP8LPrefixEncodeNoLUT(int distance, int* const code,
int* const extra_bits,
int* const extra_bits_value) {
const int highest_bit = BitsLog2Floor(--distance);
const int second_highest_bit = (distance >> (highest_bit - 1)) & 1;
*extra_bits = highest_bit - 1;
*extra_bits_value = distance & ((1 << *extra_bits) - 1);
*code = 2 * highest_bit + second_highest_bit;
}
#define PREFIX_LOOKUP_IDX_MAX 512
typedef struct {
int8_t code_;
int8_t extra_bits_;
} VP8LPrefixCode;
// These tables are derived using VP8LPrefixEncodeNoLUT.
extern const VP8LPrefixCode kPrefixEncodeCode[PREFIX_LOOKUP_IDX_MAX];
extern const uint8_t kPrefixEncodeExtraBitsValue[PREFIX_LOOKUP_IDX_MAX];
static WEBP_INLINE void VP8LPrefixEncodeBits(int distance, int* const code,
int* const extra_bits) {
if (distance < PREFIX_LOOKUP_IDX_MAX) {
const VP8LPrefixCode prefix_code = kPrefixEncodeCode[distance];
*code = prefix_code.code_;
*extra_bits = prefix_code.extra_bits_;
} else {
VP8LPrefixEncodeBitsNoLUT(distance, code, extra_bits);
}
}
static WEBP_INLINE void VP8LPrefixEncode(int distance, int* const code,
int* const extra_bits,
int* const extra_bits_value) {
if (distance < PREFIX_LOOKUP_IDX_MAX) {
const VP8LPrefixCode prefix_code = kPrefixEncodeCode[distance];
*code = prefix_code.code_;
*extra_bits = prefix_code.extra_bits_;
*extra_bits_value = kPrefixEncodeExtraBitsValue[distance];
} else {
VP8LPrefixEncodeNoLUT(distance, code, extra_bits, extra_bits_value);
}
}
// In-place difference of each component with mod 256.
static WEBP_INLINE uint32_t VP8LSubPixels(uint32_t a, uint32_t b) {
const uint32_t alpha_and_green =
0x00ff00ffu + (a & 0xff00ff00u) - (b & 0xff00ff00u);
const uint32_t red_and_blue =
0xff00ff00u + (a & 0x00ff00ffu) - (b & 0x00ff00ffu);
return (alpha_and_green & 0xff00ff00u) | (red_and_blue & 0x00ff00ffu);
}
void VP8LBundleColorMap(const uint8_t* const row, int width,
int xbits, uint32_t* const dst);
//------------------------------------------------------------------------------
#ifdef __cplusplus
} // extern "C"
#endif
#endif // WEBP_DSP_LOSSLESS_H_

416
src/dsp/lossless_mips32.c Normal file
View File

@ -0,0 +1,416 @@
// 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.
// -----------------------------------------------------------------------------
//
// MIPS version of lossless functions
//
// Author(s): Djordje Pesut (djordje.pesut@imgtec.com)
// Jovan Zelincevic (jovan.zelincevic@imgtec.com)
#include "./dsp.h"
#include "./lossless.h"
#if defined(WEBP_USE_MIPS32)
#include <assert.h>
#include <math.h>
#include <stdlib.h>
#include <string.h>
#define APPROX_LOG_WITH_CORRECTION_MAX 65536
#define APPROX_LOG_MAX 4096
#define LOG_2_RECIPROCAL 1.44269504088896338700465094007086
static float FastSLog2Slow(uint32_t v) {
assert(v >= LOG_LOOKUP_IDX_MAX);
if (v < APPROX_LOG_WITH_CORRECTION_MAX) {
uint32_t log_cnt, y, correction;
const int c24 = 24;
const float v_f = (float)v;
uint32_t temp;
// Xf = 256 = 2^8
// log_cnt is index of leading one in upper 24 bits
__asm__ volatile(
"clz %[log_cnt], %[v] \n\t"
"addiu %[y], $zero, 1 \n\t"
"subu %[log_cnt], %[c24], %[log_cnt] \n\t"
"sllv %[y], %[y], %[log_cnt] \n\t"
"srlv %[temp], %[v], %[log_cnt] \n\t"
: [log_cnt]"=&r"(log_cnt), [y]"=&r"(y),
[temp]"=r"(temp)
: [c24]"r"(c24), [v]"r"(v)
);
// vf = (2^log_cnt) * Xf; where y = 2^log_cnt and Xf < 256
// Xf = floor(Xf) * (1 + (v % y) / v)
// log2(Xf) = log2(floor(Xf)) + log2(1 + (v % y) / v)
// The correction factor: log(1 + d) ~ d; for very small d values, so
// log2(1 + (v % y) / v) ~ LOG_2_RECIPROCAL * (v % y)/v
// LOG_2_RECIPROCAL ~ 23/16
// (v % y) = (v % 2^log_cnt) = v & (2^log_cnt - 1)
correction = (23 * (v & (y - 1))) >> 4;
return v_f * (kLog2Table[temp] + log_cnt) + correction;
} else {
return (float)(LOG_2_RECIPROCAL * v * log((double)v));
}
}
static float FastLog2Slow(uint32_t v) {
assert(v >= LOG_LOOKUP_IDX_MAX);
if (v < APPROX_LOG_WITH_CORRECTION_MAX) {
uint32_t log_cnt, y;
const int c24 = 24;
double log_2;
uint32_t temp;
__asm__ volatile(
"clz %[log_cnt], %[v] \n\t"
"addiu %[y], $zero, 1 \n\t"
"subu %[log_cnt], %[c24], %[log_cnt] \n\t"
"sllv %[y], %[y], %[log_cnt] \n\t"
"srlv %[temp], %[v], %[log_cnt] \n\t"
: [log_cnt]"=&r"(log_cnt), [y]"=&r"(y),
[temp]"=r"(temp)
: [c24]"r"(c24), [v]"r"(v)
);
log_2 = kLog2Table[temp] + log_cnt;
if (v >= APPROX_LOG_MAX) {
// Since the division is still expensive, add this correction factor only
// for large values of 'v'.
const uint32_t correction = (23 * (v & (y - 1))) >> 4;
log_2 += (double)correction / v;
}
return (float)log_2;
} else {
return (float)(LOG_2_RECIPROCAL * log((double)v));
}
}
// C version of this function:
// int i = 0;
// int64_t cost = 0;
// const uint32_t* pop = &population[4];
// const uint32_t* LoopEnd = &population[length];
// while (pop != LoopEnd) {
// ++i;
// cost += i * *pop;
// cost += i * *(pop + 1);
// pop += 2;
// }
// return (double)cost;
static double ExtraCost(const uint32_t* const population, int length) {
int i, temp0, temp1;
const uint32_t* pop = &population[4];
const uint32_t* const LoopEnd = &population[length];
__asm__ volatile(
"mult $zero, $zero \n\t"
"xor %[i], %[i], %[i] \n\t"
"beq %[pop], %[LoopEnd], 2f \n\t"
"1: \n\t"
"lw %[temp0], 0(%[pop]) \n\t"
"lw %[temp1], 4(%[pop]) \n\t"
"addiu %[i], %[i], 1 \n\t"
"addiu %[pop], %[pop], 8 \n\t"
"madd %[i], %[temp0] \n\t"
"madd %[i], %[temp1] \n\t"
"bne %[pop], %[LoopEnd], 1b \n\t"
"2: \n\t"
"mfhi %[temp0] \n\t"
"mflo %[temp1] \n\t"
: [temp0]"=&r"(temp0), [temp1]"=&r"(temp1),
[i]"=&r"(i), [pop]"+r"(pop)
: [LoopEnd]"r"(LoopEnd)
: "memory", "hi", "lo"
);
return (double)((int64_t)temp0 << 32 | temp1);
}
// C version of this function:
// int i = 0;
// int64_t cost = 0;
// const uint32_t* pX = &X[4];
// const uint32_t* pY = &Y[4];
// const uint32_t* LoopEnd = &X[length];
// while (pX != LoopEnd) {
// const uint32_t xy0 = *pX + *pY;
// const uint32_t xy1 = *(pX + 1) + *(pY + 1);
// ++i;
// cost += i * xy0;
// cost += i * xy1;
// pX += 2;
// pY += 2;
// }
// return (double)cost;
static double ExtraCostCombined(const uint32_t* const X,
const uint32_t* const Y, int length) {
int i, temp0, temp1, temp2, temp3;
const uint32_t* pX = &X[4];
const uint32_t* pY = &Y[4];
const uint32_t* const LoopEnd = &X[length];
__asm__ volatile(
"mult $zero, $zero \n\t"
"xor %[i], %[i], %[i] \n\t"
"beq %[pX], %[LoopEnd], 2f \n\t"
"1: \n\t"
"lw %[temp0], 0(%[pX]) \n\t"
"lw %[temp1], 0(%[pY]) \n\t"
"lw %[temp2], 4(%[pX]) \n\t"
"lw %[temp3], 4(%[pY]) \n\t"
"addiu %[i], %[i], 1 \n\t"
"addu %[temp0], %[temp0], %[temp1] \n\t"
"addu %[temp2], %[temp2], %[temp3] \n\t"
"addiu %[pX], %[pX], 8 \n\t"
"addiu %[pY], %[pY], 8 \n\t"
"madd %[i], %[temp0] \n\t"
"madd %[i], %[temp2] \n\t"
"bne %[pX], %[LoopEnd], 1b \n\t"
"2: \n\t"
"mfhi %[temp0] \n\t"
"mflo %[temp1] \n\t"
: [temp0]"=&r"(temp0), [temp1]"=&r"(temp1),
[temp2]"=&r"(temp2), [temp3]"=&r"(temp3),
[i]"=&r"(i), [pX]"+r"(pX), [pY]"+r"(pY)
: [LoopEnd]"r"(LoopEnd)
: "memory", "hi", "lo"
);
return (double)((int64_t)temp0 << 32 | temp1);
}
#define HUFFMAN_COST_PASS \
__asm__ volatile( \
"sll %[temp1], %[temp0], 3 \n\t" \
"addiu %[temp3], %[streak], -3 \n\t" \
"addu %[temp2], %[pstreaks], %[temp1] \n\t" \
"blez %[temp3], 1f \n\t" \
"srl %[temp1], %[temp1], 1 \n\t" \
"addu %[temp3], %[pcnts], %[temp1] \n\t" \
"lw %[temp0], 4(%[temp2]) \n\t" \
"lw %[temp1], 0(%[temp3]) \n\t" \
"addu %[temp0], %[temp0], %[streak] \n\t" \
"addiu %[temp1], %[temp1], 1 \n\t" \
"sw %[temp0], 4(%[temp2]) \n\t" \
"sw %[temp1], 0(%[temp3]) \n\t" \
"b 2f \n\t" \
"1: \n\t" \
"lw %[temp0], 0(%[temp2]) \n\t" \
"addu %[temp0], %[temp0], %[streak] \n\t" \
"sw %[temp0], 0(%[temp2]) \n\t" \
"2: \n\t" \
: [temp1]"=&r"(temp1), [temp2]"=&r"(temp2), \
[temp3]"=&r"(temp3), [temp0]"+r"(temp0) \
: [pstreaks]"r"(pstreaks), [pcnts]"r"(pcnts), \
[streak]"r"(streak) \
: "memory" \
);
// Returns the various RLE counts
static VP8LStreaks HuffmanCostCount(const uint32_t* population, int length) {
int i;
int streak = 0;
VP8LStreaks stats;
int* const pstreaks = &stats.streaks[0][0];
int* const pcnts = &stats.counts[0];
int temp0, temp1, temp2, temp3;
memset(&stats, 0, sizeof(stats));
for (i = 0; i < length - 1; ++i) {
++streak;
if (population[i] == population[i + 1]) {
continue;
}
temp0 = (population[i] != 0);
HUFFMAN_COST_PASS
streak = 0;
}
++streak;
temp0 = (population[i] != 0);
HUFFMAN_COST_PASS
return stats;
}
static VP8LStreaks HuffmanCostCombinedCount(const uint32_t* X,
const uint32_t* Y, int length) {
int i;
int streak = 0;
VP8LStreaks stats;
int* const pstreaks = &stats.streaks[0][0];
int* const pcnts = &stats.counts[0];
int temp0, temp1, temp2, temp3;
memset(&stats, 0, sizeof(stats));
for (i = 0; i < length - 1; ++i) {
const uint32_t xy = X[i] + Y[i];
const uint32_t xy_next = X[i + 1] + Y[i + 1];
++streak;
if (xy == xy_next) {
continue;
}
temp0 = (xy != 0);
HUFFMAN_COST_PASS
streak = 0;
}
{
const uint32_t xy = X[i] + Y[i];
++streak;
temp0 = (xy != 0);
HUFFMAN_COST_PASS
}
return stats;
}
#define ASM_START \
__asm__ volatile( \
".set push \n\t" \
".set at \n\t" \
".set macro \n\t" \
"1: \n\t"
// P2 = P0 + P1
// A..D - offsets
// E - temp variable to tell macro
// if pointer should be incremented
// literal_ and successive histograms could be unaligned
// so we must use ulw and usw
#define ADD_TO_OUT(A, B, C, D, E, P0, P1, P2) \
"ulw %[temp0], "#A"(%["#P0"]) \n\t" \
"ulw %[temp1], "#B"(%["#P0"]) \n\t" \
"ulw %[temp2], "#C"(%["#P0"]) \n\t" \
"ulw %[temp3], "#D"(%["#P0"]) \n\t" \
"ulw %[temp4], "#A"(%["#P1"]) \n\t" \
"ulw %[temp5], "#B"(%["#P1"]) \n\t" \
"ulw %[temp6], "#C"(%["#P1"]) \n\t" \
"ulw %[temp7], "#D"(%["#P1"]) \n\t" \
"addu %[temp4], %[temp4], %[temp0] \n\t" \
"addu %[temp5], %[temp5], %[temp1] \n\t" \
"addu %[temp6], %[temp6], %[temp2] \n\t" \
"addu %[temp7], %[temp7], %[temp3] \n\t" \
"addiu %["#P0"], %["#P0"], 16 \n\t" \
".if "#E" == 1 \n\t" \
"addiu %["#P1"], %["#P1"], 16 \n\t" \
".endif \n\t" \
"usw %[temp4], "#A"(%["#P2"]) \n\t" \
"usw %[temp5], "#B"(%["#P2"]) \n\t" \
"usw %[temp6], "#C"(%["#P2"]) \n\t" \
"usw %[temp7], "#D"(%["#P2"]) \n\t" \
"addiu %["#P2"], %["#P2"], 16 \n\t" \
"bne %["#P0"], %[LoopEnd], 1b \n\t" \
".set pop \n\t" \
#define ASM_END_COMMON_0 \
: [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), \
[temp2]"=&r"(temp2), [temp3]"=&r"(temp3), \
[temp4]"=&r"(temp4), [temp5]"=&r"(temp5), \
[temp6]"=&r"(temp6), [temp7]"=&r"(temp7), \
[pa]"+r"(pa), [pout]"+r"(pout)
#define ASM_END_COMMON_1 \
: [LoopEnd]"r"(LoopEnd) \
: "memory", "at" \
);
#define ASM_END_0 \
ASM_END_COMMON_0 \
, [pb]"+r"(pb) \
ASM_END_COMMON_1
#define ASM_END_1 \
ASM_END_COMMON_0 \
ASM_END_COMMON_1
#define ADD_VECTOR(A, B, OUT, SIZE, EXTRA_SIZE) do { \
const uint32_t* pa = (const uint32_t*)(A); \
const uint32_t* pb = (const uint32_t*)(B); \
uint32_t* pout = (uint32_t*)(OUT); \
const uint32_t* const LoopEnd = pa + (SIZE); \
assert((SIZE) % 4 == 0); \
ASM_START \
ADD_TO_OUT(0, 4, 8, 12, 1, pa, pb, pout) \
ASM_END_0 \
if ((EXTRA_SIZE) > 0) { \
const int last = (EXTRA_SIZE); \
int i; \
for (i = 0; i < last; ++i) pout[i] = pa[i] + pb[i]; \
} \
} while (0)
#define ADD_VECTOR_EQ(A, OUT, SIZE, EXTRA_SIZE) do { \
const uint32_t* pa = (const uint32_t*)(A); \
uint32_t* pout = (uint32_t*)(OUT); \
const uint32_t* const LoopEnd = pa + (SIZE); \
assert((SIZE) % 4 == 0); \
ASM_START \
ADD_TO_OUT(0, 4, 8, 12, 0, pa, pout, pout) \
ASM_END_1 \
if ((EXTRA_SIZE) > 0) { \
const int last = (EXTRA_SIZE); \
int i; \
for (i = 0; i < last; ++i) pout[i] += pa[i]; \
} \
} while (0)
static void HistogramAdd(const VP8LHistogram* const a,
const VP8LHistogram* const b,
VP8LHistogram* const out) {
uint32_t temp0, temp1, temp2, temp3, temp4, temp5, temp6, temp7;
const int extra_cache_size = VP8LHistogramNumCodes(a->palette_code_bits_)
- (NUM_LITERAL_CODES + NUM_LENGTH_CODES);
assert(a->palette_code_bits_ == b->palette_code_bits_);
if (b != out) {
ADD_VECTOR(a->literal_, b->literal_, out->literal_,
NUM_LITERAL_CODES + NUM_LENGTH_CODES, extra_cache_size);
ADD_VECTOR(a->distance_, b->distance_, out->distance_,
NUM_DISTANCE_CODES, 0);
ADD_VECTOR(a->red_, b->red_, out->red_, NUM_LITERAL_CODES, 0);
ADD_VECTOR(a->blue_, b->blue_, out->blue_, NUM_LITERAL_CODES, 0);
ADD_VECTOR(a->alpha_, b->alpha_, out->alpha_, NUM_LITERAL_CODES, 0);
} else {
ADD_VECTOR_EQ(a->literal_, out->literal_,
NUM_LITERAL_CODES + NUM_LENGTH_CODES, extra_cache_size);
ADD_VECTOR_EQ(a->distance_, out->distance_, NUM_DISTANCE_CODES, 0);
ADD_VECTOR_EQ(a->red_, out->red_, NUM_LITERAL_CODES, 0);
ADD_VECTOR_EQ(a->blue_, out->blue_, NUM_LITERAL_CODES, 0);
ADD_VECTOR_EQ(a->alpha_, out->alpha_, NUM_LITERAL_CODES, 0);
}
}
#undef ADD_VECTOR_EQ
#undef ADD_VECTOR
#undef ASM_END_1
#undef ASM_END_0
#undef ASM_END_COMMON_1
#undef ASM_END_COMMON_0
#undef ADD_TO_OUT
#undef ASM_START
#endif // WEBP_USE_MIPS32
//------------------------------------------------------------------------------
// Entry point
extern void VP8LDspInitMIPS32(void);
void VP8LDspInitMIPS32(void) {
#if defined(WEBP_USE_MIPS32)
VP8LFastSLog2Slow = FastSLog2Slow;
VP8LFastLog2Slow = FastLog2Slow;
VP8LExtraCost = ExtraCost;
VP8LExtraCostCombined = ExtraCostCombined;
VP8LHuffmanCostCount = HuffmanCostCount;
VP8LHuffmanCostCombinedCount = HuffmanCostCombinedCount;
VP8LHistogramAdd = HistogramAdd;
#endif // WEBP_USE_MIPS32
}

332
src/dsp/lossless_neon.c Normal file
View File

@ -0,0 +1,332 @@
// 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.
// -----------------------------------------------------------------------------
//
// NEON variant of methods for lossless decoder
//
// Author: Skal (pascal.massimino@gmail.com)
#include "./dsp.h"
#if defined(WEBP_USE_NEON)
#include <arm_neon.h>
#include "./lossless.h"
#include "./neon.h"
//------------------------------------------------------------------------------
// Colorspace conversion functions
#if !defined(WORK_AROUND_GCC)
// gcc 4.6.0 had some trouble (NDK-r9) with this code. We only use it for
// gcc-4.8.x at least.
static void ConvertBGRAToRGBA(const uint32_t* src,
int num_pixels, uint8_t* dst) {
const uint32_t* const end = src + (num_pixels & ~15);
for (; src < end; src += 16) {
uint8x16x4_t pixel = vld4q_u8((uint8_t*)src);
// swap B and R. (VSWP d0,d2 has no intrinsics equivalent!)
const uint8x16_t tmp = pixel.val[0];
pixel.val[0] = pixel.val[2];
pixel.val[2] = tmp;
vst4q_u8(dst, pixel);
dst += 64;
}
VP8LConvertBGRAToRGBA_C(src, num_pixels & 15, dst); // left-overs
}
static void ConvertBGRAToBGR(const uint32_t* src,
int num_pixels, uint8_t* dst) {
const uint32_t* const end = src + (num_pixels & ~15);
for (; src < end; src += 16) {
const uint8x16x4_t pixel = vld4q_u8((uint8_t*)src);
const uint8x16x3_t tmp = { { pixel.val[0], pixel.val[1], pixel.val[2] } };
vst3q_u8(dst, tmp);
dst += 48;
}
VP8LConvertBGRAToBGR_C(src, num_pixels & 15, dst); // left-overs
}
static void ConvertBGRAToRGB(const uint32_t* src,
int num_pixels, uint8_t* dst) {
const uint32_t* const end = src + (num_pixels & ~15);
for (; src < end; src += 16) {
const uint8x16x4_t pixel = vld4q_u8((uint8_t*)src);
const uint8x16x3_t tmp = { { pixel.val[2], pixel.val[1], pixel.val[0] } };
vst3q_u8(dst, tmp);
dst += 48;
}
VP8LConvertBGRAToRGB_C(src, num_pixels & 15, dst); // left-overs
}
#else // WORK_AROUND_GCC
// gcc-4.6.0 fallback
static const uint8_t kRGBAShuffle[8] = { 2, 1, 0, 3, 6, 5, 4, 7 };
static void ConvertBGRAToRGBA(const uint32_t* src,
int num_pixels, uint8_t* dst) {
const uint32_t* const end = src + (num_pixels & ~1);
const uint8x8_t shuffle = vld1_u8(kRGBAShuffle);
for (; src < end; src += 2) {
const uint8x8_t pixels = vld1_u8((uint8_t*)src);
vst1_u8(dst, vtbl1_u8(pixels, shuffle));
dst += 8;
}
VP8LConvertBGRAToRGBA_C(src, num_pixels & 1, dst); // left-overs
}
static const uint8_t kBGRShuffle[3][8] = {
{ 0, 1, 2, 4, 5, 6, 8, 9 },
{ 10, 12, 13, 14, 16, 17, 18, 20 },
{ 21, 22, 24, 25, 26, 28, 29, 30 }
};
static void ConvertBGRAToBGR(const uint32_t* src,
int num_pixels, uint8_t* dst) {
const uint32_t* const end = src + (num_pixels & ~7);
const uint8x8_t shuffle0 = vld1_u8(kBGRShuffle[0]);
const uint8x8_t shuffle1 = vld1_u8(kBGRShuffle[1]);
const uint8x8_t shuffle2 = vld1_u8(kBGRShuffle[2]);
for (; src < end; src += 8) {
uint8x8x4_t pixels;
INIT_VECTOR4(pixels,
vld1_u8((const uint8_t*)(src + 0)),
vld1_u8((const uint8_t*)(src + 2)),
vld1_u8((const uint8_t*)(src + 4)),
vld1_u8((const uint8_t*)(src + 6)));
vst1_u8(dst + 0, vtbl4_u8(pixels, shuffle0));
vst1_u8(dst + 8, vtbl4_u8(pixels, shuffle1));
vst1_u8(dst + 16, vtbl4_u8(pixels, shuffle2));
dst += 8 * 3;
}
VP8LConvertBGRAToBGR_C(src, num_pixels & 7, dst); // left-overs
}
static const uint8_t kRGBShuffle[3][8] = {
{ 2, 1, 0, 6, 5, 4, 10, 9 },
{ 8, 14, 13, 12, 18, 17, 16, 22 },
{ 21, 20, 26, 25, 24, 30, 29, 28 }
};
static void ConvertBGRAToRGB(const uint32_t* src,
int num_pixels, uint8_t* dst) {
const uint32_t* const end = src + (num_pixels & ~7);
const uint8x8_t shuffle0 = vld1_u8(kRGBShuffle[0]);
const uint8x8_t shuffle1 = vld1_u8(kRGBShuffle[1]);
const uint8x8_t shuffle2 = vld1_u8(kRGBShuffle[2]);
for (; src < end; src += 8) {
uint8x8x4_t pixels;
INIT_VECTOR4(pixels,
vld1_u8((const uint8_t*)(src + 0)),
vld1_u8((const uint8_t*)(src + 2)),
vld1_u8((const uint8_t*)(src + 4)),
vld1_u8((const uint8_t*)(src + 6)));
vst1_u8(dst + 0, vtbl4_u8(pixels, shuffle0));
vst1_u8(dst + 8, vtbl4_u8(pixels, shuffle1));
vst1_u8(dst + 16, vtbl4_u8(pixels, shuffle2));
dst += 8 * 3;
}
VP8LConvertBGRAToRGB_C(src, num_pixels & 7, dst); // left-overs
}
#endif // !WORK_AROUND_GCC
//------------------------------------------------------------------------------
#ifdef USE_INTRINSICS
static WEBP_INLINE uint32_t Average2(const uint32_t* const a,
const uint32_t* const b) {
const uint8x8_t a0 = vreinterpret_u8_u64(vcreate_u64(*a));
const uint8x8_t b0 = vreinterpret_u8_u64(vcreate_u64(*b));
const uint8x8_t avg = vhadd_u8(a0, b0);
return vget_lane_u32(vreinterpret_u32_u8(avg), 0);
}
static WEBP_INLINE uint32_t Average3(const uint32_t* const a,
const uint32_t* const b,
const uint32_t* const c) {
const uint8x8_t a0 = vreinterpret_u8_u64(vcreate_u64(*a));
const uint8x8_t b0 = vreinterpret_u8_u64(vcreate_u64(*b));
const uint8x8_t c0 = vreinterpret_u8_u64(vcreate_u64(*c));
const uint8x8_t avg1 = vhadd_u8(a0, c0);
const uint8x8_t avg2 = vhadd_u8(avg1, b0);
return vget_lane_u32(vreinterpret_u32_u8(avg2), 0);
}
static WEBP_INLINE uint32_t Average4(const uint32_t* const a,
const uint32_t* const b,
const uint32_t* const c,
const uint32_t* const d) {
const uint8x8_t a0 = vreinterpret_u8_u64(vcreate_u64(*a));
const uint8x8_t b0 = vreinterpret_u8_u64(vcreate_u64(*b));
const uint8x8_t c0 = vreinterpret_u8_u64(vcreate_u64(*c));
const uint8x8_t d0 = vreinterpret_u8_u64(vcreate_u64(*d));
const uint8x8_t avg1 = vhadd_u8(a0, b0);
const uint8x8_t avg2 = vhadd_u8(c0, d0);
const uint8x8_t avg3 = vhadd_u8(avg1, avg2);
return vget_lane_u32(vreinterpret_u32_u8(avg3), 0);
}
static uint32_t Predictor5(uint32_t left, const uint32_t* const top) {
return Average3(&left, top + 0, top + 1);
}
static uint32_t Predictor6(uint32_t left, const uint32_t* const top) {
return Average2(&left, top - 1);
}
static uint32_t Predictor7(uint32_t left, const uint32_t* const top) {
return Average2(&left, top + 0);
}
static uint32_t Predictor8(uint32_t left, const uint32_t* const top) {
(void)left;
return Average2(top - 1, top + 0);
}
static uint32_t Predictor9(uint32_t left, const uint32_t* const top) {
(void)left;
return Average2(top + 0, top + 1);
}
static uint32_t Predictor10(uint32_t left, const uint32_t* const top) {
return Average4(&left, top - 1, top + 0, top + 1);
}
//------------------------------------------------------------------------------
static WEBP_INLINE uint32_t Select(const uint32_t* const c0,
const uint32_t* const c1,
const uint32_t* const c2) {
const uint8x8_t p0 = vreinterpret_u8_u64(vcreate_u64(*c0));
const uint8x8_t p1 = vreinterpret_u8_u64(vcreate_u64(*c1));
const uint8x8_t p2 = vreinterpret_u8_u64(vcreate_u64(*c2));
const uint8x8_t bc = vabd_u8(p1, p2); // |b-c|
const uint8x8_t ac = vabd_u8(p0, p2); // |a-c|
const int16x4_t sum_bc = vreinterpret_s16_u16(vpaddl_u8(bc));
const int16x4_t sum_ac = vreinterpret_s16_u16(vpaddl_u8(ac));
const int32x2_t diff = vpaddl_s16(vsub_s16(sum_bc, sum_ac));
const int32_t pa_minus_pb = vget_lane_s32(diff, 0);
return (pa_minus_pb <= 0) ? *c0 : *c1;
}
static uint32_t Predictor11(uint32_t left, const uint32_t* const top) {
return Select(top + 0, &left, top - 1);
}
static WEBP_INLINE uint32_t ClampedAddSubtractFull(const uint32_t* const c0,
const uint32_t* const c1,
const uint32_t* const c2) {
const uint8x8_t p0 = vreinterpret_u8_u64(vcreate_u64(*c0));
const uint8x8_t p1 = vreinterpret_u8_u64(vcreate_u64(*c1));
const uint8x8_t p2 = vreinterpret_u8_u64(vcreate_u64(*c2));
const uint16x8_t sum0 = vaddl_u8(p0, p1); // add and widen
const uint16x8_t sum1 = vqsubq_u16(sum0, vmovl_u8(p2)); // widen and subtract
const uint8x8_t out = vqmovn_u16(sum1); // narrow and clamp
return vget_lane_u32(vreinterpret_u32_u8(out), 0);
}
static uint32_t Predictor12(uint32_t left, const uint32_t* const top) {
return ClampedAddSubtractFull(&left, top + 0, top - 1);
}
static WEBP_INLINE uint32_t ClampedAddSubtractHalf(const uint32_t* const c0,
const uint32_t* const c1,
const uint32_t* const c2) {
const uint8x8_t p0 = vreinterpret_u8_u64(vcreate_u64(*c0));
const uint8x8_t p1 = vreinterpret_u8_u64(vcreate_u64(*c1));
const uint8x8_t p2 = vreinterpret_u8_u64(vcreate_u64(*c2));
const uint8x8_t avg = vhadd_u8(p0, p1); // Average(c0,c1)
const uint8x8_t ab = vshr_n_u8(vqsub_u8(avg, p2), 1); // (a-b)>>1 saturated
const uint8x8_t ba = vshr_n_u8(vqsub_u8(p2, avg), 1); // (b-a)>>1 saturated
const uint8x8_t out = vqsub_u8(vqadd_u8(avg, ab), ba);
return vget_lane_u32(vreinterpret_u32_u8(out), 0);
}
static uint32_t Predictor13(uint32_t left, const uint32_t* const top) {
return ClampedAddSubtractHalf(&left, top + 0, top - 1);
}
//------------------------------------------------------------------------------
// Subtract-Green Transform
// vtbl? are unavailable in iOS/arm64 builds.
#if !defined(__aarch64__)
// 255 = byte will be zero'd
static const uint8_t kGreenShuffle[8] = { 1, 255, 1, 255, 5, 255, 5, 255 };
static void SubtractGreenFromBlueAndRed(uint32_t* argb_data, int num_pixels) {
const uint32_t* const end = argb_data + (num_pixels & ~3);
const uint8x8_t shuffle = vld1_u8(kGreenShuffle);
for (; argb_data < end; argb_data += 4) {
const uint8x16_t argb = vld1q_u8((uint8_t*)argb_data);
const uint8x16_t greens =
vcombine_u8(vtbl1_u8(vget_low_u8(argb), shuffle),
vtbl1_u8(vget_high_u8(argb), shuffle));
vst1q_u8((uint8_t*)argb_data, vsubq_u8(argb, greens));
}
// fallthrough and finish off with plain-C
VP8LSubtractGreenFromBlueAndRed_C(argb_data, num_pixels & 3);
}
static void AddGreenToBlueAndRed(uint32_t* argb_data, int num_pixels) {
const uint32_t* const end = argb_data + (num_pixels & ~3);
const uint8x8_t shuffle = vld1_u8(kGreenShuffle);
for (; argb_data < end; argb_data += 4) {
const uint8x16_t argb = vld1q_u8((uint8_t*)argb_data);
const uint8x16_t greens =
vcombine_u8(vtbl1_u8(vget_low_u8(argb), shuffle),
vtbl1_u8(vget_high_u8(argb), shuffle));
vst1q_u8((uint8_t*)argb_data, vaddq_u8(argb, greens));
}
// fallthrough and finish off with plain-C
VP8LAddGreenToBlueAndRed_C(argb_data, num_pixels & 3);
}
#endif // !__aarch64__
#endif // USE_INTRINSICS
#endif // WEBP_USE_NEON
//------------------------------------------------------------------------------
extern void VP8LDspInitNEON(void);
void VP8LDspInitNEON(void) {
#if defined(WEBP_USE_NEON)
VP8LConvertBGRAToRGBA = ConvertBGRAToRGBA;
VP8LConvertBGRAToBGR = ConvertBGRAToBGR;
VP8LConvertBGRAToRGB = ConvertBGRAToRGB;
#ifdef USE_INTRINSICS
VP8LPredictors[5] = Predictor5;
VP8LPredictors[6] = Predictor6;
VP8LPredictors[7] = Predictor7;
VP8LPredictors[8] = Predictor8;
VP8LPredictors[9] = Predictor9;
VP8LPredictors[10] = Predictor10;
VP8LPredictors[11] = Predictor11;
VP8LPredictors[12] = Predictor12;
VP8LPredictors[13] = Predictor13;
#if !defined(__aarch64__)
VP8LSubtractGreenFromBlueAndRed = SubtractGreenFromBlueAndRed;
VP8LAddGreenToBlueAndRed = AddGreenToBlueAndRed;
#endif
#endif
#endif // WEBP_USE_NEON
}
//------------------------------------------------------------------------------

535
src/dsp/lossless_sse2.c Normal file
View File

@ -0,0 +1,535 @@
// 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.
// -----------------------------------------------------------------------------
//
// SSE2 variant of methods for lossless decoder
//
// Author: Skal (pascal.massimino@gmail.com)
#include "./dsp.h"
#include <assert.h>
#if defined(WEBP_USE_SSE2)
#include <emmintrin.h>
#include "./lossless.h"
//------------------------------------------------------------------------------
// Predictor Transform
static WEBP_INLINE uint32_t ClampedAddSubtractFull(uint32_t c0, uint32_t c1,
uint32_t c2) {
const __m128i zero = _mm_setzero_si128();
const __m128i C0 = _mm_unpacklo_epi8(_mm_cvtsi32_si128(c0), zero);
const __m128i C1 = _mm_unpacklo_epi8(_mm_cvtsi32_si128(c1), zero);
const __m128i C2 = _mm_unpacklo_epi8(_mm_cvtsi32_si128(c2), zero);
const __m128i V1 = _mm_add_epi16(C0, C1);
const __m128i V2 = _mm_sub_epi16(V1, C2);
const __m128i b = _mm_packus_epi16(V2, V2);
const uint32_t output = _mm_cvtsi128_si32(b);
return output;
}
static WEBP_INLINE uint32_t ClampedAddSubtractHalf(uint32_t c0, uint32_t c1,
uint32_t c2) {
const __m128i zero = _mm_setzero_si128();
const __m128i C0 = _mm_unpacklo_epi8(_mm_cvtsi32_si128(c0), zero);
const __m128i C1 = _mm_unpacklo_epi8(_mm_cvtsi32_si128(c1), zero);
const __m128i B0 = _mm_unpacklo_epi8(_mm_cvtsi32_si128(c2), zero);
const __m128i avg = _mm_add_epi16(C1, C0);
const __m128i A0 = _mm_srli_epi16(avg, 1);
const __m128i A1 = _mm_sub_epi16(A0, B0);
const __m128i BgtA = _mm_cmpgt_epi16(B0, A0);
const __m128i A2 = _mm_sub_epi16(A1, BgtA);
const __m128i A3 = _mm_srai_epi16(A2, 1);
const __m128i A4 = _mm_add_epi16(A0, A3);
const __m128i A5 = _mm_packus_epi16(A4, A4);
const uint32_t output = _mm_cvtsi128_si32(A5);
return output;
}
static WEBP_INLINE uint32_t Select(uint32_t a, uint32_t b, uint32_t c) {
int pa_minus_pb;
const __m128i zero = _mm_setzero_si128();
const __m128i A0 = _mm_cvtsi32_si128(a);
const __m128i B0 = _mm_cvtsi32_si128(b);
const __m128i C0 = _mm_cvtsi32_si128(c);
const __m128i AC0 = _mm_subs_epu8(A0, C0);
const __m128i CA0 = _mm_subs_epu8(C0, A0);
const __m128i BC0 = _mm_subs_epu8(B0, C0);
const __m128i CB0 = _mm_subs_epu8(C0, B0);
const __m128i AC = _mm_or_si128(AC0, CA0);
const __m128i BC = _mm_or_si128(BC0, CB0);
const __m128i pa = _mm_unpacklo_epi8(AC, zero); // |a - c|
const __m128i pb = _mm_unpacklo_epi8(BC, zero); // |b - c|
const __m128i diff = _mm_sub_epi16(pb, pa);
{
int16_t out[8];
_mm_storeu_si128((__m128i*)out, diff);
pa_minus_pb = out[0] + out[1] + out[2] + out[3];
}
return (pa_minus_pb <= 0) ? a : b;
}
static WEBP_INLINE __m128i Average2_128i(uint32_t a0, uint32_t a1) {
const __m128i zero = _mm_setzero_si128();
const __m128i A0 = _mm_unpacklo_epi8(_mm_cvtsi32_si128(a0), zero);
const __m128i A1 = _mm_unpacklo_epi8(_mm_cvtsi32_si128(a1), zero);
const __m128i sum = _mm_add_epi16(A1, A0);
const __m128i avg = _mm_srli_epi16(sum, 1);
return avg;
}
static WEBP_INLINE uint32_t Average2(uint32_t a0, uint32_t a1) {
const __m128i avg = Average2_128i(a0, a1);
const __m128i A2 = _mm_packus_epi16(avg, avg);
const uint32_t output = _mm_cvtsi128_si32(A2);
return output;
}
static WEBP_INLINE uint32_t Average3(uint32_t a0, uint32_t a1, uint32_t a2) {
const __m128i zero = _mm_setzero_si128();
const __m128i avg1 = Average2_128i(a0, a2);
const __m128i A1 = _mm_unpacklo_epi8(_mm_cvtsi32_si128(a1), zero);
const __m128i sum = _mm_add_epi16(avg1, A1);
const __m128i avg2 = _mm_srli_epi16(sum, 1);
const __m128i A2 = _mm_packus_epi16(avg2, avg2);
const uint32_t output = _mm_cvtsi128_si32(A2);
return output;
}
static WEBP_INLINE uint32_t Average4(uint32_t a0, uint32_t a1,
uint32_t a2, uint32_t a3) {
const __m128i avg1 = Average2_128i(a0, a1);
const __m128i avg2 = Average2_128i(a2, a3);
const __m128i sum = _mm_add_epi16(avg2, avg1);
const __m128i avg3 = _mm_srli_epi16(sum, 1);
const __m128i A0 = _mm_packus_epi16(avg3, avg3);
const uint32_t output = _mm_cvtsi128_si32(A0);
return output;
}
static uint32_t Predictor5(uint32_t left, const uint32_t* const top) {
const uint32_t pred = Average3(left, top[0], top[1]);
return pred;
}
static uint32_t Predictor6(uint32_t left, const uint32_t* const top) {
const uint32_t pred = Average2(left, top[-1]);
return pred;
}
static uint32_t Predictor7(uint32_t left, const uint32_t* const top) {
const uint32_t pred = Average2(left, top[0]);
return pred;
}
static uint32_t Predictor8(uint32_t left, const uint32_t* const top) {
const uint32_t pred = Average2(top[-1], top[0]);
(void)left;
return pred;
}
static uint32_t Predictor9(uint32_t left, const uint32_t* const top) {
const uint32_t pred = Average2(top[0], top[1]);
(void)left;
return pred;
}
static uint32_t Predictor10(uint32_t left, const uint32_t* const top) {
const uint32_t pred = Average4(left, top[-1], top[0], top[1]);
return pred;
}
static uint32_t Predictor11(uint32_t left, const uint32_t* const top) {
const uint32_t pred = Select(top[0], left, top[-1]);
return pred;
}
static uint32_t Predictor12(uint32_t left, const uint32_t* const top) {
const uint32_t pred = ClampedAddSubtractFull(left, top[0], top[-1]);
return pred;
}
static uint32_t Predictor13(uint32_t left, const uint32_t* const top) {
const uint32_t pred = ClampedAddSubtractHalf(left, top[0], top[-1]);
return pred;
}
//------------------------------------------------------------------------------
// Subtract-Green Transform
static void SubtractGreenFromBlueAndRed(uint32_t* argb_data, int num_pixels) {
const __m128i mask = _mm_set1_epi32(0x0000ff00);
int i;
for (i = 0; i + 4 <= num_pixels; i += 4) {
const __m128i in = _mm_loadu_si128((__m128i*)&argb_data[i]);
const __m128i in_00g0 = _mm_and_si128(in, mask); // 00g0|00g0|...
const __m128i in_0g00 = _mm_slli_epi32(in_00g0, 8); // 0g00|0g00|...
const __m128i in_000g = _mm_srli_epi32(in_00g0, 8); // 000g|000g|...
const __m128i in_0g0g = _mm_or_si128(in_0g00, in_000g);
const __m128i out = _mm_sub_epi8(in, in_0g0g);
_mm_storeu_si128((__m128i*)&argb_data[i], out);
}
// fallthrough and finish off with plain-C
VP8LSubtractGreenFromBlueAndRed_C(argb_data + i, num_pixels - i);
}
static void AddGreenToBlueAndRed(uint32_t* argb_data, int num_pixels) {
const __m128i mask = _mm_set1_epi32(0x0000ff00);
int i;
for (i = 0; i + 4 <= num_pixels; i += 4) {
const __m128i in = _mm_loadu_si128((__m128i*)&argb_data[i]);
const __m128i in_00g0 = _mm_and_si128(in, mask); // 00g0|00g0|...
const __m128i in_0g00 = _mm_slli_epi32(in_00g0, 8); // 0g00|0g00|...
const __m128i in_000g = _mm_srli_epi32(in_00g0, 8); // 000g|000g|...
const __m128i in_0g0g = _mm_or_si128(in_0g00, in_000g);
const __m128i out = _mm_add_epi8(in, in_0g0g);
_mm_storeu_si128((__m128i*)&argb_data[i], out);
}
// fallthrough and finish off with plain-C
VP8LAddGreenToBlueAndRed_C(argb_data + i, num_pixels - i);
}
//------------------------------------------------------------------------------
// Color Transform
static WEBP_INLINE __m128i ColorTransformDelta(__m128i color_pred,
__m128i color) {
// We simulate signed 8-bit multiplication as:
// * Left shift the two (8-bit) numbers by 8 bits,
// * Perform a 16-bit signed multiplication and retain the higher 16-bits.
const __m128i color_pred_shifted = _mm_slli_epi32(color_pred, 8);
const __m128i color_shifted = _mm_slli_epi32(color, 8);
// Note: This performs multiplication on 8 packed 16-bit numbers, 4 of which
// happen to be zeroes.
const __m128i signed_mult =
_mm_mulhi_epi16(color_pred_shifted, color_shifted);
return _mm_srli_epi32(signed_mult, 5);
}
static WEBP_INLINE void TransformColor(const VP8LMultipliers* const m,
uint32_t* argb_data,
int num_pixels) {
const __m128i g_to_r = _mm_set1_epi32(m->green_to_red_); // multipliers
const __m128i g_to_b = _mm_set1_epi32(m->green_to_blue_);
const __m128i r_to_b = _mm_set1_epi32(m->red_to_blue_);
int i;
for (i = 0; i + 4 <= num_pixels; i += 4) {
const __m128i in = _mm_loadu_si128((__m128i*)&argb_data[i]);
const __m128i alpha_green_mask = _mm_set1_epi32(0xff00ff00); // masks
const __m128i red_mask = _mm_set1_epi32(0x00ff0000);
const __m128i green_mask = _mm_set1_epi32(0x0000ff00);
const __m128i lower_8bit_mask = _mm_set1_epi32(0x000000ff);
const __m128i ag = _mm_and_si128(in, alpha_green_mask); // alpha, green
const __m128i r = _mm_srli_epi32(_mm_and_si128(in, red_mask), 16);
const __m128i g = _mm_srli_epi32(_mm_and_si128(in, green_mask), 8);
const __m128i b = in;
const __m128i r_delta = ColorTransformDelta(g_to_r, g); // red
const __m128i r_new =
_mm_and_si128(_mm_sub_epi32(r, r_delta), lower_8bit_mask);
const __m128i r_new_shifted = _mm_slli_epi32(r_new, 16);
const __m128i b_delta_1 = ColorTransformDelta(g_to_b, g); // blue
const __m128i b_delta_2 = ColorTransformDelta(r_to_b, r);
const __m128i b_delta = _mm_add_epi32(b_delta_1, b_delta_2);
const __m128i b_new =
_mm_and_si128(_mm_sub_epi32(b, b_delta), lower_8bit_mask);
const __m128i out = _mm_or_si128(_mm_or_si128(ag, r_new_shifted), b_new);
_mm_storeu_si128((__m128i*)&argb_data[i], out);
}
// Fall-back to C-version for left-overs.
VP8LTransformColor_C(m, argb_data + i, num_pixels - i);
}
static WEBP_INLINE void TransformColorInverse(const VP8LMultipliers* const m,
uint32_t* argb_data,
int num_pixels) {
const __m128i g_to_r = _mm_set1_epi32(m->green_to_red_); // multipliers
const __m128i g_to_b = _mm_set1_epi32(m->green_to_blue_);
const __m128i r_to_b = _mm_set1_epi32(m->red_to_blue_);
int i;
for (i = 0; i + 4 <= num_pixels; i += 4) {
const __m128i in = _mm_loadu_si128((__m128i*)&argb_data[i]);
const __m128i alpha_green_mask = _mm_set1_epi32(0xff00ff00); // masks
const __m128i red_mask = _mm_set1_epi32(0x00ff0000);
const __m128i green_mask = _mm_set1_epi32(0x0000ff00);
const __m128i lower_8bit_mask = _mm_set1_epi32(0x000000ff);
const __m128i ag = _mm_and_si128(in, alpha_green_mask); // alpha, green
const __m128i r = _mm_srli_epi32(_mm_and_si128(in, red_mask), 16);
const __m128i g = _mm_srli_epi32(_mm_and_si128(in, green_mask), 8);
const __m128i b = in;
const __m128i r_delta = ColorTransformDelta(g_to_r, g); // red
const __m128i r_new =
_mm_and_si128(_mm_add_epi32(r, r_delta), lower_8bit_mask);
const __m128i r_new_shifted = _mm_slli_epi32(r_new, 16);
const __m128i b_delta_1 = ColorTransformDelta(g_to_b, g); // blue
const __m128i b_delta_2 = ColorTransformDelta(r_to_b, r_new);
const __m128i b_delta = _mm_add_epi32(b_delta_1, b_delta_2);
const __m128i b_new =
_mm_and_si128(_mm_add_epi32(b, b_delta), lower_8bit_mask);
const __m128i out = _mm_or_si128(_mm_or_si128(ag, r_new_shifted), b_new);
_mm_storeu_si128((__m128i*)&argb_data[i], out);
}
// Fall-back to C-version for left-overs.
VP8LTransformColorInverse_C(m, argb_data + i, num_pixels - i);
}
//------------------------------------------------------------------------------
// Color-space conversion functions
static void ConvertBGRAToRGBA(const uint32_t* src,
int num_pixels, uint8_t* dst) {
const __m128i* in = (const __m128i*)src;
__m128i* out = (__m128i*)dst;
while (num_pixels >= 8) {
const __m128i bgra0 = _mm_loadu_si128(in++); // bgra0|bgra1|bgra2|bgra3
const __m128i bgra4 = _mm_loadu_si128(in++); // bgra4|bgra5|bgra6|bgra7
const __m128i v0l = _mm_unpacklo_epi8(bgra0, bgra4); // b0b4g0g4r0r4a0a4...
const __m128i v0h = _mm_unpackhi_epi8(bgra0, bgra4); // b2b6g2g6r2r6a2a6...
const __m128i v1l = _mm_unpacklo_epi8(v0l, v0h); // b0b2b4b6g0g2g4g6...
const __m128i v1h = _mm_unpackhi_epi8(v0l, v0h); // b1b3b5b7g1g3g5g7...
const __m128i v2l = _mm_unpacklo_epi8(v1l, v1h); // b0...b7 | g0...g7
const __m128i v2h = _mm_unpackhi_epi8(v1l, v1h); // r0...r7 | a0...a7
const __m128i ga0 = _mm_unpackhi_epi64(v2l, v2h); // g0...g7 | a0...a7
const __m128i rb0 = _mm_unpacklo_epi64(v2h, v2l); // r0...r7 | b0...b7
const __m128i rg0 = _mm_unpacklo_epi8(rb0, ga0); // r0g0r1g1 ... r6g6r7g7
const __m128i ba0 = _mm_unpackhi_epi8(rb0, ga0); // b0a0b1a1 ... b6a6b7a7
const __m128i rgba0 = _mm_unpacklo_epi16(rg0, ba0); // rgba0|rgba1...
const __m128i rgba4 = _mm_unpackhi_epi16(rg0, ba0); // rgba4|rgba5...
_mm_storeu_si128(out++, rgba0);
_mm_storeu_si128(out++, rgba4);
num_pixels -= 8;
}
// left-overs
VP8LConvertBGRAToRGBA_C((const uint32_t*)in, num_pixels, (uint8_t*)out);
}
static void ConvertBGRAToRGBA4444(const uint32_t* src,
int num_pixels, uint8_t* dst) {
const __m128i mask_0x0f = _mm_set1_epi8(0x0f);
const __m128i mask_0xf0 = _mm_set1_epi8(0xf0);
const __m128i* in = (const __m128i*)src;
__m128i* out = (__m128i*)dst;
while (num_pixels >= 8) {
const __m128i bgra0 = _mm_loadu_si128(in++); // bgra0|bgra1|bgra2|bgra3
const __m128i bgra4 = _mm_loadu_si128(in++); // bgra4|bgra5|bgra6|bgra7
const __m128i v0l = _mm_unpacklo_epi8(bgra0, bgra4); // b0b4g0g4r0r4a0a4...
const __m128i v0h = _mm_unpackhi_epi8(bgra0, bgra4); // b2b6g2g6r2r6a2a6...
const __m128i v1l = _mm_unpacklo_epi8(v0l, v0h); // b0b2b4b6g0g2g4g6...
const __m128i v1h = _mm_unpackhi_epi8(v0l, v0h); // b1b3b5b7g1g3g5g7...
const __m128i v2l = _mm_unpacklo_epi8(v1l, v1h); // b0...b7 | g0...g7
const __m128i v2h = _mm_unpackhi_epi8(v1l, v1h); // r0...r7 | a0...a7
const __m128i ga0 = _mm_unpackhi_epi64(v2l, v2h); // g0...g7 | a0...a7
const __m128i rb0 = _mm_unpacklo_epi64(v2h, v2l); // r0...r7 | b0...b7
const __m128i ga1 = _mm_srli_epi16(ga0, 4); // g0-|g1-|...|a6-|a7-
const __m128i rb1 = _mm_and_si128(rb0, mask_0xf0); // -r0|-r1|...|-b6|-a7
const __m128i ga2 = _mm_and_si128(ga1, mask_0x0f); // g0-|g1-|...|a6-|a7-
const __m128i rgba0 = _mm_or_si128(ga2, rb1); // rg0..rg7 | ba0..ba7
const __m128i rgba1 = _mm_srli_si128(rgba0, 8); // ba0..ba7 | 0
#ifdef WEBP_SWAP_16BIT_CSP
const __m128i rgba = _mm_unpacklo_epi8(rgba1, rgba0); // barg0...barg7
#else
const __m128i rgba = _mm_unpacklo_epi8(rgba0, rgba1); // rgba0...rgba7
#endif
_mm_storeu_si128(out++, rgba);
num_pixels -= 8;
}
// left-overs
VP8LConvertBGRAToRGBA4444_C((const uint32_t*)in, num_pixels, (uint8_t*)out);
}
static void ConvertBGRAToRGB565(const uint32_t* src,
int num_pixels, uint8_t* dst) {
const __m128i mask_0xe0 = _mm_set1_epi8(0xe0);
const __m128i mask_0xf8 = _mm_set1_epi8(0xf8);
const __m128i mask_0x07 = _mm_set1_epi8(0x07);
const __m128i* in = (const __m128i*)src;
__m128i* out = (__m128i*)dst;
while (num_pixels >= 8) {
const __m128i bgra0 = _mm_loadu_si128(in++); // bgra0|bgra1|bgra2|bgra3
const __m128i bgra4 = _mm_loadu_si128(in++); // bgra4|bgra5|bgra6|bgra7
const __m128i v0l = _mm_unpacklo_epi8(bgra0, bgra4); // b0b4g0g4r0r4a0a4...
const __m128i v0h = _mm_unpackhi_epi8(bgra0, bgra4); // b2b6g2g6r2r6a2a6...
const __m128i v1l = _mm_unpacklo_epi8(v0l, v0h); // b0b2b4b6g0g2g4g6...
const __m128i v1h = _mm_unpackhi_epi8(v0l, v0h); // b1b3b5b7g1g3g5g7...
const __m128i v2l = _mm_unpacklo_epi8(v1l, v1h); // b0...b7 | g0...g7
const __m128i v2h = _mm_unpackhi_epi8(v1l, v1h); // r0...r7 | a0...a7
const __m128i ga0 = _mm_unpackhi_epi64(v2l, v2h); // g0...g7 | a0...a7
const __m128i rb0 = _mm_unpacklo_epi64(v2h, v2l); // r0...r7 | b0...b7
const __m128i rb1 = _mm_and_si128(rb0, mask_0xf8); // -r0..-r7|-b0..-b7
const __m128i g_lo1 = _mm_srli_epi16(ga0, 5);
const __m128i g_lo2 = _mm_and_si128(g_lo1, mask_0x07); // g0-...g7-|xx (3b)
const __m128i g_hi1 = _mm_slli_epi16(ga0, 3);
const __m128i g_hi2 = _mm_and_si128(g_hi1, mask_0xe0); // -g0...-g7|xx (3b)
const __m128i b0 = _mm_srli_si128(rb1, 8); // -b0...-b7|0
const __m128i rg1 = _mm_or_si128(rb1, g_lo2); // gr0...gr7|xx
const __m128i b1 = _mm_srli_epi16(b0, 3);
const __m128i gb1 = _mm_or_si128(b1, g_hi2); // bg0...bg7|xx
#ifdef WEBP_SWAP_16BIT_CSP
const __m128i rgba = _mm_unpacklo_epi8(gb1, rg1); // rggb0...rggb7
#else
const __m128i rgba = _mm_unpacklo_epi8(rg1, gb1); // bgrb0...bgrb7
#endif
_mm_storeu_si128(out++, rgba);
num_pixels -= 8;
}
// left-overs
VP8LConvertBGRAToRGB565_C((const uint32_t*)in, num_pixels, (uint8_t*)out);
}
static void ConvertBGRAToBGR(const uint32_t* src,
int num_pixels, uint8_t* dst) {
const __m128i mask_l = _mm_set_epi32(0, 0x00ffffff, 0, 0x00ffffff);
const __m128i mask_h = _mm_set_epi32(0x00ffffff, 0, 0x00ffffff, 0);
const __m128i* in = (const __m128i*)src;
const uint8_t* const end = dst + num_pixels * 3;
// the last storel_epi64 below writes 8 bytes starting at offset 18
while (dst + 26 <= end) {
const __m128i bgra0 = _mm_loadu_si128(in++); // bgra0|bgra1|bgra2|bgra3
const __m128i bgra4 = _mm_loadu_si128(in++); // bgra4|bgra5|bgra6|bgra7
const __m128i a0l = _mm_and_si128(bgra0, mask_l); // bgr0|0|bgr0|0
const __m128i a4l = _mm_and_si128(bgra4, mask_l); // bgr0|0|bgr0|0
const __m128i a0h = _mm_and_si128(bgra0, mask_h); // 0|bgr0|0|bgr0
const __m128i a4h = _mm_and_si128(bgra4, mask_h); // 0|bgr0|0|bgr0
const __m128i b0h = _mm_srli_epi64(a0h, 8); // 000b|gr00|000b|gr00
const __m128i b4h = _mm_srli_epi64(a4h, 8); // 000b|gr00|000b|gr00
const __m128i c0 = _mm_or_si128(a0l, b0h); // rgbrgb00|rgbrgb00
const __m128i c4 = _mm_or_si128(a4l, b4h); // rgbrgb00|rgbrgb00
const __m128i c2 = _mm_srli_si128(c0, 8);
const __m128i c6 = _mm_srli_si128(c4, 8);
_mm_storel_epi64((__m128i*)(dst + 0), c0);
_mm_storel_epi64((__m128i*)(dst + 6), c2);
_mm_storel_epi64((__m128i*)(dst + 12), c4);
_mm_storel_epi64((__m128i*)(dst + 18), c6);
dst += 24;
num_pixels -= 8;
}
// left-overs
VP8LConvertBGRAToBGR_C((const uint32_t*)in, num_pixels, dst);
}
//------------------------------------------------------------------------------
#define LINE_SIZE 16 // 8 or 16
static void AddVector(const uint32_t* a, const uint32_t* b, uint32_t* out,
int size) {
int i;
assert(size % LINE_SIZE == 0);
for (i = 0; i < size; i += LINE_SIZE) {
const __m128i a0 = _mm_loadu_si128((__m128i*)&a[i + 0]);
const __m128i a1 = _mm_loadu_si128((__m128i*)&a[i + 4]);
#if (LINE_SIZE == 16)
const __m128i a2 = _mm_loadu_si128((__m128i*)&a[i + 8]);
const __m128i a3 = _mm_loadu_si128((__m128i*)&a[i + 12]);
#endif
const __m128i b0 = _mm_loadu_si128((__m128i*)&b[i + 0]);
const __m128i b1 = _mm_loadu_si128((__m128i*)&b[i + 4]);
#if (LINE_SIZE == 16)
const __m128i b2 = _mm_loadu_si128((__m128i*)&b[i + 8]);
const __m128i b3 = _mm_loadu_si128((__m128i*)&b[i + 12]);
#endif
_mm_storeu_si128((__m128i*)&out[i + 0], _mm_add_epi32(a0, b0));
_mm_storeu_si128((__m128i*)&out[i + 4], _mm_add_epi32(a1, b1));
#if (LINE_SIZE == 16)
_mm_storeu_si128((__m128i*)&out[i + 8], _mm_add_epi32(a2, b2));
_mm_storeu_si128((__m128i*)&out[i + 12], _mm_add_epi32(a3, b3));
#endif
}
}
static void AddVectorEq(const uint32_t* a, uint32_t* out, int size) {
int i;
assert(size % LINE_SIZE == 0);
for (i = 0; i < size; i += LINE_SIZE) {
const __m128i a0 = _mm_loadu_si128((__m128i*)&a[i + 0]);
const __m128i a1 = _mm_loadu_si128((__m128i*)&a[i + 4]);
#if (LINE_SIZE == 16)
const __m128i a2 = _mm_loadu_si128((__m128i*)&a[i + 8]);
const __m128i a3 = _mm_loadu_si128((__m128i*)&a[i + 12]);
#endif
const __m128i b0 = _mm_loadu_si128((__m128i*)&out[i + 0]);
const __m128i b1 = _mm_loadu_si128((__m128i*)&out[i + 4]);
#if (LINE_SIZE == 16)
const __m128i b2 = _mm_loadu_si128((__m128i*)&out[i + 8]);
const __m128i b3 = _mm_loadu_si128((__m128i*)&out[i + 12]);
#endif
_mm_storeu_si128((__m128i*)&out[i + 0], _mm_add_epi32(a0, b0));
_mm_storeu_si128((__m128i*)&out[i + 4], _mm_add_epi32(a1, b1));
#if (LINE_SIZE == 16)
_mm_storeu_si128((__m128i*)&out[i + 8], _mm_add_epi32(a2, b2));
_mm_storeu_si128((__m128i*)&out[i + 12], _mm_add_epi32(a3, b3));
#endif
}
}
#undef LINE_SIZE
// Note we are adding uint32_t's as *signed* int32's (using _mm_add_epi32). But
// that's ok since the histogram values are less than 1<<28 (max picture size).
static void HistogramAdd(const VP8LHistogram* const a,
const VP8LHistogram* const b,
VP8LHistogram* const out) {
int i;
const int literal_size = VP8LHistogramNumCodes(a->palette_code_bits_);
assert(a->palette_code_bits_ == b->palette_code_bits_);
if (b != out) {
AddVector(a->literal_, b->literal_, out->literal_, NUM_LITERAL_CODES);
AddVector(a->red_, b->red_, out->red_, NUM_LITERAL_CODES);
AddVector(a->blue_, b->blue_, out->blue_, NUM_LITERAL_CODES);
AddVector(a->alpha_, b->alpha_, out->alpha_, NUM_LITERAL_CODES);
} else {
AddVectorEq(a->literal_, out->literal_, NUM_LITERAL_CODES);
AddVectorEq(a->red_, out->red_, NUM_LITERAL_CODES);
AddVectorEq(a->blue_, out->blue_, NUM_LITERAL_CODES);
AddVectorEq(a->alpha_, out->alpha_, NUM_LITERAL_CODES);
}
for (i = NUM_LITERAL_CODES; i < literal_size; ++i) {
out->literal_[i] = a->literal_[i] + b->literal_[i];
}
for (i = 0; i < NUM_DISTANCE_CODES; ++i) {
out->distance_[i] = a->distance_[i] + b->distance_[i];
}
}
#endif // WEBP_USE_SSE2
//------------------------------------------------------------------------------
extern void VP8LDspInitSSE2(void);
void VP8LDspInitSSE2(void) {
#if defined(WEBP_USE_SSE2)
VP8LPredictors[5] = Predictor5;
VP8LPredictors[6] = Predictor6;
VP8LPredictors[7] = Predictor7;
VP8LPredictors[8] = Predictor8;
VP8LPredictors[9] = Predictor9;
VP8LPredictors[10] = Predictor10;
VP8LPredictors[11] = Predictor11;
VP8LPredictors[12] = Predictor12;
VP8LPredictors[13] = Predictor13;
VP8LSubtractGreenFromBlueAndRed = SubtractGreenFromBlueAndRed;
VP8LAddGreenToBlueAndRed = AddGreenToBlueAndRed;
VP8LTransformColor = TransformColor;
VP8LTransformColorInverse = TransformColorInverse;
VP8LConvertBGRAToRGBA = ConvertBGRAToRGBA;
VP8LConvertBGRAToRGBA4444 = ConvertBGRAToRGBA4444;
VP8LConvertBGRAToRGB565 = ConvertBGRAToRGB565;
VP8LConvertBGRAToBGR = ConvertBGRAToBGR;
VP8LHistogramAdd = HistogramAdd;
#endif // WEBP_USE_SSE2
}
//------------------------------------------------------------------------------

82
src/dsp/neon.h Normal file
View File

@ -0,0 +1,82 @@
// 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.
// -----------------------------------------------------------------------------
//
// NEON common code.
#ifndef WEBP_DSP_NEON_H_
#define WEBP_DSP_NEON_H_
#include <arm_neon.h>
#include "./dsp.h"
// Right now, some intrinsics functions seem slower, so we disable them
// everywhere except aarch64 where the inline assembly is incompatible.
#if defined(__aarch64__)
#define USE_INTRINSICS // use intrinsics when possible
#endif
#define INIT_VECTOR2(v, a, b) do { \
v.val[0] = a; \
v.val[1] = b; \
} while (0)
#define INIT_VECTOR3(v, a, b, c) do { \
v.val[0] = a; \
v.val[1] = b; \
v.val[2] = c; \
} while (0)
#define INIT_VECTOR4(v, a, b, c, d) do { \
v.val[0] = a; \
v.val[1] = b; \
v.val[2] = c; \
v.val[3] = d; \
} while (0)
// if using intrinsics, this flag avoids some functions that make gcc-4.6.3
// crash ("internal compiler error: in immed_double_const, at emit-rtl.").
// (probably similar to gcc.gnu.org/bugzilla/show_bug.cgi?id=48183)
#if !(LOCAL_GCC_PREREQ(4,8) || defined(__aarch64__))
#define WORK_AROUND_GCC
#endif
static WEBP_INLINE int32x4x4_t Transpose4x4(const int32x4x4_t rows) {
uint64x2x2_t row01, row23;
row01.val[0] = vreinterpretq_u64_s32(rows.val[0]);
row01.val[1] = vreinterpretq_u64_s32(rows.val[1]);
row23.val[0] = vreinterpretq_u64_s32(rows.val[2]);
row23.val[1] = vreinterpretq_u64_s32(rows.val[3]);
// Transpose 64-bit values (there's no vswp equivalent)
{
const uint64x1_t row0h = vget_high_u64(row01.val[0]);
const uint64x1_t row2l = vget_low_u64(row23.val[0]);
const uint64x1_t row1h = vget_high_u64(row01.val[1]);
const uint64x1_t row3l = vget_low_u64(row23.val[1]);
row01.val[0] = vcombine_u64(vget_low_u64(row01.val[0]), row2l);
row23.val[0] = vcombine_u64(row0h, vget_high_u64(row23.val[0]));
row01.val[1] = vcombine_u64(vget_low_u64(row01.val[1]), row3l);
row23.val[1] = vcombine_u64(row1h, vget_high_u64(row23.val[1]));
}
{
const int32x4x2_t out01 = vtrnq_s32(vreinterpretq_s32_u64(row01.val[0]),
vreinterpretq_s32_u64(row01.val[1]));
const int32x4x2_t out23 = vtrnq_s32(vreinterpretq_s32_u64(row23.val[0]),
vreinterpretq_s32_u64(row23.val[1]));
int32x4x4_t out;
out.val[0] = out01.val[0];
out.val[1] = out01.val[1];
out.val[2] = out23.val[0];
out.val[3] = out23.val[1];
return out;
}
}
#endif // WEBP_DSP_NEON_H_

222
src/dsp/upsampling.c Normal file
View File

@ -0,0 +1,222 @@
// Copyright 2011 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.
// -----------------------------------------------------------------------------
//
// YUV to RGB upsampling functions.
//
// Author: somnath@google.com (Somnath Banerjee)
#include "./dsp.h"
#include "./yuv.h"
#include <assert.h>
//------------------------------------------------------------------------------
// Fancy upsampler
#ifdef FANCY_UPSAMPLING
// Fancy upsampling functions to convert YUV to RGB
WebPUpsampleLinePairFunc WebPUpsamplers[MODE_LAST];
// Given samples laid out in a square as:
// [a b]
// [c d]
// we interpolate u/v as:
// ([9*a + 3*b + 3*c + d 3*a + 9*b + 3*c + d] + [8 8]) / 16
// ([3*a + b + 9*c + 3*d a + 3*b + 3*c + 9*d] [8 8]) / 16
// We process u and v together stashed into 32bit (16bit each).
#define LOAD_UV(u, v) ((u) | ((v) << 16))
#define UPSAMPLE_FUNC(FUNC_NAME, FUNC, XSTEP) \
static void FUNC_NAME(const uint8_t* top_y, const uint8_t* bottom_y, \
const uint8_t* top_u, const uint8_t* top_v, \
const uint8_t* cur_u, const uint8_t* cur_v, \
uint8_t* top_dst, uint8_t* bottom_dst, int len) { \
int x; \
const int last_pixel_pair = (len - 1) >> 1; \
uint32_t tl_uv = LOAD_UV(top_u[0], top_v[0]); /* top-left sample */ \
uint32_t l_uv = LOAD_UV(cur_u[0], cur_v[0]); /* left-sample */ \
assert(top_y != NULL); \
{ \
const uint32_t uv0 = (3 * tl_uv + l_uv + 0x00020002u) >> 2; \
FUNC(top_y[0], uv0 & 0xff, (uv0 >> 16), top_dst); \
} \
if (bottom_y != NULL) { \
const uint32_t uv0 = (3 * l_uv + tl_uv + 0x00020002u) >> 2; \
FUNC(bottom_y[0], uv0 & 0xff, (uv0 >> 16), bottom_dst); \
} \
for (x = 1; x <= last_pixel_pair; ++x) { \
const uint32_t t_uv = LOAD_UV(top_u[x], top_v[x]); /* top sample */ \
const uint32_t uv = LOAD_UV(cur_u[x], cur_v[x]); /* sample */ \
/* precompute invariant values associated with first and second diagonals*/\
const uint32_t avg = tl_uv + t_uv + l_uv + uv + 0x00080008u; \
const uint32_t diag_12 = (avg + 2 * (t_uv + l_uv)) >> 3; \
const uint32_t diag_03 = (avg + 2 * (tl_uv + uv)) >> 3; \
{ \
const uint32_t uv0 = (diag_12 + tl_uv) >> 1; \
const uint32_t uv1 = (diag_03 + t_uv) >> 1; \
FUNC(top_y[2 * x - 1], uv0 & 0xff, (uv0 >> 16), \
top_dst + (2 * x - 1) * XSTEP); \
FUNC(top_y[2 * x - 0], uv1 & 0xff, (uv1 >> 16), \
top_dst + (2 * x - 0) * XSTEP); \
} \
if (bottom_y != NULL) { \
const uint32_t uv0 = (diag_03 + l_uv) >> 1; \
const uint32_t uv1 = (diag_12 + uv) >> 1; \
FUNC(bottom_y[2 * x - 1], uv0 & 0xff, (uv0 >> 16), \
bottom_dst + (2 * x - 1) * XSTEP); \
FUNC(bottom_y[2 * x + 0], uv1 & 0xff, (uv1 >> 16), \
bottom_dst + (2 * x + 0) * XSTEP); \
} \
tl_uv = t_uv; \
l_uv = uv; \
} \
if (!(len & 1)) { \
{ \
const uint32_t uv0 = (3 * tl_uv + l_uv + 0x00020002u) >> 2; \
FUNC(top_y[len - 1], uv0 & 0xff, (uv0 >> 16), \
top_dst + (len - 1) * XSTEP); \
} \
if (bottom_y != NULL) { \
const uint32_t uv0 = (3 * l_uv + tl_uv + 0x00020002u) >> 2; \
FUNC(bottom_y[len - 1], uv0 & 0xff, (uv0 >> 16), \
bottom_dst + (len - 1) * XSTEP); \
} \
} \
}
// All variants implemented.
UPSAMPLE_FUNC(UpsampleRgbLinePair, VP8YuvToRgb, 3)
UPSAMPLE_FUNC(UpsampleBgrLinePair, VP8YuvToBgr, 3)
UPSAMPLE_FUNC(UpsampleRgbaLinePair, VP8YuvToRgba, 4)
UPSAMPLE_FUNC(UpsampleBgraLinePair, VP8YuvToBgra, 4)
UPSAMPLE_FUNC(UpsampleArgbLinePair, VP8YuvToArgb, 4)
UPSAMPLE_FUNC(UpsampleRgba4444LinePair, VP8YuvToRgba4444, 2)
UPSAMPLE_FUNC(UpsampleRgb565LinePair, VP8YuvToRgb565, 2)
#undef LOAD_UV
#undef UPSAMPLE_FUNC
#endif // FANCY_UPSAMPLING
//------------------------------------------------------------------------------
#if !defined(FANCY_UPSAMPLING)
#define DUAL_SAMPLE_FUNC(FUNC_NAME, FUNC) \
static void FUNC_NAME(const uint8_t* top_y, const uint8_t* bot_y, \
const uint8_t* top_u, const uint8_t* top_v, \
const uint8_t* bot_u, const uint8_t* bot_v, \
uint8_t* top_dst, uint8_t* bot_dst, int len) { \
const int half_len = len >> 1; \
int x; \
assert(top_dst != NULL); \
{ \
for (x = 0; x < half_len; ++x) { \
FUNC(top_y[2 * x + 0], top_u[x], top_v[x], top_dst + 8 * x + 0); \
FUNC(top_y[2 * x + 1], top_u[x], top_v[x], top_dst + 8 * x + 4); \
} \
if (len & 1) FUNC(top_y[2 * x + 0], top_u[x], top_v[x], top_dst + 8 * x); \
} \
if (bot_dst != NULL) { \
for (x = 0; x < half_len; ++x) { \
FUNC(bot_y[2 * x + 0], bot_u[x], bot_v[x], bot_dst + 8 * x + 0); \
FUNC(bot_y[2 * x + 1], bot_u[x], bot_v[x], bot_dst + 8 * x + 4); \
} \
if (len & 1) FUNC(bot_y[2 * x + 0], bot_u[x], bot_v[x], bot_dst + 8 * x); \
} \
}
DUAL_SAMPLE_FUNC(DualLineSamplerBGRA, VP8YuvToBgra)
DUAL_SAMPLE_FUNC(DualLineSamplerARGB, VP8YuvToArgb)
#undef DUAL_SAMPLE_FUNC
#endif // !FANCY_UPSAMPLING
WebPUpsampleLinePairFunc WebPGetLinePairConverter(int alpha_is_last) {
WebPInitUpsamplers();
VP8YUVInit();
#ifdef FANCY_UPSAMPLING
return WebPUpsamplers[alpha_is_last ? MODE_BGRA : MODE_ARGB];
#else
return (alpha_is_last ? DualLineSamplerBGRA : DualLineSamplerARGB);
#endif
}
//------------------------------------------------------------------------------
// YUV444 converter
#define YUV444_FUNC(FUNC_NAME, FUNC, XSTEP) \
static void FUNC_NAME(const uint8_t* y, const uint8_t* u, const uint8_t* v, \
uint8_t* dst, int len) { \
int i; \
for (i = 0; i < len; ++i) FUNC(y[i], u[i], v[i], &dst[i * XSTEP]); \
}
YUV444_FUNC(Yuv444ToRgb, VP8YuvToRgb, 3)
YUV444_FUNC(Yuv444ToBgr, VP8YuvToBgr, 3)
YUV444_FUNC(Yuv444ToRgba, VP8YuvToRgba, 4)
YUV444_FUNC(Yuv444ToBgra, VP8YuvToBgra, 4)
YUV444_FUNC(Yuv444ToArgb, VP8YuvToArgb, 4)
YUV444_FUNC(Yuv444ToRgba4444, VP8YuvToRgba4444, 2)
YUV444_FUNC(Yuv444ToRgb565, VP8YuvToRgb565, 2)
#undef YUV444_FUNC
const WebPYUV444Converter WebPYUV444Converters[MODE_LAST] = {
Yuv444ToRgb, // MODE_RGB
Yuv444ToRgba, // MODE_RGBA
Yuv444ToBgr, // MODE_BGR
Yuv444ToBgra, // MODE_BGRA
Yuv444ToArgb, // MODE_ARGB
Yuv444ToRgba4444, // MODE_RGBA_4444
Yuv444ToRgb565, // MODE_RGB_565
Yuv444ToRgba, // MODE_rgbA
Yuv444ToBgra, // MODE_bgrA
Yuv444ToArgb, // MODE_Argb
Yuv444ToRgba4444 // MODE_rgbA_4444
};
//------------------------------------------------------------------------------
// Main calls
extern void WebPInitUpsamplersSSE2(void);
extern void WebPInitUpsamplersNEON(void);
void WebPInitUpsamplers(void) {
#ifdef FANCY_UPSAMPLING
WebPUpsamplers[MODE_RGB] = UpsampleRgbLinePair;
WebPUpsamplers[MODE_RGBA] = UpsampleRgbaLinePair;
WebPUpsamplers[MODE_BGR] = UpsampleBgrLinePair;
WebPUpsamplers[MODE_BGRA] = UpsampleBgraLinePair;
WebPUpsamplers[MODE_ARGB] = UpsampleArgbLinePair;
WebPUpsamplers[MODE_RGBA_4444] = UpsampleRgba4444LinePair;
WebPUpsamplers[MODE_RGB_565] = UpsampleRgb565LinePair;
WebPUpsamplers[MODE_rgbA] = UpsampleRgbaLinePair;
WebPUpsamplers[MODE_bgrA] = UpsampleBgraLinePair;
WebPUpsamplers[MODE_Argb] = UpsampleArgbLinePair;
WebPUpsamplers[MODE_rgbA_4444] = UpsampleRgba4444LinePair;
// If defined, use CPUInfo() to overwrite some pointers with faster versions.
if (VP8GetCPUInfo != NULL) {
#if defined(WEBP_USE_SSE2)
if (VP8GetCPUInfo(kSSE2)) {
WebPInitUpsamplersSSE2();
}
#endif
#if defined(WEBP_USE_NEON)
if (VP8GetCPUInfo(kNEON)) {
WebPInitUpsamplersNEON();
}
#endif
}
#endif // FANCY_UPSAMPLING
}
//------------------------------------------------------------------------------

267
src/dsp/upsampling_neon.c Normal file
View File

@ -0,0 +1,267 @@
// Copyright 2011 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.
// -----------------------------------------------------------------------------
//
// NEON version of YUV to RGB upsampling functions.
//
// Author: mans@mansr.com (Mans Rullgard)
// Based on SSE code by: somnath@google.com (Somnath Banerjee)
#include "./dsp.h"
#if defined(WEBP_USE_NEON)
#include <assert.h>
#include <arm_neon.h>
#include <string.h>
#include "./neon.h"
#include "./yuv.h"
#ifdef FANCY_UPSAMPLING
//-----------------------------------------------------------------------------
// U/V upsampling
// Loads 9 pixels each from rows r1 and r2 and generates 16 pixels.
#define UPSAMPLE_16PIXELS(r1, r2, out) { \
uint8x8_t a = vld1_u8(r1); \
uint8x8_t b = vld1_u8(r1 + 1); \
uint8x8_t c = vld1_u8(r2); \
uint8x8_t d = vld1_u8(r2 + 1); \
\
uint16x8_t al = vshll_n_u8(a, 1); \
uint16x8_t bl = vshll_n_u8(b, 1); \
uint16x8_t cl = vshll_n_u8(c, 1); \
uint16x8_t dl = vshll_n_u8(d, 1); \
\
uint8x8_t diag1, diag2; \
uint16x8_t sl; \
\
/* a + b + c + d */ \
sl = vaddl_u8(a, b); \
sl = vaddw_u8(sl, c); \
sl = vaddw_u8(sl, d); \
\
al = vaddq_u16(sl, al); /* 3a + b + c + d */ \
bl = vaddq_u16(sl, bl); /* a + 3b + c + d */ \
\
al = vaddq_u16(al, dl); /* 3a + b + c + 3d */ \
bl = vaddq_u16(bl, cl); /* a + 3b + 3c + d */ \
\
diag2 = vshrn_n_u16(al, 3); \
diag1 = vshrn_n_u16(bl, 3); \
\
a = vrhadd_u8(a, diag1); \
b = vrhadd_u8(b, diag2); \
c = vrhadd_u8(c, diag2); \
d = vrhadd_u8(d, diag1); \
\
{ \
uint8x8x2_t a_b, c_d; \
INIT_VECTOR2(a_b, a, b); \
INIT_VECTOR2(c_d, c, d); \
vst2_u8(out, a_b); \
vst2_u8(out + 32, c_d); \
} \
}
// Turn the macro into a function for reducing code-size when non-critical
static void Upsample16Pixels(const uint8_t *r1, const uint8_t *r2,
uint8_t *out) {
UPSAMPLE_16PIXELS(r1, r2, out);
}
#define UPSAMPLE_LAST_BLOCK(tb, bb, num_pixels, out) { \
uint8_t r1[9], r2[9]; \
memcpy(r1, (tb), (num_pixels)); \
memcpy(r2, (bb), (num_pixels)); \
/* replicate last byte */ \
memset(r1 + (num_pixels), r1[(num_pixels) - 1], 9 - (num_pixels)); \
memset(r2 + (num_pixels), r2[(num_pixels) - 1], 9 - (num_pixels)); \
Upsample16Pixels(r1, r2, out); \
}
//-----------------------------------------------------------------------------
// YUV->RGB conversion
static const int16_t kCoeffs[4] = { kYScale, kVToR, kUToG, kVToG };
#define v255 vdup_n_u8(255)
#define STORE_Rgb(out, r, g, b) do { \
uint8x8x3_t r_g_b; \
INIT_VECTOR3(r_g_b, r, g, b); \
vst3_u8(out, r_g_b); \
} while (0)
#define STORE_Bgr(out, r, g, b) do { \
uint8x8x3_t b_g_r; \
INIT_VECTOR3(b_g_r, b, g, r); \
vst3_u8(out, b_g_r); \
} while (0)
#define STORE_Rgba(out, r, g, b) do { \
uint8x8x4_t r_g_b_v255; \
INIT_VECTOR4(r_g_b_v255, r, g, b, v255); \
vst4_u8(out, r_g_b_v255); \
} while (0)
#define STORE_Bgra(out, r, g, b) do { \
uint8x8x4_t b_g_r_v255; \
INIT_VECTOR4(b_g_r_v255, b, g, r, v255); \
vst4_u8(out, b_g_r_v255); \
} while (0)
#define CONVERT8(FMT, XSTEP, N, src_y, src_uv, out, cur_x) { \
int i; \
for (i = 0; i < N; i += 8) { \
const int off = ((cur_x) + i) * XSTEP; \
uint8x8_t y = vld1_u8((src_y) + (cur_x) + i); \
uint8x8_t u = vld1_u8((src_uv) + i); \
uint8x8_t v = vld1_u8((src_uv) + i + 16); \
const int16x8_t yy = vreinterpretq_s16_u16(vsubl_u8(y, u16)); \
const int16x8_t uu = vreinterpretq_s16_u16(vsubl_u8(u, u128)); \
const int16x8_t vv = vreinterpretq_s16_u16(vsubl_u8(v, u128)); \
int32x4_t yl = vmull_lane_s16(vget_low_s16(yy), cf16, 0); \
int32x4_t yh = vmull_lane_s16(vget_high_s16(yy), cf16, 0); \
const int32x4_t rl = vmlal_lane_s16(yl, vget_low_s16(vv), cf16, 1);\
const int32x4_t rh = vmlal_lane_s16(yh, vget_high_s16(vv), cf16, 1);\
int32x4_t gl = vmlsl_lane_s16(yl, vget_low_s16(uu), cf16, 2); \
int32x4_t gh = vmlsl_lane_s16(yh, vget_high_s16(uu), cf16, 2); \
const int32x4_t bl = vmovl_s16(vget_low_s16(uu)); \
const int32x4_t bh = vmovl_s16(vget_high_s16(uu)); \
gl = vmlsl_lane_s16(gl, vget_low_s16(vv), cf16, 3); \
gh = vmlsl_lane_s16(gh, vget_high_s16(vv), cf16, 3); \
yl = vmlaq_lane_s32(yl, bl, cf32, 0); \
yh = vmlaq_lane_s32(yh, bh, cf32, 0); \
/* vrshrn_n_s32() already incorporates the rounding constant */ \
y = vqmovun_s16(vcombine_s16(vrshrn_n_s32(rl, YUV_FIX2), \
vrshrn_n_s32(rh, YUV_FIX2))); \
u = vqmovun_s16(vcombine_s16(vrshrn_n_s32(gl, YUV_FIX2), \
vrshrn_n_s32(gh, YUV_FIX2))); \
v = vqmovun_s16(vcombine_s16(vrshrn_n_s32(yl, YUV_FIX2), \
vrshrn_n_s32(yh, YUV_FIX2))); \
STORE_ ## FMT(out + off, y, u, v); \
} \
}
#define CONVERT1(FUNC, XSTEP, N, src_y, src_uv, rgb, cur_x) { \
int i; \
for (i = 0; i < N; i++) { \
const int off = ((cur_x) + i) * XSTEP; \
const int y = src_y[(cur_x) + i]; \
const int u = (src_uv)[i]; \
const int v = (src_uv)[i + 16]; \
FUNC(y, u, v, rgb + off); \
} \
}
#define CONVERT2RGB_8(FMT, XSTEP, top_y, bottom_y, uv, \
top_dst, bottom_dst, cur_x, len) { \
CONVERT8(FMT, XSTEP, len, top_y, uv, top_dst, cur_x) \
if (bottom_y != NULL) { \
CONVERT8(FMT, XSTEP, len, bottom_y, (uv) + 32, bottom_dst, cur_x) \
} \
}
#define CONVERT2RGB_1(FUNC, XSTEP, top_y, bottom_y, uv, \
top_dst, bottom_dst, cur_x, len) { \
CONVERT1(FUNC, XSTEP, len, top_y, uv, top_dst, cur_x); \
if (bottom_y != NULL) { \
CONVERT1(FUNC, XSTEP, len, bottom_y, (uv) + 32, bottom_dst, cur_x); \
} \
}
#define NEON_UPSAMPLE_FUNC(FUNC_NAME, FMT, XSTEP) \
static void FUNC_NAME(const uint8_t *top_y, const uint8_t *bottom_y, \
const uint8_t *top_u, const uint8_t *top_v, \
const uint8_t *cur_u, const uint8_t *cur_v, \
uint8_t *top_dst, uint8_t *bottom_dst, int len) { \
int block; \
/* 16 byte aligned array to cache reconstructed u and v */ \
uint8_t uv_buf[2 * 32 + 15]; \
uint8_t *const r_uv = (uint8_t*)((uintptr_t)(uv_buf + 15) & ~15); \
const int uv_len = (len + 1) >> 1; \
/* 9 pixels must be read-able for each block */ \
const int num_blocks = (uv_len - 1) >> 3; \
const int leftover = uv_len - num_blocks * 8; \
const int last_pos = 1 + 16 * num_blocks; \
\
const int u_diag = ((top_u[0] + cur_u[0]) >> 1) + 1; \
const int v_diag = ((top_v[0] + cur_v[0]) >> 1) + 1; \
\
const int16x4_t cf16 = vld1_s16(kCoeffs); \
const int32x2_t cf32 = vdup_n_s32(kUToB); \
const uint8x8_t u16 = vdup_n_u8(16); \
const uint8x8_t u128 = vdup_n_u8(128); \
\
/* Treat the first pixel in regular way */ \
assert(top_y != NULL); \
{ \
const int u0 = (top_u[0] + u_diag) >> 1; \
const int v0 = (top_v[0] + v_diag) >> 1; \
VP8YuvTo ## FMT(top_y[0], u0, v0, top_dst); \
} \
if (bottom_y != NULL) { \
const int u0 = (cur_u[0] + u_diag) >> 1; \
const int v0 = (cur_v[0] + v_diag) >> 1; \
VP8YuvTo ## FMT(bottom_y[0], u0, v0, bottom_dst); \
} \
\
for (block = 0; block < num_blocks; ++block) { \
UPSAMPLE_16PIXELS(top_u, cur_u, r_uv); \
UPSAMPLE_16PIXELS(top_v, cur_v, r_uv + 16); \
CONVERT2RGB_8(FMT, XSTEP, top_y, bottom_y, r_uv, \
top_dst, bottom_dst, 16 * block + 1, 16); \
top_u += 8; \
cur_u += 8; \
top_v += 8; \
cur_v += 8; \
} \
\
UPSAMPLE_LAST_BLOCK(top_u, cur_u, leftover, r_uv); \
UPSAMPLE_LAST_BLOCK(top_v, cur_v, leftover, r_uv + 16); \
CONVERT2RGB_1(VP8YuvTo ## FMT, XSTEP, top_y, bottom_y, r_uv, \
top_dst, bottom_dst, last_pos, len - last_pos); \
}
// NEON variants of the fancy upsampler.
NEON_UPSAMPLE_FUNC(UpsampleRgbLinePair, Rgb, 3)
NEON_UPSAMPLE_FUNC(UpsampleBgrLinePair, Bgr, 3)
NEON_UPSAMPLE_FUNC(UpsampleRgbaLinePair, Rgba, 4)
NEON_UPSAMPLE_FUNC(UpsampleBgraLinePair, Bgra, 4)
#endif // FANCY_UPSAMPLING
#endif // WEBP_USE_NEON
//------------------------------------------------------------------------------
extern void WebPInitUpsamplersNEON(void);
#ifdef FANCY_UPSAMPLING
extern WebPUpsampleLinePairFunc WebPUpsamplers[/* MODE_LAST */];
void WebPInitUpsamplersNEON(void) {
#if defined(WEBP_USE_NEON)
WebPUpsamplers[MODE_RGB] = UpsampleRgbLinePair;
WebPUpsamplers[MODE_RGBA] = UpsampleRgbaLinePair;
WebPUpsamplers[MODE_BGR] = UpsampleBgrLinePair;
WebPUpsamplers[MODE_BGRA] = UpsampleBgraLinePair;
WebPUpsamplers[MODE_rgbA] = UpsampleRgbaLinePair;
WebPUpsamplers[MODE_bgrA] = UpsampleBgraLinePair;
#endif // WEBP_USE_NEON
}
#else
// this empty function is to avoid an empty .o
void WebPInitUpsamplersNEON(void) {}
#endif // FANCY_UPSAMPLING

214
src/dsp/upsampling_sse2.c Normal file
View File

@ -0,0 +1,214 @@
// Copyright 2011 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.
// -----------------------------------------------------------------------------
//
// SSE2 version of YUV to RGB upsampling functions.
//
// Author: somnath@google.com (Somnath Banerjee)
#include "./dsp.h"
#if defined(WEBP_USE_SSE2)
#include <assert.h>
#include <emmintrin.h>
#include <string.h>
#include "./yuv.h"
#ifdef FANCY_UPSAMPLING
// We compute (9*a + 3*b + 3*c + d + 8) / 16 as follows
// u = (9*a + 3*b + 3*c + d + 8) / 16
// = (a + (a + 3*b + 3*c + d) / 8 + 1) / 2
// = (a + m + 1) / 2
// where m = (a + 3*b + 3*c + d) / 8
// = ((a + b + c + d) / 2 + b + c) / 4
//
// Let's say k = (a + b + c + d) / 4.
// We can compute k as
// k = (s + t + 1) / 2 - ((a^d) | (b^c) | (s^t)) & 1
// where s = (a + d + 1) / 2 and t = (b + c + 1) / 2
//
// Then m can be written as
// m = (k + t + 1) / 2 - (((b^c) & (s^t)) | (k^t)) & 1
// Computes out = (k + in + 1) / 2 - ((ij & (s^t)) | (k^in)) & 1
#define GET_M(ij, in, out) do { \
const __m128i tmp0 = _mm_avg_epu8(k, (in)); /* (k + in + 1) / 2 */ \
const __m128i tmp1 = _mm_and_si128((ij), st); /* (ij) & (s^t) */ \
const __m128i tmp2 = _mm_xor_si128(k, (in)); /* (k^in) */ \
const __m128i tmp3 = _mm_or_si128(tmp1, tmp2); /* ((ij) & (s^t)) | (k^in) */\
const __m128i tmp4 = _mm_and_si128(tmp3, one); /* & 1 -> lsb_correction */ \
(out) = _mm_sub_epi8(tmp0, tmp4); /* (k + in + 1) / 2 - lsb_correction */ \
} while (0)
// pack and store two alternating pixel rows
#define PACK_AND_STORE(a, b, da, db, out) do { \
const __m128i t_a = _mm_avg_epu8(a, da); /* (9a + 3b + 3c + d + 8) / 16 */ \
const __m128i t_b = _mm_avg_epu8(b, db); /* (3a + 9b + c + 3d + 8) / 16 */ \
const __m128i t_1 = _mm_unpacklo_epi8(t_a, t_b); \
const __m128i t_2 = _mm_unpackhi_epi8(t_a, t_b); \
_mm_store_si128(((__m128i*)(out)) + 0, t_1); \
_mm_store_si128(((__m128i*)(out)) + 1, t_2); \
} while (0)
// Loads 17 pixels each from rows r1 and r2 and generates 32 pixels.
#define UPSAMPLE_32PIXELS(r1, r2, out) { \
const __m128i one = _mm_set1_epi8(1); \
const __m128i a = _mm_loadu_si128((__m128i*)&(r1)[0]); \
const __m128i b = _mm_loadu_si128((__m128i*)&(r1)[1]); \
const __m128i c = _mm_loadu_si128((__m128i*)&(r2)[0]); \
const __m128i d = _mm_loadu_si128((__m128i*)&(r2)[1]); \
\
const __m128i s = _mm_avg_epu8(a, d); /* s = (a + d + 1) / 2 */ \
const __m128i t = _mm_avg_epu8(b, c); /* t = (b + c + 1) / 2 */ \
const __m128i st = _mm_xor_si128(s, t); /* st = s^t */ \
\
const __m128i ad = _mm_xor_si128(a, d); /* ad = a^d */ \
const __m128i bc = _mm_xor_si128(b, c); /* bc = b^c */ \
\
const __m128i t1 = _mm_or_si128(ad, bc); /* (a^d) | (b^c) */ \
const __m128i t2 = _mm_or_si128(t1, st); /* (a^d) | (b^c) | (s^t) */ \
const __m128i t3 = _mm_and_si128(t2, one); /* (a^d) | (b^c) | (s^t) & 1 */ \
const __m128i t4 = _mm_avg_epu8(s, t); \
const __m128i k = _mm_sub_epi8(t4, t3); /* k = (a + b + c + d) / 4 */ \
__m128i diag1, diag2; \
\
GET_M(bc, t, diag1); /* diag1 = (a + 3b + 3c + d) / 8 */ \
GET_M(ad, s, diag2); /* diag2 = (3a + b + c + 3d) / 8 */ \
\
/* pack the alternate pixels */ \
PACK_AND_STORE(a, b, diag1, diag2, out + 0); /* store top */ \
PACK_AND_STORE(c, d, diag2, diag1, out + 2 * 32); /* store bottom */ \
}
// Turn the macro into a function for reducing code-size when non-critical
static void Upsample32Pixels(const uint8_t r1[], const uint8_t r2[],
uint8_t* const out) {
UPSAMPLE_32PIXELS(r1, r2, out);
}
#define UPSAMPLE_LAST_BLOCK(tb, bb, num_pixels, out) { \
uint8_t r1[17], r2[17]; \
memcpy(r1, (tb), (num_pixels)); \
memcpy(r2, (bb), (num_pixels)); \
/* replicate last byte */ \
memset(r1 + (num_pixels), r1[(num_pixels) - 1], 17 - (num_pixels)); \
memset(r2 + (num_pixels), r2[(num_pixels) - 1], 17 - (num_pixels)); \
/* using the shared function instead of the macro saves ~3k code size */ \
Upsample32Pixels(r1, r2, out); \
}
#define CONVERT2RGB(FUNC, XSTEP, top_y, bottom_y, \
top_dst, bottom_dst, cur_x, num_pixels) { \
int n; \
for (n = 0; n < (num_pixels); ++n) { \
FUNC(top_y[(cur_x) + n], r_u[n], r_v[n], \
top_dst + ((cur_x) + n) * XSTEP); \
} \
if (bottom_y != NULL) { \
for (n = 0; n < (num_pixels); ++n) { \
FUNC(bottom_y[(cur_x) + n], r_u[64 + n], r_v[64 + n], \
bottom_dst + ((cur_x) + n) * XSTEP); \
} \
} \
}
#define CONVERT2RGB_32(FUNC, XSTEP, top_y, bottom_y, \
top_dst, bottom_dst, cur_x) do { \
FUNC##32(top_y + (cur_x), r_u, r_v, top_dst + (cur_x) * XSTEP); \
if (bottom_y != NULL) { \
FUNC##32(bottom_y + (cur_x), r_u + 64, r_v + 64, \
bottom_dst + (cur_x) * XSTEP); \
} \
} while (0)
#define SSE2_UPSAMPLE_FUNC(FUNC_NAME, FUNC, XSTEP) \
static void FUNC_NAME(const uint8_t* top_y, const uint8_t* bottom_y, \
const uint8_t* top_u, const uint8_t* top_v, \
const uint8_t* cur_u, const uint8_t* cur_v, \
uint8_t* top_dst, uint8_t* bottom_dst, int len) { \
int uv_pos, pos; \
/* 16byte-aligned array to cache reconstructed u and v */ \
uint8_t uv_buf[4 * 32 + 15]; \
uint8_t* const r_u = (uint8_t*)((uintptr_t)(uv_buf + 15) & ~15); \
uint8_t* const r_v = r_u + 32; \
\
assert(top_y != NULL); \
{ /* Treat the first pixel in regular way */ \
const int u_diag = ((top_u[0] + cur_u[0]) >> 1) + 1; \
const int v_diag = ((top_v[0] + cur_v[0]) >> 1) + 1; \
const int u0_t = (top_u[0] + u_diag) >> 1; \
const int v0_t = (top_v[0] + v_diag) >> 1; \
FUNC(top_y[0], u0_t, v0_t, top_dst); \
if (bottom_y != NULL) { \
const int u0_b = (cur_u[0] + u_diag) >> 1; \
const int v0_b = (cur_v[0] + v_diag) >> 1; \
FUNC(bottom_y[0], u0_b, v0_b, bottom_dst); \
} \
} \
/* For UPSAMPLE_32PIXELS, 17 u/v values must be read-able for each block */ \
for (pos = 1, uv_pos = 0; pos + 32 + 1 <= len; pos += 32, uv_pos += 16) { \
UPSAMPLE_32PIXELS(top_u + uv_pos, cur_u + uv_pos, r_u); \
UPSAMPLE_32PIXELS(top_v + uv_pos, cur_v + uv_pos, r_v); \
CONVERT2RGB_32(FUNC, XSTEP, top_y, bottom_y, top_dst, bottom_dst, pos); \
} \
if (len > 1) { \
const int left_over = ((len + 1) >> 1) - (pos >> 1); \
assert(left_over > 0); \
UPSAMPLE_LAST_BLOCK(top_u + uv_pos, cur_u + uv_pos, left_over, r_u); \
UPSAMPLE_LAST_BLOCK(top_v + uv_pos, cur_v + uv_pos, left_over, r_v); \
CONVERT2RGB(FUNC, XSTEP, top_y, bottom_y, top_dst, bottom_dst, \
pos, len - pos); \
} \
}
// SSE2 variants of the fancy upsampler.
SSE2_UPSAMPLE_FUNC(UpsampleRgbLinePair, VP8YuvToRgb, 3)
SSE2_UPSAMPLE_FUNC(UpsampleBgrLinePair, VP8YuvToBgr, 3)
SSE2_UPSAMPLE_FUNC(UpsampleRgbaLinePair, VP8YuvToRgba, 4)
SSE2_UPSAMPLE_FUNC(UpsampleBgraLinePair, VP8YuvToBgra, 4)
#undef GET_M
#undef PACK_AND_STORE
#undef UPSAMPLE_32PIXELS
#undef UPSAMPLE_LAST_BLOCK
#undef CONVERT2RGB
#undef CONVERT2RGB_32
#undef SSE2_UPSAMPLE_FUNC
#endif // FANCY_UPSAMPLING
#endif // WEBP_USE_SSE2
//------------------------------------------------------------------------------
extern void WebPInitUpsamplersSSE2(void);
#ifdef FANCY_UPSAMPLING
extern WebPUpsampleLinePairFunc WebPUpsamplers[/* MODE_LAST */];
void WebPInitUpsamplersSSE2(void) {
#if defined(WEBP_USE_SSE2)
VP8YUVInitSSE2();
WebPUpsamplers[MODE_RGB] = UpsampleRgbLinePair;
WebPUpsamplers[MODE_RGBA] = UpsampleRgbaLinePair;
WebPUpsamplers[MODE_BGR] = UpsampleBgrLinePair;
WebPUpsamplers[MODE_BGRA] = UpsampleBgraLinePair;
WebPUpsamplers[MODE_rgbA] = UpsampleRgbaLinePair;
WebPUpsamplers[MODE_bgrA] = UpsampleBgraLinePair;
#endif // WEBP_USE_SSE2
}
#else
// this empty function is to avoid an empty .o
void WebPInitUpsamplersSSE2(void) {}
#endif // FANCY_UPSAMPLING

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