Compare commits

..

176 Commits

Author SHA1 Message Date
e85d3313d6 update ChangeLog
Change-Id: I39043d4986664312947a0668cb1b7bfbcf5a2477
2018-11-08 15:29:51 -08:00
fa8210e43c Fix pair update in stochastic entropy merging.
The old code simply did not make sense.
The effect is that the pair would be popped from the
queue no matter what; as the queue is small, it does
not matter that much on the results.
But it will matter for a later CL.

Change-Id: If50c9fa9d7f3ac3c48bb7336d81479287d4944c4
(cherry picked from commit 485ff86fbb)
2018-11-07 23:07:24 -08:00
825389acba README.mux: add a reference to the AnimDecoder API
this balances the AnimEncoder section

Change-Id: I205c8d0bd6104509e06737dcbf9a7651fd4bc6a3
2018-11-06 18:47:38 -08:00
3be698c3d3 CMake: fix webp_js compilation
Stick to the strict necessary for running webp_js,
and avoid building sub-lib or examples with heavy dependencies.

Change-Id: Ife4170a7839fb3201b2cf158d98d17bebe10008f
(cherry picked from commit 4cd0582d50)
2018-11-06 17:20:43 -08:00
4cbb4caf49 update NEWS
Change-Id: I4a97342d47247724f12da9d8a7d8f22047c2a179
2018-11-03 11:27:07 -07:00
f5a5918d13 bump version to 1.0.1
libwebp{,decoder} - 1.0.1
libwebp libtool - 7.3.0
libwebpdecoder libtool - 3.3.0

mux - 1.0.1
libtool - 3.3.0

demux - 1.0.1
libtool - 2.5.0

Change-Id: I4310caed27d1e53cc8c1b534571e3d653ad434c8
2018-11-02 20:36:14 -07:00
d61385db35 Speed-up: Make sure we only initialize histograms when needed.
Also, histograms in a HistogramSet can be initialized all
at once.

Change-Id: Ibbfa6034dce58dca8bb9113487e2ae507222ce7d
(cherry picked from commit 6752904b2f)
2018-11-02 17:40:00 -07:00
0c57031629 update AUTHORS
Change-Id: Ie7731464088d985a7398401c8ef45bd26c536fe5
2018-10-27 12:40:29 -07:00
301a2ddae5 img2webp: add help note about arguments from a file
this was added in:
94a8377b extract the command-line parsing helpers to example_util

and matches the help in webpmux

https://groups.google.com/a/webmproject.org/d/msg/webp-discuss/DJs-w_-Id6o/svFXs2CqBgAJ

BUG=webp:101

Change-Id: I2944d1fb1ed3030c356960be2a6c8de15a79311f
(cherry picked from commit b6284d8247)
2018-10-26 22:53:15 -07:00
f0abab9217 Speedups for empty histograms.
When histograms are empty, it is easy to add them.
They should also not be considered when merging histograms
(it is a waste of CPU).
This does not change the compression performance,
just the speed.

Change-Id: I42c721ca0f9c5ea067e73b792aa3db6d5e71d01f
(cherry picked from commit decf6f6b87)
2018-10-26 22:53:05 -07:00
f2dfd92557 Split HistogramAdd to only have the high level logic in C.
Change-Id: Ic9eaebf7128ca0215b49d2a13bde1f5b94a28061
(cherry picked from commit dea3e89983)
2018-10-26 22:52:50 -07:00
06b7bc7dec Fix compilation on windows and clang-cl+ninja.
Change-Id: I4e468519e1bcb99da5057f3b6646b077a1e0e7f1
(cherry picked from commit a376e7b96a)
2018-10-26 22:52:35 -07:00
981794958b remove some minor TODOs
if we didn't do these, they were probably non vital.

Change-Id: I952d2351f5c71934247d4d6631cfdfe070f76bf5
2018-10-17 10:48:19 +02:00
cbf82cc04d Remove AVX2 files.
There is only enc_avx2.c and we never managed to get
something fast enough.

Change-Id: I7465b5d8ccf47d9aa612173b8f80f96060cdb366
2018-10-16 14:12:03 +02:00
5030e90278 Merge "TIFF decoder: remove unused KINV definition" 2018-10-15 18:16:24 +00:00
ac5433118a Remove a few more useless #defines
Change-Id: I211e9bcb1c37d0ebc108896f109b23ce915e22b4
2018-10-15 16:26:10 +02:00
123d330699 TIFF decoder: remove unused KINV definition
+ some #undef

Change-Id: Ib8b8357ad3a6458ca421a59d9ad625656dd54afe
2018-10-14 08:24:43 +02:00
ef1094b0fe Merge "- install pkg-config files during the CMake build" 2018-10-10 03:25:02 +00:00
b911fbc980 libwebp: Remove duplicate GIFDisplayError in anim_util
GIFDisplayError() is already defined exactly the same way
in gifdec. Remove it from anim_util.c and add dependency.

Change-Id: Iec01b41c44d0b61b3a279b8cd754d9917d64f804
2018-10-09 17:29:54 +02:00
eee00b6627 - install pkg-config files during the CMake build
Signed-off-by: Konstantin Ivlev <tomskside@gmail.com>
Change-Id: I88b1a22b19dd9ecdb2ae38082fa9580dbc66d98c
2018-10-08 16:02:12 -07:00
ac3ec8c91d Merge "Clean-up the common sources in dsp." 2018-10-08 15:19:40 +00:00
3e13da7b4f Clean-up the common sources in dsp.
Change-Id: I1b995e6517e8437127a433dccbb5b2db63e7c3a3
2018-10-08 15:00:01 +02:00
5c395f1d71 libwebp: cmake-format all
https://github.com/cheshirekow/cmake_format
A complete row of # is replaced by only one,
so add a space after the first one to keep it.

Change-Id: I367749353a555c89c717f1939220699e43ecab2c
2018-10-05 14:23:06 +02:00
e7a697297b libwebp: Add extras targets in CMakeLists.txt
To be compiled with Visual Studio on Windows through CMake.
Targets are get_disto, vwebp_sdl, webp_quality.

Change-Id: Idec1e19b61b6a661011effee42f7440264afd3ed
2018-10-04 18:58:43 +02:00
e52485d6db libwebp: Rename macros in webpmux.c
For clarity and to avoid:
  webpmux -info
  ERROR: Too many arguments for '-info'.

Change-Id: Iae8e62ed8997f7a4ea183d1b3505373255c3c73a
2018-10-03 21:39:38 +02:00
92dc0f0937 clean-up MakeInputImageCopy()
use pointer increments.

Change-Id: I269412d41a58ab9ffd7fc0f3d479fe73a3d07b9e
2018-10-02 14:46:35 +00:00
39952de265 VP8IteratorImport: add missing 'const'
Change-Id: I0b259e2979de787b5e4606ae93f23df1b49e4c8f
2018-10-02 14:46:27 +00:00
382af7a2dd clean-up WebPBlendAlpha
use pointers instead of ptr + y * stride
+ misc re-org

Change-Id: I29fca781aa44f3bed3f8c1e956c5387705c80ed1
2018-10-02 13:57:12 +00:00
14d020f6e6 libwebp: Use ExUtilGet*() in anim_diff
Instead of strtod() or strtol().

Change-Id: I320373cd969c6969cf4b1491391a95668d1b0beb
2018-10-02 13:55:57 +02:00
0d92ff25f2 libwebp: remove useless variable in gif2webp
"out" is never used.

Change-Id: I4441308ef2267b2a9443add240d2fccabfb817f6
2018-10-02 11:39:48 +02:00
556cb1b45e Merge "CMake: Set WEBP_BUILD_GIF2WEBP to off" 2018-10-01 13:14:46 +00:00
da26ee49a6 CMake: Set WEBP_BUILD_GIF2WEBP to off
Instead of unsetting WEBP_BUILD_GIF2WEBP,
disable it to keep it displayed in ccmake.
Disable WEBP_BUILD_GIF2WEBP before it's tested.
Do the same for WEBP_BUILD_ANIM_UTILS.

Change-Id: I91920814fbda4825ced9a801bb005f8d44bfe09c
2018-10-01 13:48:22 +02:00
b2a867c038 cwebp: Don't premultiply during -resize if -exact
Fix issue where color data is discarded in fully transparent
areas when -resize -exact.
BUG=webp:397

Change-Id: I58ce8d5ae172d5d0f0138e07c7df3a3c6cbd0019
2018-10-01 10:14:51 +02:00
637141bc7c pngdec: fix build w/libpng < 1.4.x
after:
bc5092b1 pngdec: set memory functions

png_alloc_size_t was added in 1.4 use png_size_t in earlier versions

Change-Id: If65ac1c501e2d497b1be480095bf21f06ea7026a
2018-09-28 17:42:27 -07:00
bc5092b162 pngdec: set memory functions
use png_create_read_struct_2 to set a malloc function allowing the code
to fail on large allocations while fuzzing

Change-Id: Iaca1b93ecc6570067708f3ae2db07fbca74386ee
2018-09-28 00:35:47 -07:00
50d8345ae6 Fix CMake math library.
Just in case we have a warning.

Change-Id: I5f2aabf5f4adaaf9ba6c4fbbbf352603259e8081
2018-09-21 15:40:40 +02:00
6aa3e8aaf3 Fix math library on Visual Studio.
The code was compiled but optimized, and no math function
was used.

Change-Id: Ib2ab262c072761ec41df8f9260a1e0fe57d01cef
2018-09-11 18:28:44 +02:00
d71df4e2ee Fix math library finding in CMake.
BUG=webp:396

Change-Id: I8ca35573c242cba24f1e82997b4fb289a48a3005
2018-09-03 14:35:50 +00:00
de08d72741 cosmetics: normalize include guard comment
Change-Id: I0e08ec604aad8412cfe3d3670d773f4ae5650375
2018-08-22 14:46:53 -07:00
009562b403 vwebp: Fix bug when Dispose then NoBlend frames
The graphical bug happens when there is a frame disposed to background
color, followed by another frame that does not blend, and their areas
don't fully overlap. Only the previous frame clears its part of the
viewport. The fix consists in clearing the screen for the previous and
the current frame if needed.

Change-Id: I3425cf7297f0c7b2cf13a3a61b517cc0b1c031d8
2018-08-03 14:15:13 -07:00
423f257930 Fix up CMake to create targets.
Change-Id: I4b0b71d0ab7e49e237bd928de690915cc3b86be2
2018-07-25 14:04:18 +02:00
907208f97e Wait for all threads to be done in DecodeRemaining.
This could lead to a race condition.

BUG=oss-fuzz:9417

Change-Id: Ifef4001115888541cb76095e1c0226487d497b78
2018-07-20 17:03:01 -07:00
4649b3c422 vwebp: Add background color display option
Option -usebgcolor may be used to display ANIM background color (or white if no ANIM chunk), blended on top of checkerboard. By default this is disabled (old behavior) to easily see transparent areas. Spec says that "background color MAY be used", so it's an option.
Key b may be pressed to toggle ANIM background color display. There are visual artifacts (leftovers) when toggling during an animation. This is already the case for rescaling, toggling info etc. (fixing it implies storing viewport render or rendering whole animation from start till current frame).

BUG=webp:394

Change-Id: If9ab898b2eac77226f30f062d522f9861789ef8f
2018-07-20 12:54:30 +02:00
78ad57a36a Fix bad glClearColor parameters
Container spec indicates that background color is written
in BGRA byte order, but glClearColor() parameters are RGBA.
Anyway the checkerboard is displayed right after glClear()
calls so it replaces background color.

In response to webp-discuss/TkLHALGaHaM

Change-Id: Ief5435fadfd6a422b881a9dc240b5e8dc6546e19
2018-07-18 10:50:33 +02:00
da96d8d9ab Allow for a non-initialized alpha decompressor in DoRemap.
BUG=oss-fuzz:9364

Change-Id: Ib1a1c6b0ccfcc255505f019e3e8fd15db73bc4b6
2018-07-13 22:09:06 +02:00
2563db4759 fix rescaling rounding inaccuracy
We should be using 'floor' when doing the final divide.

-> new MACRO is MULT_FIX_FLOOR()

     XXX*** Mips code is DISABLED for now ***XXX

I'll update and re-enable it in a later
patch, since this code needs some refactoring first.

BUG=oss-fuzz:9179

Change-Id: Ic0693cdca4e71f5beab1029475e35c4d06b12d13
2018-07-10 22:45:50 -07:00
211f37ee63 fix endian problems in pattern copy
CopyBlock8b() was over-using memcpy() of 16b values.

BUG=webp:393

Change-Id: Id56f10d334b9a453fbcf50dabfaa63529bcff7e5
2018-07-10 05:15:26 +00:00
5f0f5c07c4 Make sure partition #0 is read before VP8 data in IDecode.
Change-Id: Ie0b264b6422774343206ddba3c2820a0cf37ffc0
2018-07-09 20:20:52 +02:00
de98732b04 fix GetColorf() bug
We should only use the lower 8 bits, masking was missing.

Change-Id: I3072168e100b242356ad57b5a73b7f4d6ebfbb9e
2018-07-06 21:25:41 -07:00
4338cd36fe misc fixes in libwebpmux
* Assert chunklist
  * fix potential memory leak and
  * fix null pointer access

There should not be several alpha_ or img_ chunks in SynthesizeBitstream. Use ChunkListDelete in MuxImageRelease to be safe.
A null pointer accessed in WebPMuxPushFrame triggered a harmless runtime error.

Change-Id: I3027f8752093652bd41f55e667d041c0de77ab6e
2018-07-04 19:03:21 +00:00
e00af13ef4 fix signatures after a9ceda7ff1
fixes vs10_x64 build.

Change-Id: I636e6a5bea1239bacdaa4d160be1d645636c3ae8
2018-07-04 06:03:37 +00:00
a9ceda7ff1 Speed-up chunk list operations.
The chunk list only has two operations: append and set
to one element. The two operations are split and the append
one is sped up by storing the last element.
Corrupted data could make a very long list to search through.

BUG=oss-fuzz:9190

Change-Id: I1aa813ca629df29efaa3b46dbd4c4c42dbeaa34c
2018-07-03 16:36:34 +02:00
2281bbf6f7 Merge "Better handling of bogus Huffman codes." 2018-07-03 08:33:35 +00:00
39cb9aad85 Better handling of bogus Huffman codes.
The standard allows for Huffman images with any coefficients.
Hence potentially big memory allocations. The previous workaround
was "trying" things out, the new one is more rigorous and
only allocates what is needed, modifying the Huffman image
to contain the minimal set of coefficients.

BUG=oss-fuzz:8623,oss-fuzz:9111,oss-fuzz:9134

Change-Id: I6a972e90e4ae509c15cb41ee22c58b775fa3f4aa
2018-07-03 10:00:52 +02:00
89cc9d3787 Merge "fix read-overflow while parsing VP8X chunk" 2018-07-03 03:06:42 +00:00
95fd650706 fix read-overflow while parsing VP8X chunk
The available size was not checked before parsing the VP8X data

BUG=oss-fuzz:9100,oss-fuzz:9123

Change-Id: I0143cc4554883c1015e2f084a0e371229e04a8ca
2018-07-03 02:36:25 +00:00
9e729fe19b Fix VP8IoTeardownHook being called twice on worker sync failure
idec_dec.c, DecodeRemaining: Set decoder state to ERROR to prevent VP8ExitCritical to be called again

Change-Id: Id5f893f45c348e1c529680d930e640f780a73d4c
2018-07-02 13:37:46 +02:00
29fb8562c6 Merge "muxread,anmf: fail on multiple image chunks" 2018-06-30 04:25:20 +00:00
eb82ce76dd muxread,anmf: fail on multiple image chunks
treat an ANMF chunk containing multiple VP8/VP8L file as malformed.
fixes a WebPMuxImage::img_ leak.

Though the invalid free in #9106 was avoided in (ubsan):
be738c6d muxread,ChunkVerifyAndAssign: validate chunk_size
that file would still cause a leak similar to #9099.

BUG=oss-fuzz:9099,oss-fuzz:9106

Change-Id: Ib873446a1188afeeb2fe5d53a86b75e0c5de9573
2018-06-29 17:52:58 -07:00
1344a2e947 fix alpha-filtering crash when image width is larger than radius
(we also limit radius based on height too, for good measure, although it's not an asan bug)

fixes oss-fuzz issue #9105

Change-Id: Ie0d79dd81480dc4e2b653b7e992e5cdcd3dfa834
2018-06-29 11:02:17 -07:00
be738c6d39 muxread,ChunkVerifyAndAssign: validate chunk_size
before accounting for padding which might overflow if chunk_size is >
MAX_CHUNK_PAYLOAD.

BUG=webp:387,webp:388

Change-Id: I3985b8817ed4faaec0629102c5333c228a0e9c98
2018-06-20 18:21:48 -07:00
2c70ad76c9 muxread,CreateInternal: fix riff size checks
previously when adjusting size down based on a smaller riff_size the
checks were insufficient to prevent 'size -= RIFF_HEADER_SIZE' from
rolling over causing ChunkVerifyAndAssign to over read. the new checks
are imported from demux.c.

BUG=webp:386

Change-Id: If863c4a9892977b9ade7dd894392a0ecae13775c
2018-06-14 18:06:44 -07:00
569001f19f Fix for thread race heap-use-after-free
BUG=webp:384

Change-Id: I3a300b45ccae33470888cf2e35a7e937579c9409
2018-06-13 10:45:12 +02:00
c56a02d971 Android.mk: use LOCAL_EXPORT_C_INCLUDES w/public libs
dependents can then pickup the include path for webp/ automatically

Change-Id: Ie768a93d0054f8ebc1720f16fbb550c0b10ef61d
2018-06-07 16:12:58 -07:00
1579559662 CMakeLists.txt,cosmetics: normalize if() formatting
+ break a long line

Change-Id: Ia508d517e89dd2109b655c220b66d8aa834a3b52
2018-06-05 09:27:08 -07:00
1a44c233b9 Merge "cmake: add support for webpmux" 2018-06-05 12:54:53 +00:00
e9569ad708 Merge "configure,*am,cosmetics: s/WANT_/BUILD_/" 2018-06-04 23:23:36 +00:00
35c7de6fc4 cmake: add support for webpmux
Change-Id: Ia694ba49549c43956f6552e6981a46df0fe7e686
2018-06-04 15:44:04 -07:00
0f25e61c13 WebpToSDL(): fix the return value in case of error
spotted Diego Casorran

Change-Id: I48822ade22eb8fcef85043a84d712e892324476d
2018-06-04 09:51:53 +02:00
5d8985de47 configure,*am,cosmetics: s/WANT_/BUILD_/
'BUILD_' is more common across the build files

Change-Id: Id302dba2e9e567c186a9da1da0fba44517e85d07
2018-06-02 10:41:49 -07:00
895fd28f9b Merge "man/Makefile.am: add img2webp.1" 2018-06-02 17:37:04 +00:00
5cf3e2afb5 man/Makefile.am: add img2webp.1
Change-Id: I83ed6e85d36b79e6a97b93221fadb7d35e2305c5
2018-06-01 19:25:53 -07:00
2a9de5b9d3 Add build rules for anim_diff & anim_dump utils.
Change-Id: I2697a6dc3c419a19909262003a6d6a263d3c2747
2018-06-01 19:23:47 -07:00
71ed73cf86 fix invalid check for buffer size
BUG=webp:383

Change-Id: I8ebbb5ca4860d73c3b59b12e238b54a89184bed0
2018-05-25 13:25:39 +02:00
af0e4fbb06 gif2webp: fix transcode of loop count=65535
with loop_compatibility disabled (the default), non-zero loop counts
will be incremented by 1 for browser rendering compatibility. the max,
65535, is a special case as the muxer will fail if it is exceeded; avoid
increasing the limit in this case. this isn't 100% correct, but should
be close enough given the high number of iterations.

BUG=webp:382

Change-Id: Icde3e98a58e9ee89604a72fafda30ab71060dec5
2018-05-11 12:10:25 -07:00
dce5d76431 Limit memory allocation when reading invalid Huffman codes.
BUG=webp:381

Change-Id: I6b68a33689a3309691eba582b759131b81b612c1
2018-05-03 13:53:44 +02:00
f9df0081a7 Merge "cmake: quiet glut deprecation warnings on OS X" 2018-04-25 18:45:52 +00:00
dc39b16fe4 webpmux.1: correct grammar
argument -> arguments

Change-Id: I57132c942150f18dccc5ef84c4c09a6dcc054ffa
2018-04-23 16:06:54 -07:00
c7aa1264f0 cwebp.c: fix a missing \n
+ lot more coverage of exotic options and combinations

Change-Id: I4d8e571a6d94023af9848a2bbd98edda05a54f33
2018-04-23 15:45:41 -07:00
53aa51e9a3 Merge tag 'v1.0.0'
libwebp-1.0.0

- 4/2/2018: version 1.0.0
  This is a binary compatible release.
  * lossy encoder improvements to avoid chroma shifts in various circumstances
    (issues #308, #340)
  * big-endian fixes for decode, RGBA import and WebPPictureDistortion
  Tool updates:
    gifwebp, anim_diff - default duration behavior (<= 10ms) changed to match
                         web browsers, transcoding tools (issue #379)
    img2webp, webpmux - allow options to be passed in via a file (issue #355)

* tag 'v1.0.0': (23 commits)
  update ChangeLog
  webp-container-spec: correct frame duration=0 note
  vwebp: Copy Chrome's behavior w/frame duration == 0
  update ChangeLog
  add WEBP_DSP_INIT / WEBP_DSP_INIT_FUNC
  fix 16b overflow in SSE2
  makefile.unix: add DEBUG flag for compiling w/ debug-symbol
  cwebp,get_disto: fix bpp output
  cmake: Make sure we use near-lossless by default.
  fix bug in WebPImport565: alpha value was not set
  update ChangeLog
  Revert "Use proper targets for CMake."
  Use proper targets for CMake.
  Remove some very hard TODOs.
  {de,}mux/Makefile.am: add missing headers
  makefile.unix,dist: use ascii for text output
  add -version option to anim_dump,anim_diff and img2webp
  webp_js: fix webp_js demo html
  update ChangeLog
  update AUTHORS
  ...

Change-Id: I5659406c022a0964f728ce2eb35338fd9c195466
2018-04-23 14:54:39 -07:00
698b8844e3 update ChangeLog
Change-Id: Ica00314a3dfacad89ec62a3dc2df0d476e6397af
2018-04-20 20:04:55 -07:00
8d510751da webp-container-spec: correct frame duration=0 note
the interpretation of a 0 duration depends on the implementation;
merging of multiple frames isn't guaranteed, some may enforce a minimum
duration.

BUG=webp:380

Change-Id: Idf592049d2092e4cc5cfb2e4c59ddbc91bd52f9c
(cherry picked from commit 71c39a06c8)
2018-04-20 19:59:21 -07:00
e6b2164e3a vwebp: Copy Chrome's behavior w/frame duration == 0
BUG=webp:380

Change-Id: Ia0b108d7da755ff91cf6c84581412e47a3a6e5d9
(cherry picked from commit fd3d5756cb)
2018-04-20 19:59:15 -07:00
094b3b285b cmake: quiet glut deprecation warnings on OS X
BUG=webp:187

Change-Id: I652b474dc8389b2219a424d43dec80c3bf9ba62c
2018-04-20 19:57:16 -07:00
71c39a06c8 webp-container-spec: correct frame duration=0 note
the interpretation of a 0 duration depends on the implementation;
merging of multiple frames isn't guaranteed, some may enforce a minimum
duration.

BUG=webp:380

Change-Id: Idf592049d2092e4cc5cfb2e4c59ddbc91bd52f9c
2018-04-20 15:23:12 -07:00
fd3d5756cb vwebp: Copy Chrome's behavior w/frame duration == 0
BUG=webp:380

Change-Id: Ia0b108d7da755ff91cf6c84581412e47a3a6e5d9
2018-04-20 12:53:10 -07:00
b0c966fb66 Build vwebp from CMake.
Change-Id: I428fd563964a72d58bee75e651c581fbbdb0eb26
2018-04-20 11:13:09 +02:00
d20b770713 update ChangeLog
Change-Id: I809f4b9581802d43503cba85f03c90e3a98627a4
2018-04-17 18:37:49 -07:00
0d5fad46cf add WEBP_DSP_INIT / WEBP_DSP_INIT_FUNC
this internalizes the init checks and provides stronger synchronization
with pthreads when available while still allowing VP8GetCPUInfo to be
modified (mostly for testing purposes). windows is left as is since a
critical section or mutex would cause a leak.

Change-Id: Ieb997e014f2805c0ae39c16f13337663521356f4
(cherry picked from commit d77bf512bd)
2018-04-17 18:01:34 -07:00
d77bf512bd add WEBP_DSP_INIT / WEBP_DSP_INIT_FUNC
this internalizes the init checks and provides stronger synchronization
with pthreads when available while still allowing VP8GetCPUInfo to be
modified (mostly for testing purposes). windows is left as is since a
critical section or mutex would cause a leak.

Change-Id: Ieb997e014f2805c0ae39c16f13337663521356f4
2018-04-17 11:45:34 +00:00
c1cb86af5f fix 16b overflow in SSE2
the 'accum' variable can be larger than 15b for large
rescale values.

Assert triggered:
 src/dsp/rescaler_sse2.c:249: RescalerExportRowExpand_SSE2: Assertion `v >= 0 && v <= 255' failed.
 src/dsp/rescaler_sse2.c:350: RescalerExportRowShrink_SSE2: Assertion `v >= 0 && v <= 255' failed.

-> fall back to C implementation in this case for now

Change-Id: I7ea1cb72301cafc1459be403f6a6f4e3cbc89bb1
2018-04-11 21:25:06 +00:00
e577feb7c2 makefile.unix: add DEBUG flag for compiling w/ debug-symbol
usage example: make -f makefile.unix DEBUG=

Change-Id: I5aefe026a3364e5db5e0220b9fa506687cb98a8d
2018-04-11 20:51:04 +00:00
99be34b3a8 cwebp,get_disto: fix bpp output
bits-per-pixel were intended, not bytes-per-pixel

Change-Id: I023349013ac5956154ab4526bd1e195dfe95b8ab
(cherry picked from commit e122e511cf)
2018-04-10 18:00:23 -07:00
e122e511cf cwebp,get_disto: fix bpp output
bits-per-pixel were intended, not bytes-per-pixel

Change-Id: I023349013ac5956154ab4526bd1e195dfe95b8ab
2018-04-10 15:51:23 -07:00
f5565ca84a cmake: Make sure we use near-lossless by default.
The name of the CMake variable needs to be the same
as the C define used in cmake/config.h.in.

Change-Id: Id56d338617f6e4ed5f1da7ce01006d324ef4989f
2018-04-10 14:40:33 -07:00
d898dc14a5 fix bug in WebPImport565: alpha value was not set
Change-Id: I2af4efb3c6ed49800bc16dbd4a997f7a95931918
2018-04-09 18:39:45 +00:00
1c8f358df4 Fix CMake with WASM.
Change-Id: I21c78999484815c58b5b2c9795310da9d04888e9
2018-04-05 16:25:15 +02:00
a0215fb7dc webp_js: fix webp_js demo html
We need to export 'Module.cwrap' method.

Change-Id: I2986c5a4c06630ae3f95086a114e727a86c99a2b
2018-04-05 16:25:15 +02:00
882784b03d update ChangeLog
Change-Id: I7e38d9beb2d733b85f56a44add8481cb45faf698
2018-04-03 20:22:31 -07:00
2f930e0872 Revert "Use proper targets for CMake."
This reverts commit 8165e8fb3b.

breaks webp_js builds: missing includes, multiply defined symbols

Change-Id: I8df7eda3974e708c2a96b98600ec69981ec7aacb
2018-04-03 19:53:20 -07:00
8165e8fb3b Use proper targets for CMake.
Also fix the bug where near lossless was not used
and allow examples to be built by default.

Change-Id: Ieb5ef77fafe83f3776ff4fd27a6d26534c7a51f3
(cherry picked from commit e155dda0cc)
2018-04-03 18:38:09 -07:00
3f157dd5e7 Remove some very hard TODOs.
Change-Id: I3d1b0072e0ac9125840fbbd76e91d151c82489ec
(cherry picked from commit 4033e1d70d)
2018-04-03 18:38:00 -07:00
abb4776006 Merge "Use proper targets for CMake." 2018-04-04 01:35:03 +00:00
cd758a1745 {de,}mux/Makefile.am: add missing headers
demux + mux: format_constants.h
demux: decode.h (included by demux.h for anim_decode)

Change-Id: I290a3416d4e47b4b6ebc14e99775d9db1ce5aec2
2018-04-03 18:02:27 -07:00
e155dda0cc Use proper targets for CMake.
Also fix the bug where near lossless was not used
and allow examples to be built by default.

Change-Id: Ieb5ef77fafe83f3776ff4fd27a6d26534c7a51f3
2018-04-03 17:49:08 -07:00
b892b8ba8b makefile.unix,dist: use ascii for text output
this prevents unknown escapes containing '-'s getting stripped on OS X
when a tty targeted font is used

Change-Id: I11d77f2984d9fd67a8b22948fb21e4c11396aec4
2018-04-03 12:55:01 -07:00
64a57d0587 add -version option to anim_dump,anim_diff and img2webp
This is to harmonize the -h/-version options on all our examples.

+ added GetAnimatedImageVersions() method to anim_util.*

Change-Id: I2304a1c29e310682e97f236d3867274a192a7a09
2018-04-03 11:46:17 -07:00
994be82d00 Merge "Remove some very hard TODOs." 2018-04-03 14:10:50 +00:00
4033e1d70d Remove some very hard TODOs.
Change-Id: I3d1b0072e0ac9125840fbbd76e91d151c82489ec
2018-04-03 15:17:21 +02:00
fc1b8e3a8b webp_js: fix webp_js demo html
We need to export 'Module.cwrap' method.

Change-Id: I2986c5a4c06630ae3f95086a114e727a86c99a2b
2018-04-03 13:56:53 +02:00
15aa48d905 update ChangeLog
Change-Id: I4a34bfa69c203bec92b42f91d6e7d79a46780584
2018-04-02 17:38:41 -07:00
e607dabcf2 update AUTHORS
Change-Id: I51c52f4f9b37dee36a9201893d7acf1fde46a78e
2018-04-02 16:57:46 -07:00
38410c082f [CFI] Remove function pointer casts
Control Flow Integrity [1] indirect call checking verifies that function
pointers only call valid functions with a matching type signature. This
change eliminates function pointer casts that were causing cfi-icall
failures.

[1] https://www.chromium.org/developers/testing/control-flow-integrity

BUG=chromium:827826

Change-Id: I5db021d06390a6cefd670fdd2f0d34c9e530465e
(cherry picked from commit 978eec2507)
2018-04-02 16:57:14 -07:00
978eec2507 [CFI] Remove function pointer casts
Control Flow Integrity [1] indirect call checking verifies that function
pointers only call valid functions with a matching type signature. This
change eliminates function pointer casts that were causing cfi-icall
failures.

[1] https://www.chromium.org/developers/testing/control-flow-integrity

BUG=chromium:827826

Change-Id: I5db021d06390a6cefd670fdd2f0d34c9e530465e
2018-04-02 16:04:47 -07:00
c57b273698 bump version to 1.0.0
libwebp{,decoder} - 1.0.0
libwebp libtool - 7.2.0
libwebpdecoder libtool - 3.2.0

mux - 1.0.0
libtool - 3.2.0

demux - 1.0.0
libtool - 2.4.0

Change-Id: I4310caed27d1e53cc8c1b534571e3d653ad434c8
2018-04-02 15:36:15 -07:00
cba2885375 update NEWS
Change-Id: I3470bf02d20f87e17bbabcb3e415a7c2dd5804ed
2018-04-02 15:36:15 -07:00
c909d53182 Merge "remove some deprecation warning on MacOSX" 2018-03-31 08:09:41 +00:00
217443c71a remove some deprecation warning on MacOSX
Change-Id: I3e6de5ae6d84aa7906049eb55b6373c5123b0158
2018-03-31 09:30:00 +02:00
b672bdfaad configure: quiet glut deprecation warnings on OS X
BUG=webp:187

Change-Id: Iad88b5fe417289f00dedcc32e7672fc0898e9ed1
2018-03-31 00:24:53 -07:00
daa9fcaf5b configure: use sdl-config if available
+ do a full link to ensure SDL_main is resolved if needed

fixes detection on OS X

BUG=webp:366

Change-Id: Id53329f5d1c2536c4584be61c6379fa76ff0e5de
2018-03-30 23:30:43 -07:00
dd174caeff Merge "imagedec: support metadata reading for WebP image decoding" 2018-03-30 03:18:39 +00:00
641cedccd3 imagedec: support metadata reading for WebP image decoding
Needs to link imagedec.a to demux/libwebpdemux.a

Change-Id: Id8f4068718b0e4a1e84607bccd5af5419120c231
2018-03-28 16:36:37 -07:00
065b2ce10e anim_diff: add a couple missing newlines in Help()
Change-Id: Iad2a4ad2555718f1822b82d38219940ed49385b8
2018-03-26 21:37:29 -07:00
c4cc114785 Merge "gif2webp: force low duration frames to 100ms" 2018-03-27 03:11:48 +00:00
09333097ed gif2webp: force low duration frames to 100ms
this is consistent with web browser behavior as well as various
transcoding tools (ffmpeg, gif2apng, etc).

also: update anim_diff to account for this new behaviour.

BUG=webp:379

Change-Id: I70cc72a6b401ef32b73cd182a3f12d993d495bf4
2018-03-24 08:26:53 +01:00
e03f0ec319 sharp_yuv: use 14b fixed-point precision for gamma
Output is <.1% difference in size, randomly.

Speed is 30-50% faster (-m 0 -sharp_yuv).
It also gives the exact same output on ARM and x86, because floats
are no longer used.

Change-Id: Id0f0aa748cc4fc0b82bac1fc5ca954775a0a1b7c
2018-03-23 20:19:28 +01:00
b2db361ca6 image_enc,WebPWritePNG: move locals after setjmp
this quiets a -Wclobbered warning on const has_alpha under gcc-7 and
brings the variables closer to their first use.

Change-Id: I8a24f275b7ff34a94d47b576bcf276dbedac2121
2018-03-08 22:58:11 -08:00
74e82ec64a Merge "WebPPictureDistortion: fix big-endian results order" 2018-02-20 21:20:45 +00:00
645d04ca7f Merge "cwebp,get_disto: report bpp" 2018-02-20 19:56:57 +00:00
120f58c3aa Merge "lossless*sse2: improve non-const 16-bit vector creation" 2018-02-20 19:56:07 +00:00
a7fe9412d0 WebPPictureDistortion: fix big-endian results order
match the little-endian BGRA order

Change-Id: Ie8f1ae3100fac478bae13e53121a6af5b2443374
2018-02-20 11:52:41 -08:00
e26fe06680 cwebp,get_disto: report bpp
Change-Id: Iefbd834baa4f70eb862071a8e4b87f7d30736aa3
2018-02-19 13:38:29 -08:00
9df64e28dd Merge changes Id5b4a1a4,Ia20ce844
* changes:
  Import: extract condition from loop
  Import,RGBA: fix for BigEndian import
2018-02-19 04:28:22 +00:00
8043504f95 lossless*sse2: improve non-const 16-bit vector creation
use _mm_set1_epi32 instead of _mm_set_epi16 with non-const values;
reduces shifts and ors.

Change-Id: Ie2cb2ab815f642855d03c6f3001223bcac4bd35c
2018-02-17 17:59:20 -08:00
1e3dfc48fb Import: extract condition from loop
do_copy is a loop invariant, but based on a variable parameter; it would
only be extracted if Import was inlined.

Change-Id: Id5b4a1a4a83a4f2083444da4934e4c994df65b44
2018-02-17 13:30:28 -08:00
3b07d32712 Import,RGBA: fix for BigEndian import
+ simplification of the logic

Change-Id: Ia20ce844793ed35ea03a17cef45838f3d0ae4afa
2018-02-17 13:07:58 -08:00
551948e45f Remove unused argument in VP8LBitsEntropy.
The function is only used once and does not use the extra argument.

Change-Id: I9735383784746cb02b5a643b7a4a2037f2874bf9
2018-02-16 16:05:28 +01:00
3005237a5d ReadWebP: fix for big-endian
Change-Id: I36b3c12ccf02eb5dad350c460387c0528fff8df3
2018-02-14 23:39:26 -08:00
499c395a35 Merge "anim_diff: expose the -max_diff option" 2018-02-09 19:39:03 +00:00
f69dcd692a Merge "remove WEBP_EXPERIMENTAL_FEATURES" 2018-02-09 18:53:59 +00:00
07d884d59b anim_diff: expose the -max_diff option
this removes the last remnant of WEBP_EXPERIMENTAL_FEATURES

Change-Id: I5952107b5aae60b865f0745e0bb4a7e1663af5aa
2018-02-09 10:32:09 -08:00
f4dd92565e remove WEBP_EXPERIMENTAL_FEATURES
the webp bitstream is considered stable at this point

Change-Id: I4b13f9ed4c45f63785474b097e96cb7bf651be7b
2018-02-09 10:25:11 -08:00
94a8377b3e extract the command-line parsing helpers to example_util
+ make img2webp tool use the text-file parsing option too.

Change-Id: I1976e651bbe8b4701abceba89e054b4fb3c35696
2018-02-08 08:11:31 +00:00
fc09e6e252 PNM decoder: prevent unsupported depth=2 PAM case.
Change-Id: I8476818908d71498dd80b07dc255aa008ffd16f5
2018-02-07 18:24:01 -08:00
6de58603b7 MIPS64: Fix defined-but-not-used errors with WEBP_REDUCE_CSP
BUG=webp:372

Change-Id: Ided3fae748face18138a8050eaced5e0f58120d4
2018-01-30 17:40:09 -08:00
cbde5728c8 gif2webp: add support for reading from stdin
output to stdout is already supported; this matches [cd]webp

BUG=webp:371

Change-Id: Ib1ce1661b16ea792943bca2980f779584e90cc86
2018-01-26 03:13:44 -08:00
cf1c5054c7 Add an SSE4 version of some lossless color transforms.
Change-Id: Ieac094f684116d1292793b2ca321f6f1a69565b5
2018-01-24 14:33:25 +01:00
45a8b5eb59 Fix lint error with man page.
LC_ALL=en_US.UTF-8 MANROFFSEQ='' MANWIDTH=80 \
     man --warnings -E UTF-8 -l -Tutf8 -Z img2webp.1 >/dev/null
would trigger it.

BUG=webp:370

Change-Id: I9543112bc58ac424af86bb65f7d894707a5646c7
2018-01-23 21:18:30 +01:00
cff38e8f4d Merge "PNG decoder: handle gAMA chunk" 2018-01-06 00:07:58 +00:00
59cb1a48c1 Merge "enable dc error-diffusion always" 2018-01-05 22:51:58 +00:00
78318b30e5 PNG decoder: handle gAMA chunk
Apply gamma correction to the decoded RGB values.

This handles corner cases where the PNG file doesn't have
a standard 1/2.2 gamma value.

BUG=webp:369

Change-Id: I9907b6e2c458002de7c26d0b9e416278cca33990
2018-01-05 10:56:52 -08:00
664c21dd01 Merge "remove some TODOs" 2017-12-28 14:39:35 +00:00
815652de03 enable dc error-diffusion always
for q<=98, we always enable error diffusion.

+ reduce storage 2x by using int8_t
+ make the error diffusion more robust

BUG=webp:340,308

Change-Id: I0608df839ff7b64d6843005a0f81d2577143af9e
2017-12-27 20:11:57 +00:00
aec45cec33 remove some TODOs
* regarding alpha_data_ used for testing.
   alpha_data_!=NULL is as close a good test as we'll get.
* regarding filter-strength / sharpness forcing
   no practical use (can be done during encode cycles,
   for experimentation)
* regarding a 'less-complex' filtering:
   no practical use so far. Next version!

Change-Id: If2dfff5818552a7d3e7c23ac08d64fe6d270229c
2017-12-27 17:40:18 +01:00
5715dfce2e fix block-count[] increment in case of large image
For large images overflowing the partition0, we re-do a number
of passes but were forgetting to reset the block_count[].
This was leading to incorrect summary.

+ some cosmetic fixes here and there

BUG=webp:355

Change-Id: Ie87158d7f177f8efdca429b146cfcd0e81652d2f
2017-12-27 17:12:58 +01:00
c2d04f3eb2 enable DC error-diffusion always for multi-pass
We can't predict if the quality is going to be below the threshold
eventually, so we might as well enable it always.

Change-Id: I30aedecc8c6d4daf159f6ef152697df0206d1e93
2017-12-12 15:00:45 +01:00
96bf07c560 use DC error diffusion for U/V at low-quality
This fixes some color smearing due to heavy quantization.
This is only enabled for q <= 30 (cf ERROR_DIFFUSION_QUALITY)

Change-Id: I07e83a4d38461357a32c9e214f7eadc6db73baa9
2017-12-11 06:37:40 -08:00
1c59020b93 fix missing sse41 targets in makefile.unix
Change-Id: I8c7a39746594caea160c40e25ea22d756ca44e11
2017-12-11 00:00:19 -08:00
7a8e814b57 cosmetics: s/color_space/colorspace/
in webpinfo.c, quality_estimate.c.
this form is used elsewhere in the codebase

Change-Id: I40c8202db51a7356e6a14d7e9b25c68153548438
2017-12-08 12:40:18 -08:00
05f6fe24c3 upsampling: rm asserts w/REDUCE_CSP+OMIT_C_CODE
with WEBP_NEON_OMIT_C_CODE the default _C functions won't be set and
with WEBP_REDUCE_CSP the NEON functions won't be either triggering an
assert for an empty table member.

BUG=chromium:792627

Change-Id: I8d2d430eaa37bb92885b61a3dd39f961924a8def
2017-12-06 17:09:26 -08:00
b4cf5597f4 Merge "Upsampling SSE2/SSE4 speedup." 2017-12-06 10:10:12 +00:00
ccbeb32c04 Makefile.vc: add missing sse41 files
upsampling_sse41.c and yuv_sse41.c added in:
807b53c4 Implement the upsampling/yuv functions in SSE41

Change-Id: I186cb6f6c296ba26b8e9b42d88da7f58c55710a9
2017-12-05 23:27:16 -08:00
55403a9a5a Upsampling SSE2/SSE4 speedup.
RGB to YUV conversion was not using SSE to finish up the row.
End data is now copied to a buffer big enough to fit in a
SSE register.
(UPSAMPLE_LAST_BLOCK was already using that trick).

Change-Id: Ie539bcbe570a643a774aa88263503c0d2c41890f
2017-12-05 23:37:06 +01:00
807b53c47e Implement the upsampling/yuv functions in SSE41
Change-Id: If122da22b74a974262063d232f6ca0ab902ff64e
2017-12-04 22:29:43 +01:00
84101a8165 Fix wasm WebP compilation
Change-Id: I6638628fbf3b7ae310bc892c9ca49678d1098b9b
2017-12-04 13:39:50 +01:00
8bebd2a32e fix warning on MSVC
'function' : different 'const' qualifiers

Change-Id: I855e94e8734a7e9a6156c771a7bad41b19a450d7
2017-12-01 22:46:48 -08:00
a7f93fe32d webpmux: allow reading argument from a file
if a single text file name is supplied as argument
(e.g.: 'webpmux my_long_list_of_frames.txt'), the command
line arguments are actually parsed from this file.
Tokenizer will remove space, tabs, LF, CR, returns, etc.

+ changed ImgIoUtilReadFile() to return a null-terminated
data, for convenience.

+ misc clean-up in the code

BUG=webp:355

Change-Id: I76796305641d660933de5881763d723006712fa9
---
2017-12-01 01:42:22 -08:00
b69f18a73a gif2webp.1: fix -loop_compatibility layout
Change-Id: Ia29b7a9e3b72605d2bb8c13ad3e37b88094444f5
2017-11-29 22:59:30 -08:00
72d530c01d Merge "fix lossless decoding w/WEBP_REDUCE_SIZE" 2017-11-30 06:42:20 +00:00
296c7dc4ac fix lossless decoding w/WEBP_REDUCE_SIZE
alpha processing is still required when requesting premultiplied output

since:
1b27bf8b WEBP_REDUCE_SIZE: disable all rescaler code

Change-Id: Id1b03256c4c04b8db31527e60cd31dd20ce6f3ad
2017-11-29 17:01:40 -08:00
0d5d029c18 Merge "ImgIoUtilReadFile: fix file leak upon error" 2017-11-30 00:24:51 +00:00
ae568ce7c4 ImgIoUtilReadFile: fix file leak upon error
the file was not closed in case of malloc error.

Change-Id: I5f8b22d7d0da6d2c8c2dd245cdd57994e3ddea3a
2017-11-29 21:30:22 +01:00
796b5a8a8a Merge tag 'v0.6.1'
libwebp-0.6.1

- 11/24/2017: version 0.6.1
  This is a binary compatible release.
  * lossless performance and compression improvements + a new 'cruncher' mode
    (-m 6 -q 100)
  * ARM performance improvements with clang (15-20% w/ndk r15c, issue #339)
  * webp-js: emscripten/webassembly based javascript decoder
  * miscellaneous bug & build fixes (issue #329, #332, #343, #353, #360, #361,
    #363)
  Tool updates / additions:
    added webpinfo - prints file format information (issue #330)
    gif2webp - loop behavior modified to match Chrome M63+ (crbug.com/649264);
               '-loop_compatibility' can be used for the old behavior

* tag 'v0.6.1':
  update ChangeLog
  WEBP_REDUCE_CSP: restrict colorspace support
  update ChangeLog
  vwebp: disable double buffering on windows & mac
  webp_to_sdl.c: fix file mode
  WEBP_REDUCE_SIZE: disable all rescaler code
  webpinfo: add -version option
  bump version to 0.6.1
  update NEWS
  README: add webpinfo section

Change-Id: Iab2153fae38da3c99daccdf57fec816e07b7909a
2017-11-28 15:03:15 -08:00
1af0df7662 Merge "WEBP_REDUCE_CSP: restrict colorspace support" 2017-11-27 20:08:55 +00:00
6de20df02c WEBP_REDUCE_CSP: restrict colorspace support
only supported ones are: RGBA/BGRA/rgbA/bgrA (decoder)
as well as: WebPPictureImportRGB/RGBX/RGBA (encoder).

(note: extras/get_disto is affected too)

Change-Id: If6c4f95054ca15759c4e289fb3b4c352b3521c2c
2017-11-26 08:44:08 +00:00
0df22b9eed WEBP_REDUCE_SIZE: disable all rescaler code
BUG=webp:355

Change-Id: Id87cb11902e3fb8544a214308526ea9665ce8440
2017-11-24 22:08:32 +00:00
150 changed files with 3664 additions and 2175 deletions

View File

@ -1,4 +1,5 @@
Contributors: Contributors:
- Alan Browning (browning at google dot com)
- Charles Munger (clm at google dot com) - Charles Munger (clm at google dot com)
- Christian Duvivier (cduvivier at google dot com) - Christian Duvivier (cduvivier at google dot com)
- Djordje Pesut (djordje dot pesut at imgtec dot com) - Djordje Pesut (djordje dot pesut at imgtec dot com)
@ -9,6 +10,7 @@ Contributors:
- Johann (johann dot koenig at duck dot com) - Johann (johann dot koenig at duck dot com)
- Jovan Zelincevic (jovan dot zelincevic at imgtec dot com) - Jovan Zelincevic (jovan dot zelincevic at imgtec dot com)
- Jyrki Alakuijala (jyrki at google dot com) - Jyrki Alakuijala (jyrki at google dot com)
- Konstantin Ivlev (tomskside at gmail dot com)
- Lode Vandevenne (lode at google dot com) - Lode Vandevenne (lode at google dot com)
- Lou Quillio (louquillio at google dot com) - Lou Quillio (louquillio at google dot com)
- Mans Rullgard (mans at mansr dot com) - Mans Rullgard (mans at mansr dot com)
@ -35,4 +37,6 @@ Contributors:
- Urvang Joshi (urvang at google dot com) - Urvang Joshi (urvang at google dot com)
- Vikas Arora (vikasa at google dot com) - Vikas Arora (vikasa at google dot com)
- Vincent Rabaud (vrabaud at google dot com) - Vincent Rabaud (vrabaud at google dot com)
- Vlad Tsyrklevich (vtsyrklevich at chromium dot org)
- Yang Zhang (yang dot zhang at arm dot com) - Yang Zhang (yang dot zhang at arm dot com)
- Yannis Guyon (yguyon at google dot com)

View File

@ -85,11 +85,13 @@ dsp_dec_srcs := \
src/dsp/upsampling_msa.c \ src/dsp/upsampling_msa.c \
src/dsp/upsampling_neon.$(NEON) \ src/dsp/upsampling_neon.$(NEON) \
src/dsp/upsampling_sse2.c \ src/dsp/upsampling_sse2.c \
src/dsp/upsampling_sse41.c \
src/dsp/yuv.c \ src/dsp/yuv.c \
src/dsp/yuv_mips32.c \ src/dsp/yuv_mips32.c \
src/dsp/yuv_mips_dsp_r2.c \ src/dsp/yuv_mips_dsp_r2.c \
src/dsp/yuv_neon.$(NEON) \ src/dsp/yuv_neon.$(NEON) \
src/dsp/yuv_sse2.c \ src/dsp/yuv_sse2.c \
src/dsp/yuv_sse41.c \
dsp_enc_srcs := \ dsp_enc_srcs := \
src/dsp/cost.c \ src/dsp/cost.c \
@ -97,7 +99,6 @@ dsp_enc_srcs := \
src/dsp/cost_mips_dsp_r2.c \ src/dsp/cost_mips_dsp_r2.c \
src/dsp/cost_sse2.c \ src/dsp/cost_sse2.c \
src/dsp/enc.c \ src/dsp/enc.c \
src/dsp/enc_avx2.c \
src/dsp/enc_mips32.c \ src/dsp/enc_mips32.c \
src/dsp/enc_mips_dsp_r2.c \ src/dsp/enc_mips_dsp_r2.c \
src/dsp/enc_msa.c \ src/dsp/enc_msa.c \
@ -121,7 +122,6 @@ enc_srcs := \
src/enc/backward_references_enc.c \ src/enc/backward_references_enc.c \
src/enc/config_enc.c \ src/enc/config_enc.c \
src/enc/cost_enc.c \ src/enc/cost_enc.c \
src/enc/delta_palettization_enc.c \
src/enc/filter_enc.c \ src/enc/filter_enc.c \
src/enc/frame_enc.c \ src/enc/frame_enc.c \
src/enc/histogram_enc.c \ src/enc/histogram_enc.c \
@ -173,7 +173,7 @@ LOCAL_SRC_FILES := \
$(utils_dec_srcs) \ $(utils_dec_srcs) \
LOCAL_CFLAGS := $(WEBP_CFLAGS) LOCAL_CFLAGS := $(WEBP_CFLAGS)
LOCAL_C_INCLUDES += $(LOCAL_PATH)/src LOCAL_EXPORT_C_INCLUDES += $(LOCAL_PATH)/src
# prefer arm over thumb mode for performance gains # prefer arm over thumb mode for performance gains
LOCAL_ARM_MODE := arm LOCAL_ARM_MODE := arm
@ -207,7 +207,7 @@ LOCAL_SRC_FILES := \
$(utils_enc_srcs) \ $(utils_enc_srcs) \
LOCAL_CFLAGS := $(WEBP_CFLAGS) LOCAL_CFLAGS := $(WEBP_CFLAGS)
LOCAL_C_INCLUDES += $(LOCAL_PATH)/src LOCAL_EXPORT_C_INCLUDES += $(LOCAL_PATH)/src
# prefer arm over thumb mode for performance gains # prefer arm over thumb mode for performance gains
LOCAL_ARM_MODE := arm LOCAL_ARM_MODE := arm
@ -230,7 +230,7 @@ include $(CLEAR_VARS)
LOCAL_SRC_FILES := $(demux_srcs) LOCAL_SRC_FILES := $(demux_srcs)
LOCAL_CFLAGS := $(WEBP_CFLAGS) LOCAL_CFLAGS := $(WEBP_CFLAGS)
LOCAL_C_INCLUDES += $(LOCAL_PATH)/src LOCAL_EXPORT_C_INCLUDES += $(LOCAL_PATH)/src
# prefer arm over thumb mode for performance gains # prefer arm over thumb mode for performance gains
LOCAL_ARM_MODE := arm LOCAL_ARM_MODE := arm
@ -253,7 +253,7 @@ include $(CLEAR_VARS)
LOCAL_SRC_FILES := $(mux_srcs) LOCAL_SRC_FILES := $(mux_srcs)
LOCAL_CFLAGS := $(WEBP_CFLAGS) LOCAL_CFLAGS := $(WEBP_CFLAGS)
LOCAL_C_INCLUDES += $(LOCAL_PATH)/src LOCAL_EXPORT_C_INCLUDES += $(LOCAL_PATH)/src
# prefer arm over thumb mode for performance gains # prefer arm over thumb mode for performance gains
LOCAL_ARM_MODE := arm LOCAL_ARM_MODE := arm

View File

@ -1,81 +1,118 @@
cmake_minimum_required(VERSION 2.8.7) cmake_minimum_required(VERSION 3.5)
project(libwebp C) project(WebP C)
# Options for coder / decoder executables. # Options for coder / decoder executables.
option(WEBP_ENABLE_SIMD "Enable any SIMD optimization." ON) option(WEBP_ENABLE_SIMD "Enable any SIMD optimization." ON)
option(WEBP_BUILD_CWEBP "Build the cwebp command line tool." OFF) option(WEBP_BUILD_ANIM_UTILS "Build animation utilities." ON)
option(WEBP_BUILD_DWEBP "Build the dwebp command line tool." OFF) option(WEBP_BUILD_CWEBP "Build the cwebp command line tool." ON)
option(WEBP_BUILD_GIF2WEBP "Build the gif2webp conversion tool." OFF) option(WEBP_BUILD_DWEBP "Build the dwebp command line tool." ON)
option(WEBP_BUILD_IMG2WEBP "Build the img2webp animation tool." OFF) option(WEBP_BUILD_GIF2WEBP "Build the gif2webp conversion tool." ON)
option(WEBP_BUILD_WEBPINFO "Build the webpinfo command line tool." OFF) option(WEBP_BUILD_IMG2WEBP "Build the img2webp animation tool." ON)
option(WEBP_BUILD_VWEBP "Build the vwebp viewer tool." ON)
option(WEBP_BUILD_WEBPINFO "Build the webpinfo command line tool." ON)
option(WEBP_BUILD_WEBPMUX "Build the webpmux command line tool." ON)
option(WEBP_BUILD_EXTRAS "Build extras." ON)
option(WEBP_BUILD_WEBP_JS "Emscripten build of webp.js." OFF) option(WEBP_BUILD_WEBP_JS "Emscripten build of webp.js." OFF)
option(WEBP_ENABLE_NEAR_LOSSLESS "Enable near-lossless encoding" ON) option(WEBP_NEAR_LOSSLESS "Enable near-lossless encoding" ON)
option(WEBP_EXPERIMENTAL_FEATURES "Build with experimental features." OFF) option(WEBP_ENABLE_SWAP_16BIT_CSP "Enable byte swap for 16 bit colorspaces."
option(WEBP_ENABLE_SWAP_16BIT_CSP "Enable byte swap for 16 bit colorspaces." OFF) OFF)
if(WEBP_BUILD_WEBP_JS) if(WEBP_BUILD_WEBP_JS)
set(WEBP_ENABLE_SIMD OFF) set(WEBP_ENABLE_SIMD OFF)
set(WEBP_BUILD_ANIM_UTILS OFF)
set(WEBP_BUILD_CWEBP OFF)
set(WEBP_BUILD_DWEBP OFF)
set(WEBP_BUILD_GIF2WEBP OFF)
set(WEBP_BUILD_IMG2WEBP OFF)
set(WEBP_BUILD_VWEBP OFF)
set(WEBP_BUILD_WEBPINFO OFF)
set(WEBP_BUILD_WEBPMUX OFF)
set(WEBP_BUILD_EXTRAS OFF)
endif() endif()
set(WEBP_DEP_LIBRARIES) set(WEBP_DEP_LIBRARIES)
set(WEBP_DEP_INCLUDE_DIRS) set(WEBP_DEP_INCLUDE_DIRS)
if(NOT CMAKE_BUILD_TYPE) if(NOT CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE "Release" CACHE set(CMAKE_BUILD_TYPE "Release"
"Build type: Release, Debug or RelWithDebInfo" STRING FORCE CACHE "Build type: Release, Debug, MinSizeRel or RelWithDebInfo" STRING
) FORCE)
endif() endif()
# Include dependencies. # Include dependencies.
include(cmake/deps.cmake) include(cmake/deps.cmake)
include(GNUInstallDirs) include(GNUInstallDirs)
################################################################################ # ##############################################################################
# Options. # Options.
if(WEBP_ENABLE_SWAP_16BIT_CSP) if(WEBP_ENABLE_SWAP_16BIT_CSP)
add_definitions(-DWEBP_SWAP_16BIT_CSP=1) add_definitions(-DWEBP_SWAP_16BIT_CSP=1)
endif() endif()
################################################################################ set(prefix ${CMAKE_INSTALL_PREFIX})
set(exec_prefix "\$\{prefix\}")
set(libdir "\$\{prefix\}/lib")
set(includedir "\$\{prefix\}/include")
set(PTHREAD_LIBS ${CMAKE_THREAD_LIBS_INIT})
# ##############################################################################
# Android only. # Android only.
if(ANDROID) if(ANDROID)
include_directories(${ANDROID_NDK}/sources/android/cpufeatures) include_directories(${ANDROID_NDK}/sources/android/cpufeatures)
add_library(cpufeatures STATIC add_library(cpufeatures STATIC
${ANDROID_NDK}/sources/android/cpufeatures/cpu-features.c ${ANDROID_NDK}/sources/android/cpufeatures/cpu-features.c)
)
target_link_libraries(cpufeatures dl) target_link_libraries(cpufeatures dl)
set(WEBP_DEP_LIBRARIES ${WEBP_DEP_LIBRARIES} cpufeatures) set(WEBP_DEP_LIBRARIES ${WEBP_DEP_LIBRARIES} cpufeatures)
set(WEBP_DEP_INCLUDE_DIRS ${WEBP_DEP_INCLUDE_DIRS} set(WEBP_DEP_INCLUDE_DIRS ${WEBP_DEP_INCLUDE_DIRS}
${ANDROID_NDK}/sources/android/cpufeatures ${ANDROID_NDK}/sources/android/cpufeatures)
)
add_definitions(-DHAVE_CPU_FEATURES_H=1) add_definitions(-DHAVE_CPU_FEATURES_H=1)
set(HAVE_CPU_FEATURES_H 1) set(HAVE_CPU_FEATURES_H 1)
else() else()
set(HAVE_CPU_FEATURES_H 0) set(HAVE_CPU_FEATURES_H 0)
endif() endif()
################################################################################ function(configure_pkg_config FILE)
# WebP source files. configure_file("${CMAKE_CURRENT_SOURCE_DIR}/${FILE}.in"
# Read the Makefile.am to get the source files. "${CMAKE_CURRENT_BINARY_DIR}/${FILE}")
# We expect the Makefiles to define the sources as defined in if(HAVE_MATH_LIBRARY)
# the first regex. E.g.: # MSVC doesn't have libm
# libimagedec_la_SOURCES = image_dec.c image_dec.h file(READ ${CMAKE_CURRENT_BINARY_DIR}/${FILE} data)
string(REPLACE "-lm" "" data ${data})
file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/${FILE} ${data})
endif()
install(
FILES "${CMAKE_CURRENT_BINARY_DIR}/${FILE}"
DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig
)
endfunction()
# ##############################################################################
# WebP source files. Read the Makefile.am to get the source files.
# We expect the Makefiles to define the sources as defined in the first regex.
# E.g.: libimagedec_la_SOURCES = image_dec.c image_dec.h
function(parse_Makefile_am FOLDER VAR SRC_REGEX) function(parse_Makefile_am FOLDER VAR SRC_REGEX)
file(READ ${FOLDER}/Makefile.am MAKEFILE_AM) file(READ ${FOLDER}/Makefile.am MAKEFILE_AM)
string(REGEX MATCHALL "${SRC_REGEX}_SOURCES[ ]*\\+?=[ ]+[0-9a-z\\._ ]*" string(REGEX MATCHALL
FILES_PER_LINE ${MAKEFILE_AM} "${SRC_REGEX}_SOURCES[ ]*\\+?=[ ]+[0-9a-z\\._ ]*"
) FILES_PER_LINE
${MAKEFILE_AM})
set(SRCS ${${VAR}}) set(SRCS ${${VAR}})
foreach(FILES ${FILES_PER_LINE}) foreach(FILES ${FILES_PER_LINE})
string(FIND ${FILES} "=" OFFSET) string(FIND ${FILES} "=" OFFSET)
math(EXPR OFFSET "${OFFSET} + 2") math(EXPR OFFSET "${OFFSET} + 2")
string(SUBSTRING ${FILES} ${OFFSET} -1 FILES) string(SUBSTRING ${FILES}
${OFFSET}
-1
FILES)
if(FILES) if(FILES)
string(REGEX MATCHALL "[0-9a-z\\._]+" string(REGEX MATCHALL
FILES ${FILES} "[0-9a-z\\._]+"
) FILES
${FILES})
foreach(FILE ${FILES}) foreach(FILE ${FILES})
list(APPEND SRCS ${FOLDER}/${FILE}) list(APPEND SRCS ${FOLDER}/${FILE})
endforeach() endforeach()
@ -85,16 +122,16 @@ function(parse_Makefile_am FOLDER VAR SRC_REGEX)
endfunction() endfunction()
set(WEBP_SRC_DIR ${CMAKE_CURRENT_SOURCE_DIR}/src) set(WEBP_SRC_DIR ${CMAKE_CURRENT_SOURCE_DIR}/src)
parse_Makefile_am(${WEBP_SRC_DIR}/dec "WEBP_DEC_SRCS" "") parse_makefile_am(${WEBP_SRC_DIR}/dec "WEBP_DEC_SRCS" "")
parse_Makefile_am(${WEBP_SRC_DIR}/demux "WEBP_DEMUX_SRCS" "") parse_makefile_am(${WEBP_SRC_DIR}/demux "WEBP_DEMUX_SRCS" "")
parse_Makefile_am(${WEBP_SRC_DIR}/dsp "WEBP_DSP_COMMON_SRCS" "COMMON") parse_makefile_am(${WEBP_SRC_DIR}/dsp "WEBP_DSP_COMMON_SRCS" "COMMON")
parse_Makefile_am(${WEBP_SRC_DIR}/dsp "WEBP_DSP_ENC_SRCS" "ENC") parse_makefile_am(${WEBP_SRC_DIR}/dsp "WEBP_DSP_ENC_SRCS" "ENC")
parse_Makefile_am(${WEBP_SRC_DIR}/dsp "WEBP_DSP_ENC_SRCS" "dsp_[^ ]*") parse_makefile_am(${WEBP_SRC_DIR}/dsp "WEBP_DSP_ENC_SRCS" "dsp_[^ ]*")
parse_Makefile_am(${WEBP_SRC_DIR}/dsp "WEBP_DSP_DEC_SRCS" "decode_[^ ]*") parse_makefile_am(${WEBP_SRC_DIR}/dsp "WEBP_DSP_DEC_SRCS" "decode_[^ ]*")
parse_Makefile_am(${WEBP_SRC_DIR}/enc "WEBP_ENC_SRCS" "") parse_makefile_am(${WEBP_SRC_DIR}/enc "WEBP_ENC_SRCS" "")
parse_Makefile_am(${WEBP_SRC_DIR}/utils "WEBP_UTILS_COMMON_SRCS" "COMMON") parse_makefile_am(${WEBP_SRC_DIR}/utils "WEBP_UTILS_COMMON_SRCS" "COMMON")
parse_Makefile_am(${WEBP_SRC_DIR}/utils "WEBP_UTILS_ENC_SRCS" "ENC") parse_makefile_am(${WEBP_SRC_DIR}/utils "WEBP_UTILS_ENC_SRCS" "ENC")
parse_Makefile_am(${WEBP_SRC_DIR}/utils "WEBP_UTILS_DEC_SRCS" "decode_[^ ]*") parse_makefile_am(${WEBP_SRC_DIR}/utils "WEBP_UTILS_DEC_SRCS" "decode_[^ ]*")
# Remove the files specific to SIMD we don't use. # Remove the files specific to SIMD we don't use.
foreach(FILE ${WEBP_SIMD_FILES_NOT_TO_INCLUDE}) foreach(FILE ${WEBP_SIMD_FILES_NOT_TO_INCLUDE})
@ -102,7 +139,12 @@ foreach(FILE ${WEBP_SIMD_FILES_NOT_TO_INCLUDE})
list(REMOVE_ITEM WEBP_DSP_DEC_SRCS ${FILE}) list(REMOVE_ITEM WEBP_DSP_DEC_SRCS ${FILE})
endforeach() endforeach()
### Define the mandatory libraries. # Generate the config.h file.
configure_file(${CMAKE_CURRENT_LIST_DIR}/cmake/config.h.in
${CMAKE_CURRENT_BINARY_DIR}/src/webp/config.h)
add_definitions(-DHAVE_CONFIG_H)
# ##############################################################################
# Build the webpdecoder library. # Build the webpdecoder library.
if(MSVC) if(MSVC)
# avoid security warnings for e.g., fopen() used in the examples. # avoid security warnings for e.g., fopen() used in the examples.
@ -110,257 +152,455 @@ if(MSVC)
else() else()
add_definitions(-Wall) add_definitions(-Wall)
endif() endif()
include_directories(${CMAKE_CURRENT_SOURCE_DIR} ${WEBP_DEP_INCLUDE_DIRS}) include_directories(${WEBP_DEP_INCLUDE_DIRS})
add_library(webpdecode OBJECT ${WEBP_DEC_SRCS}) add_library(webpdecode OBJECT ${WEBP_DEC_SRCS})
target_include_directories(webpdecode
PRIVATE ${CMAKE_CURRENT_BINARY_DIR}
${CMAKE_CURRENT_SOURCE_DIR})
add_library(webpdspdecode OBJECT ${WEBP_DSP_COMMON_SRCS} ${WEBP_DSP_DEC_SRCS}) add_library(webpdspdecode OBJECT ${WEBP_DSP_COMMON_SRCS} ${WEBP_DSP_DEC_SRCS})
add_library(webputilsdecode OBJECT ${WEBP_UTILS_COMMON_SRCS} target_include_directories(webpdspdecode
${WEBP_UTILS_DEC_SRCS}) PRIVATE ${CMAKE_CURRENT_BINARY_DIR}
add_library(webpdecoder $<TARGET_OBJECTS:webpdecode> ${CMAKE_CURRENT_SOURCE_DIR})
$<TARGET_OBJECTS:webpdspdecode> $<TARGET_OBJECTS:webputilsdecode>) add_library(webputilsdecode
OBJECT
${WEBP_UTILS_COMMON_SRCS}
${WEBP_UTILS_DEC_SRCS})
target_include_directories(webputilsdecode
PRIVATE ${CMAKE_CURRENT_BINARY_DIR}
${CMAKE_CURRENT_SOURCE_DIR})
add_library(webpdecoder
$<TARGET_OBJECTS:webpdecode>
$<TARGET_OBJECTS:webpdspdecode>
$<TARGET_OBJECTS:webputilsdecode>)
target_link_libraries(webpdecoder ${WEBP_DEP_LIBRARIES}) target_link_libraries(webpdecoder ${WEBP_DEP_LIBRARIES})
target_include_directories(
webpdecoder
PRIVATE ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR}
INTERFACE $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>)
set_target_properties(
webpdecoder
PROPERTIES PUBLIC_HEADER "${CMAKE_CURRENT_SOURCE_DIR}/src/webp/decode.h;\
${CMAKE_CURRENT_SOURCE_DIR}/src/webp/types.h")
configure_pkg_config("src/libwebpdecoder.pc")
# Build the webp library. # Build the webp library.
add_library(webpencode OBJECT ${WEBP_ENC_SRCS}) add_library(webpencode OBJECT ${WEBP_ENC_SRCS})
target_include_directories( target_include_directories(webpencode
webpencode PRIVATE ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR} PRIVATE ${CMAKE_CURRENT_BINARY_DIR}
${CMAKE_CURRENT_SOURCE_DIR}/src) ${CMAKE_CURRENT_SOURCE_DIR})
add_library(webpdsp OBJECT ${WEBP_DSP_COMMON_SRCS} ${WEBP_DSP_DEC_SRCS} add_library(webpdsp
${WEBP_DSP_ENC_SRCS}) OBJECT
target_include_directories(webpdsp PRIVATE ${CMAKE_CURRENT_BINARY_DIR} ${WEBP_DSP_COMMON_SRCS}
${CMAKE_CURRENT_SOURCE_DIR}) ${WEBP_DSP_DEC_SRCS}
add_library(webputils OBJECT ${WEBP_UTILS_COMMON_SRCS} ${WEBP_UTILS_DEC_SRCS} ${WEBP_DSP_ENC_SRCS})
${WEBP_UTILS_ENC_SRCS}) target_include_directories(webpdsp
target_include_directories(webputils PRIVATE ${CMAKE_CURRENT_BINARY_DIR} PRIVATE ${CMAKE_CURRENT_BINARY_DIR}
${CMAKE_CURRENT_SOURCE_DIR}) ${CMAKE_CURRENT_SOURCE_DIR})
add_library(webp $<TARGET_OBJECTS:webpdecode> $<TARGET_OBJECTS:webpdsp> add_library(webputils
$<TARGET_OBJECTS:webpencode> $<TARGET_OBJECTS:webputils>) OBJECT
if(XCODE) ${WEBP_UTILS_COMMON_SRCS}
libwebp_add_stub_file(webp) ${WEBP_UTILS_DEC_SRCS}
endif() ${WEBP_UTILS_ENC_SRCS})
target_include_directories(webputils
PRIVATE ${CMAKE_CURRENT_BINARY_DIR}
${CMAKE_CURRENT_SOURCE_DIR})
add_library(webp
$<TARGET_OBJECTS:webpdecode>
$<TARGET_OBJECTS:webpdsp>
$<TARGET_OBJECTS:webpencode>
$<TARGET_OBJECTS:webputils>)
target_link_libraries(webp ${WEBP_DEP_LIBRARIES}) target_link_libraries(webp ${WEBP_DEP_LIBRARIES})
target_include_directories( target_include_directories(webp
webp PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
PUBLIC $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/src> ${CMAKE_CURRENT_BINARY_DIR}
$<INSTALL_INTERFACE:include>) PUBLIC $<INSTALL_INTERFACE:include>)
set_target_properties( set_target_properties(
webp webp
PROPERTIES PUBLIC_HEADER "${CMAKE_CURRENT_SOURCE_DIR}/src/webp/decode.h;\ PROPERTIES PUBLIC_HEADER "${CMAKE_CURRENT_SOURCE_DIR}/src/webp/decode.h;\
${CMAKE_CURRENT_SOURCE_DIR}/src/webp/encode.h;\ ${CMAKE_CURRENT_SOURCE_DIR}/src/webp/encode.h;\
${CMAKE_CURRENT_SOURCE_DIR}/src/webp/types.h") ${CMAKE_CURRENT_SOURCE_DIR}/src/webp/types.h")
# Make sure the OBJECT libraries are built with position independent code # Make sure the OBJECT libraries are built with position independent code (it is
# (it is not ON by default). # not ON by default).
set_target_properties(webpdecode webpdspdecode webputilsdecode set_target_properties(webpdecode
webpencode webpdsp webputils PROPERTIES POSITION_INDEPENDENT_CODE ON) webpdspdecode
webputilsdecode
webpencode
webpdsp
webputils
PROPERTIES POSITION_INDEPENDENT_CODE ON)
configure_pkg_config("src/libwebp.pc")
# Build the webp demux library. # Build the webp demux library.
add_library(webpdemux ${WEBP_DEMUX_SRCS}) add_library(webpdemux ${WEBP_DEMUX_SRCS})
target_link_libraries(webpdemux webp) target_link_libraries(webpdemux webp)
target_include_directories( target_include_directories(webpdemux
webpdemux PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
PUBLIC $<INSTALL_INTERFACE:include>) ${CMAKE_CURRENT_BINARY_DIR}
PUBLIC $<INSTALL_INTERFACE:include>)
set_target_properties( set_target_properties(
webpdemux webpdemux
PROPERTIES PROPERTIES PUBLIC_HEADER "${CMAKE_CURRENT_SOURCE_DIR}/src/webp/decode.h;\
PUBLIC_HEADER
"${CMAKE_CURRENT_SOURCE_DIR}/src/webp/decode.h;\
${CMAKE_CURRENT_SOURCE_DIR}/src/webp/demux.h;\ ${CMAKE_CURRENT_SOURCE_DIR}/src/webp/demux.h;\
${CMAKE_CURRENT_SOURCE_DIR}/src/webp/mux_types.h;\ ${CMAKE_CURRENT_SOURCE_DIR}/src/webp/mux_types.h;\
${CMAKE_CURRENT_SOURCE_DIR}/src/webp/types.h") ${CMAKE_CURRENT_SOURCE_DIR}/src/webp/types.h")
configure_pkg_config("src/demux/libwebpdemux.pc")
# Set the version numbers. # Set the version numbers.
function(parse_version FILE NAME VAR) function(parse_version FILE NAME VAR)
file(READ ${CMAKE_CURRENT_SOURCE_DIR}/src/${FILE} SOURCE_FILE) file(READ ${CMAKE_CURRENT_SOURCE_DIR}/src/${FILE} SOURCE_FILE)
string(REGEX MATCH "${NAME}_la_LDFLAGS[^\n]* -version-info [0-9:]+" TMP string(REGEX MATCH
${SOURCE_FILE}) "${NAME}_la_LDFLAGS[^\n]* -version-info [0-9:]+"
string(REGEX MATCH "[0-9:]+" TMP ${TMP}) TMP
string(REGEX REPLACE ":" "." VERSION ${TMP}) ${SOURCE_FILE})
string(REGEX MATCH
"[0-9:]+"
TMP
${TMP})
string(REGEX
REPLACE ":"
"."
VERSION
${TMP})
set(${VAR} "${VERSION}" PARENT_SCOPE) set(${VAR} "${VERSION}" PARENT_SCOPE)
endfunction() endfunction()
parse_version(Makefile.am webp WEBP_WEBP_SOVERSION) parse_version(Makefile.am webp WEBP_WEBP_SOVERSION)
set_target_properties(webp PROPERTIES VERSION ${PACKAGE_VERSION} set_target_properties(webp
SOVERSION ${WEBP_WEBP_SOVERSION}) PROPERTIES VERSION
${PACKAGE_VERSION}
SOVERSION
${WEBP_WEBP_SOVERSION})
parse_version(Makefile.am webpdecoder WEBP_DECODER_SOVERSION) parse_version(Makefile.am webpdecoder WEBP_DECODER_SOVERSION)
set_target_properties(webpdecoder PROPERTIES VERSION ${PACKAGE_VERSION} set_target_properties(webpdecoder
SOVERSION ${WEBP_DECODER_SOVERSION}) PROPERTIES VERSION
${PACKAGE_VERSION}
SOVERSION
${WEBP_DECODER_SOVERSION})
parse_version(demux/Makefile.am webpdemux WEBP_DEMUX_SOVERSION) parse_version(demux/Makefile.am webpdemux WEBP_DEMUX_SOVERSION)
set_target_properties(webpdemux PROPERTIES VERSION ${PACKAGE_VERSION} set_target_properties(webpdemux
SOVERSION ${WEBP_DEMUX_SOVERSION}) PROPERTIES VERSION
${PACKAGE_VERSION}
SOVERSION
${WEBP_DEMUX_SOVERSION})
file(READ ${CMAKE_CURRENT_SOURCE_DIR}/configure.ac CONFIGURE_FILE)
string(REGEX MATCH
"AC_INIT\\([^\n]*\\[[0-9\\.]+\\]"
TMP
${CONFIGURE_FILE})
string(REGEX MATCH
"[0-9\\.]+"
PROJECT_VERSION
${TMP})
# Define the libraries to install. # Define the libraries to install.
set(INSTALLED_LIBRARIES webpdecoder webp webpdemux) set(INSTALLED_LIBRARIES webpdecoder webp webpdemux)
### Deal with SIMD. # Deal with SIMD. Change the compile flags for SIMD files we use.
# Change the compile flags for SIMD files we use.
list(LENGTH WEBP_SIMD_FILES_TO_INCLUDE WEBP_SIMD_FILES_TO_INCLUDE_LENGTH) list(LENGTH WEBP_SIMD_FILES_TO_INCLUDE WEBP_SIMD_FILES_TO_INCLUDE_LENGTH)
math(EXPR WEBP_SIMD_FILES_TO_INCLUDE_RANGE math(EXPR WEBP_SIMD_FILES_TO_INCLUDE_RANGE
"${WEBP_SIMD_FILES_TO_INCLUDE_LENGTH}-1" "${WEBP_SIMD_FILES_TO_INCLUDE_LENGTH}-1")
)
foreach(I_FILE RANGE ${WEBP_SIMD_FILES_TO_INCLUDE_RANGE}) foreach(I_FILE RANGE ${WEBP_SIMD_FILES_TO_INCLUDE_RANGE})
list(GET WEBP_SIMD_FILES_TO_INCLUDE ${I_FILE} FILE) list(GET WEBP_SIMD_FILES_TO_INCLUDE ${I_FILE} FILE)
list(GET WEBP_SIMD_FLAGS_TO_INCLUDE ${I_FILE} SIMD_COMPILE_FLAG) list(GET WEBP_SIMD_FLAGS_TO_INCLUDE ${I_FILE} SIMD_COMPILE_FLAG)
set_source_files_properties(${FILE} PROPERTIES set_source_files_properties(${FILE}
COMPILE_FLAGS ${SIMD_COMPILE_FLAG} PROPERTIES
) COMPILE_FLAGS
${SIMD_COMPILE_FLAG})
endforeach() endforeach()
# Build the executables if asked for. if(WEBP_BUILD_GIF2WEBP AND NOT GIF_FOUND)
if(WEBP_BUILD_CWEBP OR WEBP_BUILD_DWEBP OR set(WEBP_BUILD_GIF2WEBP OFF)
WEBP_BUILD_GIF2WEBP OR WEBP_BUILD_IMG2WEBP OR WEBP_BUILD_WEBP_JS) endif()
# Example utility library.
parse_Makefile_am(${CMAKE_CURRENT_SOURCE_DIR}/examples "EXAMPLEUTIL_SRCS"
"example_util_[^ ]*")
list(APPEND EXAMPLEUTIL_SRCS
${CMAKE_CURRENT_SOURCE_DIR}/examples/stopwatch.h)
add_library(exampleutil ${EXAMPLEUTIL_SRCS})
parse_Makefile_am(${CMAKE_CURRENT_SOURCE_DIR}/imageio "IMAGEIOUTILS_SRCS" if(WEBP_BUILD_ANIM_UTILS AND NOT GIF_FOUND)
"imageio_util_[^ ]*") set(WEBP_BUILD_ANIM_UTILS OFF)
endif()
# Build the executables if asked for.
if(WEBP_BUILD_ANIM_UTILS
OR WEBP_BUILD_CWEBP
OR WEBP_BUILD_DWEBP
OR WEBP_BUILD_GIF2WEBP
OR WEBP_BUILD_IMG2WEBP
OR WEBP_BUILD_VWEBP)
# Example utility library.
parse_makefile_am(${CMAKE_CURRENT_SOURCE_DIR}/examples "EXAMPLEUTIL_SRCS"
"example_util_[^ ]*")
list(APPEND EXAMPLEUTIL_SRCS ${CMAKE_CURRENT_SOURCE_DIR}/examples/stopwatch.h)
add_library(exampleutil ${EXAMPLEUTIL_SRCS})
target_include_directories(
exampleutil
PUBLIC $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/src>)
parse_makefile_am(${CMAKE_CURRENT_SOURCE_DIR}/imageio "IMAGEIOUTILS_SRCS"
"imageio_util_[^ ]*")
add_library(imageioutil ${IMAGEIOUTILS_SRCS}) add_library(imageioutil ${IMAGEIOUTILS_SRCS})
target_link_libraries(imageioutil webp) target_link_libraries(imageioutil webp)
# Image-decoding utility library. # Image-decoding utility library.
parse_Makefile_am(${CMAKE_CURRENT_SOURCE_DIR}/imageio "IMAGEDEC_SRCS" parse_makefile_am(${CMAKE_CURRENT_SOURCE_DIR}/imageio "IMAGEDEC_SRCS"
"imagedec_[^ ]*") "imagedec_[^ ]*")
add_library(imagedec ${IMAGEDEC_SRCS}) add_library(imagedec ${IMAGEDEC_SRCS})
target_link_libraries(imagedec imageioutil webp ${WEBP_DEP_IMG_LIBRARIES}) target_link_libraries(imagedec
imageioutil
webpdemux
webp
${WEBP_DEP_IMG_LIBRARIES})
# Image-encoding utility library. # Image-encoding utility library.
parse_Makefile_am(${CMAKE_CURRENT_SOURCE_DIR}/imageio "IMAGEENC_SRCS" parse_makefile_am(${CMAKE_CURRENT_SOURCE_DIR}/imageio "IMAGEENC_SRCS"
"imageenc_[^ ]*") "imageenc_[^ ]*")
add_library(imageenc ${IMAGEENC_SRCS}) add_library(imageenc ${IMAGEENC_SRCS})
target_link_libraries(imageenc webp) target_link_libraries(imageenc webp)
set_property(TARGET exampleutil imageioutil imagedec imageenc set_property(TARGET exampleutil
PROPERTY INCLUDE_DIRECTORIES imageioutil
${CMAKE_CURRENT_SOURCE_DIR}/src ${CMAKE_CURRENT_BINARY_DIR}/src) imagedec
imageenc
PROPERTY INCLUDE_DIRECTORIES ${CMAKE_CURRENT_SOURCE_DIR}/src
${CMAKE_CURRENT_BINARY_DIR}/src)
endif() endif()
if(WEBP_BUILD_DWEBP) if(WEBP_BUILD_DWEBP)
# dwebp # dwebp
include_directories(${WEBP_DEP_IMG_INCLUDE_DIRS}) parse_makefile_am(${CMAKE_CURRENT_SOURCE_DIR}/examples "DWEBP_SRCS" "dwebp")
parse_Makefile_am(${CMAKE_CURRENT_SOURCE_DIR}/examples "DWEBP_SRCS"
"dwebp")
add_executable(dwebp ${DWEBP_SRCS}) add_executable(dwebp ${DWEBP_SRCS})
target_link_libraries(dwebp exampleutil imagedec imageenc webpdecoder) target_link_libraries(dwebp exampleutil imagedec imageenc)
install(TARGETS dwebp RUNTIME DESTINATION bin) target_include_directories(dwebp PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/src)
set_property(TARGET dwebp PROPERTY INCLUDE_DIRECTORIES install(TARGETS dwebp RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
${CMAKE_CURRENT_SOURCE_DIR}/src ${CMAKE_CURRENT_BINARY_DIR}/src)
endif() endif()
if(WEBP_BUILD_CWEBP) if(WEBP_BUILD_CWEBP)
# cwebp # cwebp
include_directories(${WEBP_DEP_IMG_INCLUDE_DIRS}) parse_makefile_am(${CMAKE_CURRENT_SOURCE_DIR}/examples "CWEBP_SRCS" "cwebp")
parse_Makefile_am(${CMAKE_CURRENT_SOURCE_DIR}/examples "CWEBP_SRCS"
"cwebp")
add_executable(cwebp ${CWEBP_SRCS}) add_executable(cwebp ${CWEBP_SRCS})
target_link_libraries(cwebp exampleutil imagedec webp) target_link_libraries(cwebp exampleutil imagedec webp)
install(TARGETS cwebp RUNTIME DESTINATION bin) target_include_directories(cwebp PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/src)
set_property(TARGET cwebp PROPERTY INCLUDE_DIRECTORIES install(TARGETS cwebp RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
${CMAKE_CURRENT_SOURCE_DIR}/src ${CMAKE_CURRENT_BINARY_DIR}/src)
endif()
if(WEBP_BUILD_GIF2WEBP AND NOT GIF_FOUND)
unset(WEBP_BUILD_GIF2WEBP CACHE)
endif() endif()
if(WEBP_BUILD_GIF2WEBP OR WEBP_BUILD_IMG2WEBP) if(WEBP_BUILD_GIF2WEBP OR WEBP_BUILD_IMG2WEBP)
parse_Makefile_am(${CMAKE_CURRENT_SOURCE_DIR}/src/mux "WEBP_MUX_SRCS" parse_makefile_am(${CMAKE_CURRENT_SOURCE_DIR}/src/mux "WEBP_MUX_SRCS" "")
"") add_library(libwebpmux ${WEBP_MUX_SRCS})
add_library(webpmux ${WEBP_MUX_SRCS}) target_link_libraries(libwebpmux webp)
target_link_libraries(webpmux webp) target_include_directories(libwebpmux
PRIVATE ${CMAKE_CURRENT_BINARY_DIR}
${CMAKE_CURRENT_SOURCE_DIR})
parse_version(mux/Makefile.am webpmux WEBP_MUX_SOVERSION) parse_version(mux/Makefile.am webpmux WEBP_MUX_SOVERSION)
set_target_properties(webpmux PROPERTIES VERSION ${PACKAGE_VERSION} set_target_properties(libwebpmux
SOVERSION ${WEBP_MUX_SOVERSION}) PROPERTIES VERSION
set_target_properties( ${PACKAGE_VERSION}
webpmux SOVERSION
PROPERTIES PUBLIC_HEADER "${CMAKE_CURRENT_SOURCE_DIR}/src/webp/mux.h;\ ${WEBP_MUX_SOVERSION})
set_target_properties(libwebpmux
PROPERTIES PUBLIC_HEADER
"${CMAKE_CURRENT_SOURCE_DIR}/src/webp/mux.h;\
${CMAKE_CURRENT_SOURCE_DIR}/src/webp/mux_types.h;\ ${CMAKE_CURRENT_SOURCE_DIR}/src/webp/mux_types.h;\
${CMAKE_CURRENT_SOURCE_DIR}/src/webp/types.h;") ${CMAKE_CURRENT_SOURCE_DIR}/src/webp/types.h;")
list(APPEND INSTALLED_LIBRARIES webpmux) set_target_properties(libwebpmux PROPERTIES OUTPUT_NAME webpmux)
list(APPEND INSTALLED_LIBRARIES libwebpmux)
configure_pkg_config("src/mux/libwebpmux.pc")
endif() endif()
if(WEBP_BUILD_GIF2WEBP) if(WEBP_BUILD_GIF2WEBP)
# gif2webp # gif2webp
include_directories(${WEBP_DEP_GIF_INCLUDE_DIRS}) include_directories(${WEBP_DEP_GIF_INCLUDE_DIRS})
parse_Makefile_am(${CMAKE_CURRENT_SOURCE_DIR}/examples "GIF2WEBP_SRCS" parse_makefile_am(${CMAKE_CURRENT_SOURCE_DIR}/examples "GIF2WEBP_SRCS"
"gif2webp") "gif2webp")
add_executable(gif2webp ${GIF2WEBP_SRCS}) add_executable(gif2webp ${GIF2WEBP_SRCS})
target_link_libraries(gif2webp exampleutil imageioutil webp webpmux target_link_libraries(gif2webp
${WEBP_DEP_GIF_LIBRARIES}) exampleutil
install(TARGETS gif2webp RUNTIME DESTINATION bin) imageioutil
set_property(TARGET gif2webp PROPERTY INCLUDE_DIRECTORIES webp
${CMAKE_CURRENT_SOURCE_DIR}/src ${CMAKE_CURRENT_BINARY_DIR}/src) libwebpmux
${WEBP_DEP_GIF_LIBRARIES})
target_include_directories(gif2webp PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/src)
install(TARGETS gif2webp RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
endif() endif()
if(WEBP_BUILD_IMG2WEBP) if(WEBP_BUILD_IMG2WEBP)
# img2webp # img2webp
include_directories(${WEBP_DEP_IMG_INCLUDE_DIRS}) include_directories(${WEBP_DEP_IMG_INCLUDE_DIRS})
parse_Makefile_am(${CMAKE_CURRENT_SOURCE_DIR}/examples "IMG2WEBP_SRCS" parse_makefile_am(${CMAKE_CURRENT_SOURCE_DIR}/examples "IMG2WEBP_SRCS"
"img2webp") "img2webp")
add_executable(img2webp ${IMG2WEBP_SRCS}) add_executable(img2webp ${IMG2WEBP_SRCS})
target_link_libraries(img2webp exampleutil imagedec imageioutil webp webpmux) target_link_libraries(img2webp
install(TARGETS img2webp RUNTIME DESTINATION bin) exampleutil
set_property(TARGET img2webp PROPERTY INCLUDE_DIRECTORIES imagedec
${CMAKE_CURRENT_SOURCE_DIR}/src ${CMAKE_CURRENT_BINARY_DIR}/src) imageioutil
webp
libwebpmux)
target_include_directories(img2webp PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/src)
install(TARGETS img2webp RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
endif() endif()
if (WEBP_BUILD_WEBPINFO) if(WEBP_BUILD_VWEBP)
# vwebp
find_package(GLUT)
if(GLUT_FOUND)
include_directories(${WEBP_DEP_IMG_INCLUDE_DIRS})
parse_makefile_am(${CMAKE_CURRENT_SOURCE_DIR}/examples "VWEBP_SRCS" "vwebp")
add_executable(vwebp ${VWEBP_SRCS})
target_link_libraries(vwebp
${OPENGL_LIBRARIES}
exampleutil
GLUT::GLUT
imageioutil
webp
webpdemux)
target_include_directories(vwebp
PRIVATE GLUT::GLUT
${CMAKE_CURRENT_BINARY_DIR}/src
${OPENGL_INCLUDE_DIR})
install(TARGETS vwebp RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
if(${CMAKE_SYSTEM_NAME} STREQUAL "Darwin")
check_c_compiler_flag("-Wno-deprecated-declarations" HAS_NO_DEPRECATED)
if(HAS_NO_DEPRECATED)
target_compile_options(vwebp PRIVATE "-Wno-deprecated-declarations")
endif()
endif()
endif()
endif()
if(WEBP_BUILD_WEBPINFO)
# webpinfo # webpinfo
include_directories(${WEBP_DEP_IMG_INCLUDE_DIRS}) include_directories(${WEBP_DEP_IMG_INCLUDE_DIRS})
parse_Makefile_am(${CMAKE_CURRENT_SOURCE_DIR}/examples "WEBPINFO_SRCS" parse_makefile_am(${CMAKE_CURRENT_SOURCE_DIR}/examples "WEBPINFO_SRCS"
"webpinfo") "webpinfo")
add_executable(webpinfo ${WEBPINFO_SRCS}) add_executable(webpinfo ${WEBPINFO_SRCS})
target_link_libraries(webpinfo exampleutil imageioutil) target_link_libraries(webpinfo exampleutil imageioutil)
install(TARGETS webpinfo RUNTIME DESTINATION bin) target_include_directories(webpinfo PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/src)
set_property(TARGET webpinfo PROPERTY INCLUDE_DIRECTORIES install(TARGETS webpinfo RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
${CMAKE_CURRENT_SOURCE_DIR}/src ${CMAKE_CURRENT_BINARY_DIR}/src) endif()
if(WEBP_BUILD_WEBPMUX)
# webpmux
parse_makefile_am(${CMAKE_CURRENT_SOURCE_DIR}/examples "WEBPMUX_SRCS"
"webpmux")
add_executable(webpmux ${WEBPMUX_SRCS})
target_link_libraries(webpmux exampleutil imageioutil libwebpmux webp)
target_include_directories(webpmux PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/src)
install(TARGETS webpmux RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
endif()
if(WEBP_BUILD_EXTRAS)
set(EXTRAS_MAKEFILE "${CMAKE_CURRENT_SOURCE_DIR}/extras")
parse_makefile_am(${EXTRAS_MAKEFILE} "WEBP_EXTRAS_SRCS" "libwebpextras_la")
parse_makefile_am(${EXTRAS_MAKEFILE} "GET_DISTO_SRCS" "get_disto")
parse_makefile_am(${EXTRAS_MAKEFILE} "WEBP_QUALITY_SRCS" "webp_quality")
parse_makefile_am(${EXTRAS_MAKEFILE} "VWEBP_SDL_SRCS" "vwebp_sdl")
# get_disto
add_executable(get_disto ${GET_DISTO_SRCS})
target_link_libraries(get_disto imagedec)
target_include_directories(get_disto
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
${CMAKE_CURRENT_SOURCE_DIR}/src
${CMAKE_CURRENT_BINARY_DIR}/src)
install(TARGETS get_disto RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
# webp_quality
add_executable(webp_quality ${WEBP_QUALITY_SRCS} ${WEBP_EXTRAS_SRCS})
target_link_libraries(webp_quality exampleutil imagedec)
target_include_directories(webp_quality PRIVATE ${CMAKE_CURRENT_SOURCE_DIR})
install(TARGETS webp_quality RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
# vwebp_sdl
find_package(SDL)
if(SDL_FOUND)
add_executable(vwebp_sdl ${VWEBP_SDL_SRCS})
target_link_libraries(vwebp_sdl ${SDL_LIBRARY} imageioutil webp)
target_include_directories(vwebp_sdl
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
${CMAKE_CURRENT_SOURCE_DIR}/src
${CMAKE_CURRENT_BINARY_DIR}
${CMAKE_CURRENT_BINARY_DIR}/src
${SDL_INCLUDE_DIR})
set(WEBP_HAVE_SDL 1)
target_compile_definitions(vwebp_sdl PUBLIC WEBP_HAVE_SDL)
install(TARGETS vwebp_sdl RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
endif()
endif() endif()
if(WEBP_BUILD_WEBP_JS) if(WEBP_BUILD_WEBP_JS)
# JavaScript version # JavaScript version
add_executable(webp_js add_executable(webp_js ${CMAKE_CURRENT_SOURCE_DIR}/extras/webp_to_sdl.c)
${CMAKE_CURRENT_SOURCE_DIR}/extras/webp_to_sdl.c)
target_link_libraries(webp_js webpdecoder SDL) target_link_libraries(webp_js webpdecoder SDL)
target_include_directories(webp_js PRIVATE ${CMAKE_CURRENT_BINARY_DIR})
set(WEBP_HAVE_SDL 1) set(WEBP_HAVE_SDL 1)
set_target_properties(webp_js PROPERTIES LINK_FLAGS set_target_properties(
"-s EXPORTED_FUNCTIONS='[\"_WebpToSDL\"]' -s INVOKE_RUN=0") webp_js
PROPERTIES LINK_FLAGS
"-s EXPORTED_FUNCTIONS='[\"_WebpToSDL\"]' -s INVOKE_RUN=0 \
-s EXTRA_EXPORTED_RUNTIME_METHODS='[\"cwrap\"]'")
set_target_properties(webp_js PROPERTIES OUTPUT_NAME webp) set_target_properties(webp_js PROPERTIES OUTPUT_NAME webp)
target_compile_definitions(webp_js PUBLIC EMSCRIPTEN WEBP_HAVE_SDL) target_compile_definitions(webp_js PUBLIC EMSCRIPTEN WEBP_HAVE_SDL)
# WASM version # WASM version
add_executable(webp_wasm add_executable(webp_wasm ${CMAKE_CURRENT_SOURCE_DIR}/extras/webp_to_sdl.c)
${CMAKE_CURRENT_SOURCE_DIR}/extras/webp_to_sdl.c)
target_link_libraries(webp_wasm webpdecoder SDL) target_link_libraries(webp_wasm webpdecoder SDL)
set_target_properties(webp_wasm PROPERTIES LINK_FLAGS target_include_directories(webp_wasm PRIVATE ${CMAKE_CURRENT_BINARY_DIR})
"-s WASM=1 -s 'BINARYEN_METHOD=\"native-wasm\"' \ set_target_properties(
-s EXPORTED_FUNCTIONS='[\"_WebpToSDL\"]' -s INVOKE_RUN=0") webp_wasm
PROPERTIES LINK_FLAGS "-s WASM=1 -s 'BINARYEN_METHOD=\"native-wasm\"' \
-s EXPORTED_FUNCTIONS='[\"_WebpToSDL\"]' -s INVOKE_RUN=0 \
-s EXTRA_EXPORTED_RUNTIME_METHODS='[\"cwrap\"]'")
target_compile_definitions(webp_wasm PUBLIC EMSCRIPTEN WEBP_HAVE_SDL) target_compile_definitions(webp_wasm PUBLIC EMSCRIPTEN WEBP_HAVE_SDL)
target_compile_definitions(webpdecoder PUBLIC EMSCRIPTEN) target_compile_definitions(webpdspdecode PUBLIC EMSCRIPTEN)
endif() endif()
# Generate the config.h file. if(WEBP_BUILD_ANIM_UTILS)
configure_file(${CMAKE_CURRENT_LIST_DIR}/cmake/config.h.in # anim_diff
${CMAKE_CURRENT_BINARY_DIR}/src/webp/config.h) include_directories(${WEBP_DEP_IMG_INCLUDE_DIRS} ${WEBP_DEP_GIF_INCLUDE_DIRS})
add_definitions(-DHAVE_CONFIG_H) parse_makefile_am(${CMAKE_CURRENT_SOURCE_DIR}/examples "ANIM_DIFF_SRCS"
# The webp folder is included as we reference config.h as "anim_diff")
# ../webp/config.h or webp/config.h add_executable(anim_diff ${ANIM_DIFF_SRCS})
include_directories(${CMAKE_CURRENT_BINARY_DIR}) target_link_libraries(anim_diff
exampleutil
imagedec
imageenc
imageioutil
webp
libwebpmux
webpdemux
${WEBP_DEP_GIF_LIBRARIES})
target_include_directories(anim_diff PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/src)
# anim_dump
include_directories(${WEBP_DEP_IMG_INCLUDE_DIRS} ${WEBP_DEP_GIF_INCLUDE_DIRS})
parse_makefile_am(${CMAKE_CURRENT_SOURCE_DIR}/examples "ANIM_DUMP_SRCS"
"anim_dump")
add_executable(anim_dump ${ANIM_DUMP_SRCS})
target_link_libraries(anim_dump
exampleutil
imagedec
imageenc
imageioutil
webp
libwebpmux
webpdemux
${WEBP_DEP_GIF_LIBRARIES})
target_include_directories(anim_dump PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/src)
endif()
# Install the different headers and libraries. # Install the different headers and libraries.
install( include(GNUInstallDirs)
TARGETS ${INSTALLED_LIBRARIES} install(TARGETS ${INSTALLED_LIBRARIES}
EXPORT WebPTargets EXPORT ${PROJECT_NAME}Targets
PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/webp PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/webp
INCLUDES INCLUDES
DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
set(ConfigPackageLocation ${CMAKE_INSTALL_DATADIR}/WebP/cmake/) set(ConfigPackageLocation ${CMAKE_INSTALL_DATADIR}/${PROJECT_NAME}/cmake/)
install(EXPORT WebPTargets NAMESPACE WebP:: install(EXPORT ${PROJECT_NAME}Targets
NAMESPACE ${PROJECT_NAME}::
DESTINATION ${ConfigPackageLocation}) DESTINATION ${ConfigPackageLocation})
# Create the CMake version file. # Create the CMake version file.
@ -368,30 +608,38 @@ include(CMakePackageConfigHelpers)
write_basic_package_version_file( write_basic_package_version_file(
"${CMAKE_CURRENT_BINARY_DIR}/WebPConfigVersion.cmake" "${CMAKE_CURRENT_BINARY_DIR}/WebPConfigVersion.cmake"
VERSION ${PACKAGE_VERSION} VERSION ${PACKAGE_VERSION}
COMPATIBILITY AnyNewerVersion COMPATIBILITY AnyNewerVersion)
)
# Create the Config file. # Create the Config file.
include(CMakePackageConfigHelpers) include(CMakePackageConfigHelpers)
set(ConfigPackageLocation share/WebP/cmake/)
configure_package_config_file( configure_package_config_file(
${CMAKE_CURRENT_SOURCE_DIR}/cmake/WebPConfig.cmake.in ${CMAKE_CURRENT_SOURCE_DIR}/cmake/WebPConfig.cmake.in
${CMAKE_CURRENT_BINARY_DIR}/WebPConfig.cmake ${CMAKE_CURRENT_BINARY_DIR}/WebPConfig.cmake
INSTALL_DESTINATION ${ConfigPackageLocation} INSTALL_DESTINATION
PATH_VARS CMAKE_INSTALL_INCLUDEDIR) ${ConfigPackageLocation})
# Install the generated CMake files. # Install the generated CMake files.
install( install(FILES "${CMAKE_CURRENT_BINARY_DIR}/WebPConfigVersion.cmake"
FILES "${CMAKE_CURRENT_BINARY_DIR}/WebPConfigVersion.cmake" "${CMAKE_CURRENT_BINARY_DIR}/WebPConfig.cmake"
"${CMAKE_CURRENT_BINARY_DIR}/WebPConfig.cmake" DESTINATION ${ConfigPackageLocation})
DESTINATION ${ConfigPackageLocation}
)
# Install the man pages. # Install the man pages.
set(MAN_PAGES cwebp.1 dwebp.1 gif2webp.1 img2webp.1 vwebp.1 webpmux.1 set(MAN_PAGES
webpinfo.1) cwebp.1
set(EXEC_BUILDS "CWEBP" "DWEBP" "GIF2WEBP" "IMG2WEBP" "VWEBP" "WEBPMUX" dwebp.1
"WEBPINFO") gif2webp.1
img2webp.1
vwebp.1
webpmux.1
webpinfo.1)
set(EXEC_BUILDS
"CWEBP"
"DWEBP"
"GIF2WEBP"
"IMG2WEBP"
"VWEBP"
"WEBPMUX"
"WEBPINFO")
list(LENGTH MAN_PAGES MAN_PAGES_LENGTH) list(LENGTH MAN_PAGES MAN_PAGES_LENGTH)
math(EXPR MAN_PAGES_RANGE "${MAN_PAGES_LENGTH} - 1") math(EXPR MAN_PAGES_RANGE "${MAN_PAGES_LENGTH} - 1")
@ -400,8 +648,7 @@ foreach(I_MAN RANGE ${MAN_PAGES_RANGE})
if(WEBP_BUILD_${EXEC_BUILD}) if(WEBP_BUILD_${EXEC_BUILD})
list(GET MAN_PAGES ${I_MAN} MAN_PAGE) list(GET MAN_PAGES ${I_MAN} MAN_PAGE)
install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/man/${MAN_PAGE} install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/man/${MAN_PAGE}
DESTINATION ${CMAKE_INSTALL_PREFIX}/share/man/man1 DESTINATION ${CMAKE_INSTALL_MANDIR}/man1
COMPONENT doc COMPONENT doc)
)
endif() endif()
endforeach() endforeach()

176
ChangeLog
View File

@ -1,9 +1,185 @@
fa8210e4 Fix pair update in stochastic entropy merging.
825389ac README.mux: add a reference to the AnimDecoder API
3be698c3 CMake: fix webp_js compilation
4cbb4caf update NEWS
f5a5918d bump version to 1.0.1
d61385db Speed-up: Make sure we only initialize histograms when needed.
0c570316 update AUTHORS
301a2dda img2webp: add help note about arguments from a file
f0abab92 Speedups for empty histograms.
f2dfd925 Split HistogramAdd to only have the high level logic in C.
06b7bc7d Fix compilation on windows and clang-cl+ninja.
98179495 remove some minor TODOs
cbf82cc0 Remove AVX2 files.
5030e902 Merge "TIFF decoder: remove unused KINV definition"
ac543311 Remove a few more useless #defines
123d3306 TIFF decoder: remove unused KINV definition
ef1094b0 Merge "- install pkg-config files during the CMake build"
b911fbc9 libwebp: Remove duplicate GIFDisplayError in anim_util
eee00b66 - install pkg-config files during the CMake build
ac3ec8c9 Merge "Clean-up the common sources in dsp."
3e13da7b Clean-up the common sources in dsp.
5c395f1d libwebp: cmake-format all
e7a69729 libwebp: Add extras targets in CMakeLists.txt
e52485d6 libwebp: Rename macros in webpmux.c
92dc0f09 clean-up MakeInputImageCopy()
39952de2 VP8IteratorImport: add missing 'const'
382af7a2 clean-up WebPBlendAlpha
14d020f6 libwebp: Use ExUtilGet*() in anim_diff
0d92ff25 libwebp: remove useless variable in gif2webp
556cb1b4 Merge "CMake: Set WEBP_BUILD_GIF2WEBP to off"
da26ee49 CMake: Set WEBP_BUILD_GIF2WEBP to off
b2a867c0 cwebp: Don't premultiply during -resize if -exact
637141bc pngdec: fix build w/libpng < 1.4.x
bc5092b1 pngdec: set memory functions
50d8345a Fix CMake math library.
6aa3e8aa Fix math library on Visual Studio.
d71df4e2 Fix math library finding in CMake.
de08d727 cosmetics: normalize include guard comment
009562b4 vwebp: Fix bug when Dispose then NoBlend frames
423f2579 Fix up CMake to create targets.
907208f9 Wait for all threads to be done in DecodeRemaining.
4649b3c4 vwebp: Add background color display option
78ad57a3 Fix bad glClearColor parameters
da96d8d9 Allow for a non-initialized alpha decompressor in DoRemap.
2563db47 fix rescaling rounding inaccuracy
211f37ee fix endian problems in pattern copy
5f0f5c07 Make sure partition #0 is read before VP8 data in IDecode.
de98732b fix GetColorf() bug
4338cd36 misc fixes in libwebpmux
e00af13e fix signatures after a9ceda7ff1
a9ceda7f Speed-up chunk list operations.
2281bbf6 Merge "Better handling of bogus Huffman codes."
39cb9aad Better handling of bogus Huffman codes.
89cc9d37 Merge "fix read-overflow while parsing VP8X chunk"
95fd6507 fix read-overflow while parsing VP8X chunk
9e729fe1 Fix VP8IoTeardownHook being called twice on worker sync failure
29fb8562 Merge "muxread,anmf: fail on multiple image chunks"
eb82ce76 muxread,anmf: fail on multiple image chunks
1344a2e9 fix alpha-filtering crash when image width is larger than radius
be738c6d muxread,ChunkVerifyAndAssign: validate chunk_size
2c70ad76 muxread,CreateInternal: fix riff size checks
569001f1 Fix for thread race heap-use-after-free
c56a02d9 Android.mk: use LOCAL_EXPORT_C_INCLUDES w/public libs
15795596 CMakeLists.txt,cosmetics: normalize if() formatting
1a44c233 Merge "cmake: add support for webpmux"
e9569ad7 Merge "configure,*am,cosmetics: s/WANT_/BUILD_/"
35c7de6f cmake: add support for webpmux
0f25e61c WebpToSDL(): fix the return value in case of error
5d8985de configure,*am,cosmetics: s/WANT_/BUILD_/
895fd28f Merge "man/Makefile.am: add img2webp.1"
5cf3e2af man/Makefile.am: add img2webp.1
2a9de5b9 Add build rules for anim_diff & anim_dump utils.
71ed73cf fix invalid check for buffer size
af0e4fbb gif2webp: fix transcode of loop count=65535
dce5d764 Limit memory allocation when reading invalid Huffman codes.
f9df0081 Merge "cmake: quiet glut deprecation warnings on OS X"
dc39b16f webpmux.1: correct grammar
c7aa1264 cwebp.c: fix a missing \n
53aa51e9 Merge tag 'v1.0.0'
698b8844 update ChangeLog (tag: v1.0.0)
8d510751 webp-container-spec: correct frame duration=0 note
e6b2164e vwebp: Copy Chrome's behavior w/frame duration == 0
094b3b28 cmake: quiet glut deprecation warnings on OS X
71c39a06 webp-container-spec: correct frame duration=0 note
fd3d5756 vwebp: Copy Chrome's behavior w/frame duration == 0
b0c966fb Build vwebp from CMake.
d20b7707 update ChangeLog (tag: v1.0.0-rc3)
0d5fad46 add WEBP_DSP_INIT / WEBP_DSP_INIT_FUNC
d77bf512 add WEBP_DSP_INIT / WEBP_DSP_INIT_FUNC
c1cb86af fix 16b overflow in SSE2
e577feb7 makefile.unix: add DEBUG flag for compiling w/ debug-symbol
99be34b3 cwebp,get_disto: fix bpp output
e122e511 cwebp,get_disto: fix bpp output
f5565ca8 cmake: Make sure we use near-lossless by default.
d898dc14 fix bug in WebPImport565: alpha value was not set
1c8f358d Fix CMake with WASM.
a0215fb7 webp_js: fix webp_js demo html
882784b0 update ChangeLog (tag: v1.0.0-rc2)
2f930e08 Revert "Use proper targets for CMake."
8165e8fb Use proper targets for CMake.
3f157dd5 Remove some very hard TODOs.
abb47760 Merge "Use proper targets for CMake."
cd758a17 {de,}mux/Makefile.am: add missing headers
e155dda0 Use proper targets for CMake.
b892b8ba makefile.unix,dist: use ascii for text output
64a57d05 add -version option to anim_dump,anim_diff and img2webp
994be82d Merge "Remove some very hard TODOs."
4033e1d7 Remove some very hard TODOs.
fc1b8e3a webp_js: fix webp_js demo html
15aa48d9 update ChangeLog (tag: v1.0.0-rc1)
e607dabc update AUTHORS
38410c08 [CFI] Remove function pointer casts
978eec25 [CFI] Remove function pointer casts
c57b2736 bump version to 1.0.0
cba28853 update NEWS
c909d531 Merge "remove some deprecation warning on MacOSX"
217443c7 remove some deprecation warning on MacOSX
b672bdfa configure: quiet glut deprecation warnings on OS X
daa9fcaf configure: use sdl-config if available
dd174cae Merge "imagedec: support metadata reading for WebP image decoding"
641cedcc imagedec: support metadata reading for WebP image decoding
065b2ce1 anim_diff: add a couple missing newlines in Help()
c4cc1147 Merge "gif2webp: force low duration frames to 100ms"
09333097 gif2webp: force low duration frames to 100ms
e03f0ec3 sharp_yuv: use 14b fixed-point precision for gamma
b2db361c image_enc,WebPWritePNG: move locals after setjmp
74e82ec6 Merge "WebPPictureDistortion: fix big-endian results order"
645d04ca Merge "cwebp,get_disto: report bpp"
120f58c3 Merge "lossless*sse2: improve non-const 16-bit vector creation"
a7fe9412 WebPPictureDistortion: fix big-endian results order
e26fe066 cwebp,get_disto: report bpp
9df64e28 Merge changes Id5b4a1a4,Ia20ce844
8043504f lossless*sse2: improve non-const 16-bit vector creation
1e3dfc48 Import: extract condition from loop
3b07d327 Import,RGBA: fix for BigEndian import
551948e4 Remove unused argument in VP8LBitsEntropy.
3005237a ReadWebP: fix for big-endian
499c395a Merge "anim_diff: expose the -max_diff option"
f69dcd69 Merge "remove WEBP_EXPERIMENTAL_FEATURES"
07d884d5 anim_diff: expose the -max_diff option
f4dd9256 remove WEBP_EXPERIMENTAL_FEATURES
94a8377b extract the command-line parsing helpers to example_util
fc09e6e2 PNM decoder: prevent unsupported depth=2 PAM case.
6de58603 MIPS64: Fix defined-but-not-used errors with WEBP_REDUCE_CSP
cbde5728 gif2webp: add support for reading from stdin
cf1c5054 Add an SSE4 version of some lossless color transforms.
45a8b5eb Fix lint error with man page.
cff38e8f Merge "PNG decoder: handle gAMA chunk"
59cb1a48 Merge "enable dc error-diffusion always"
78318b30 PNG decoder: handle gAMA chunk
664c21dd Merge "remove some TODOs"
815652de enable dc error-diffusion always
aec45cec remove some TODOs
5715dfce fix block-count[] increment in case of large image
c2d04f3e enable DC error-diffusion always for multi-pass
96bf07c5 use DC error diffusion for U/V at low-quality
1c59020b fix missing sse41 targets in makefile.unix
7a8e814b cosmetics: s/color_space/colorspace/
05f6fe24 upsampling: rm asserts w/REDUCE_CSP+OMIT_C_CODE
b4cf5597 Merge "Upsampling SSE2/SSE4 speedup."
ccbeb32c Makefile.vc: add missing sse41 files
55403a9a Upsampling SSE2/SSE4 speedup.
807b53c4 Implement the upsampling/yuv functions in SSE41
84101a81 Fix wasm WebP compilation
8bebd2a3 fix warning on MSVC
a7f93fe3 webpmux: allow reading argument from a file
b69f18a7 gif2webp.1: fix -loop_compatibility layout
72d530c0 Merge "fix lossless decoding w/WEBP_REDUCE_SIZE"
296c7dc4 fix lossless decoding w/WEBP_REDUCE_SIZE
0d5d029c Merge "ImgIoUtilReadFile: fix file leak upon error"
ae568ce7 ImgIoUtilReadFile: fix file leak upon error
796b5a8a Merge tag 'v0.6.1'
6b7a95fd update ChangeLog (tag: v0.6.1)
f66955de WEBP_REDUCE_CSP: restrict colorspace support f66955de WEBP_REDUCE_CSP: restrict colorspace support
1af0df76 Merge "WEBP_REDUCE_CSP: restrict colorspace support"
6de20df0 WEBP_REDUCE_CSP: restrict colorspace support
a289d8e7 update ChangeLog (tag: v0.6.1-rc2) a289d8e7 update ChangeLog (tag: v0.6.1-rc2)
c10a493c vwebp: disable double buffering on windows & mac c10a493c vwebp: disable double buffering on windows & mac
0d4466c2 webp_to_sdl.c: fix file mode 0d4466c2 webp_to_sdl.c: fix file mode
1b27bf8b WEBP_REDUCE_SIZE: disable all rescaler code 1b27bf8b WEBP_REDUCE_SIZE: disable all rescaler code
126be109 webpinfo: add -version option 126be109 webpinfo: add -version option
0df22b9e WEBP_REDUCE_SIZE: disable all rescaler code
9add62b5 bump version to 0.6.1 9add62b5 bump version to 0.6.1
d3e26144 update NEWS d3e26144 update NEWS
2edda639 README: add webpinfo section 2edda639 README: add webpinfo section

View File

@ -2,7 +2,7 @@ ACLOCAL_AMFLAGS = -I m4
SUBDIRS = src imageio man SUBDIRS = src imageio man
EXTRA_DIST = COPYING autogen.sh EXTRA_DIST = COPYING autogen.sh
if WANT_EXTRAS if BUILD_EXTRAS
SUBDIRS += extras SUBDIRS += extras
endif endif

View File

@ -53,11 +53,6 @@ OUTDIR = ..\obj\
OUTDIR = $(OBJDIR) OUTDIR = $(OBJDIR)
!ENDIF !ENDIF
!IF "$(HAVE_AVX2)" == "1"
CFLAGS = $(CFLAGS) /DWEBP_HAVE_AVX2
AVX2_FLAGS = /arch:AVX2
!ENDIF
############################################################## ##############################################################
# Runtime library configuration # Runtime library configuration
!IF "$(RTLIBCFG)" == "static" !IF "$(RTLIBCFG)" == "static"
@ -227,11 +222,13 @@ DSP_DEC_OBJS = \
$(DIROBJ)\dsp\upsampling_msa.obj \ $(DIROBJ)\dsp\upsampling_msa.obj \
$(DIROBJ)\dsp\upsampling_neon.obj \ $(DIROBJ)\dsp\upsampling_neon.obj \
$(DIROBJ)\dsp\upsampling_sse2.obj \ $(DIROBJ)\dsp\upsampling_sse2.obj \
$(DIROBJ)\dsp\upsampling_sse41.obj \
$(DIROBJ)\dsp\yuv.obj \ $(DIROBJ)\dsp\yuv.obj \
$(DIROBJ)\dsp\yuv_mips32.obj \ $(DIROBJ)\dsp\yuv_mips32.obj \
$(DIROBJ)\dsp\yuv_mips_dsp_r2.obj \ $(DIROBJ)\dsp\yuv_mips_dsp_r2.obj \
$(DIROBJ)\dsp\yuv_neon.obj \ $(DIROBJ)\dsp\yuv_neon.obj \
$(DIROBJ)\dsp\yuv_sse2.obj \ $(DIROBJ)\dsp\yuv_sse2.obj \
$(DIROBJ)\dsp\yuv_sse41.obj \
DSP_ENC_OBJS = \ DSP_ENC_OBJS = \
$(DIROBJ)\dsp\cost.obj \ $(DIROBJ)\dsp\cost.obj \
@ -239,7 +236,6 @@ DSP_ENC_OBJS = \
$(DIROBJ)\dsp\cost_mips_dsp_r2.obj \ $(DIROBJ)\dsp\cost_mips_dsp_r2.obj \
$(DIROBJ)\dsp\cost_sse2.obj \ $(DIROBJ)\dsp\cost_sse2.obj \
$(DIROBJ)\dsp\enc.obj \ $(DIROBJ)\dsp\enc.obj \
$(DIROBJ)\dsp\enc_avx2.obj \
$(DIROBJ)\dsp\enc_mips32.obj \ $(DIROBJ)\dsp\enc_mips32.obj \
$(DIROBJ)\dsp\enc_mips_dsp_r2.obj \ $(DIROBJ)\dsp\enc_mips_dsp_r2.obj \
$(DIROBJ)\dsp\enc_msa.obj \ $(DIROBJ)\dsp\enc_msa.obj \
@ -285,7 +281,6 @@ ENC_OBJS = \
$(DIROBJ)\enc\backward_references_enc.obj \ $(DIROBJ)\enc\backward_references_enc.obj \
$(DIROBJ)\enc\config_enc.obj \ $(DIROBJ)\enc\config_enc.obj \
$(DIROBJ)\enc\cost_enc.obj \ $(DIROBJ)\enc\cost_enc.obj \
$(DIROBJ)\enc\delta_palettization_enc.obj \
$(DIROBJ)\enc\filter_enc.obj \ $(DIROBJ)\enc\filter_enc.obj \
$(DIROBJ)\enc\frame_enc.obj \ $(DIROBJ)\enc\frame_enc.obj \
$(DIROBJ)\enc\histogram_enc.obj \ $(DIROBJ)\enc\histogram_enc.obj \
@ -367,9 +362,11 @@ $(DIRBIN)\anim_dump.exe: $(EX_GIF_DEC_OBJS) $(LIBWEBPDEMUX) $(LIBWEBP)
$(DIRBIN)\anim_dump.exe: $(IMAGEIO_ENC_OBJS) $(DIRBIN)\anim_dump.exe: $(IMAGEIO_ENC_OBJS)
$(DIRBIN)\cwebp.exe: $(DIROBJ)\examples\cwebp.obj $(IMAGEIO_DEC_OBJS) $(DIRBIN)\cwebp.exe: $(DIROBJ)\examples\cwebp.obj $(IMAGEIO_DEC_OBJS)
$(DIRBIN)\cwebp.exe: $(IMAGEIO_UTIL_OBJS) $(DIRBIN)\cwebp.exe: $(IMAGEIO_UTIL_OBJS)
$(DIRBIN)\cwebp.exe: $(LIBWEBPDEMUX)
$(DIRBIN)\dwebp.exe: $(DIROBJ)\examples\dwebp.obj $(IMAGEIO_DEC_OBJS) $(DIRBIN)\dwebp.exe: $(DIROBJ)\examples\dwebp.obj $(IMAGEIO_DEC_OBJS)
$(DIRBIN)\dwebp.exe: $(IMAGEIO_ENC_OBJS) $(DIRBIN)\dwebp.exe: $(IMAGEIO_ENC_OBJS)
$(DIRBIN)\dwebp.exe: $(IMAGEIO_UTIL_OBJS) $(DIRBIN)\dwebp.exe: $(IMAGEIO_UTIL_OBJS)
$(DIRBIN)\dwebp.exe: $(LIBWEBPDEMUX)
$(DIRBIN)\gif2webp.exe: $(DIROBJ)\examples\gif2webp.obj $(EX_GIF_DEC_OBJS) $(DIRBIN)\gif2webp.exe: $(DIROBJ)\examples\gif2webp.obj $(EX_GIF_DEC_OBJS)
$(DIRBIN)\gif2webp.exe: $(EX_UTIL_OBJS) $(IMAGEIO_UTIL_OBJS) $(LIBWEBPMUX) $(DIRBIN)\gif2webp.exe: $(EX_UTIL_OBJS) $(IMAGEIO_UTIL_OBJS) $(LIBWEBPMUX)
$(DIRBIN)\gif2webp.exe: $(LIBWEBP) $(DIRBIN)\gif2webp.exe: $(LIBWEBP)
@ -382,26 +379,24 @@ $(DIRBIN)\webpmux.exe: $(DIROBJ)\examples\webpmux.obj $(LIBWEBPMUX)
$(DIRBIN)\webpmux.exe: $(EX_UTIL_OBJS) $(IMAGEIO_UTIL_OBJS) $(LIBWEBP) $(DIRBIN)\webpmux.exe: $(EX_UTIL_OBJS) $(IMAGEIO_UTIL_OBJS) $(LIBWEBP)
$(DIRBIN)\img2webp.exe: $(DIROBJ)\examples\img2webp.obj $(LIBWEBPMUX) $(DIRBIN)\img2webp.exe: $(DIROBJ)\examples\img2webp.obj $(LIBWEBPMUX)
$(DIRBIN)\img2webp.exe: $(IMAGEIO_DEC_OBJS) $(DIRBIN)\img2webp.exe: $(IMAGEIO_DEC_OBJS)
$(DIRBIN)\img2webp.exe: $(EX_UTIL_OBJS) $(IMAGEIO_UTIL_OBJS) $(LIBWEBP) $(DIRBIN)\img2webp.exe: $(EX_UTIL_OBJS) $(IMAGEIO_UTIL_OBJS)
$(DIRBIN)\img2webp.exe: $(LIBWEBPDEMUX) $(LIBWEBP)
$(DIRBIN)\get_disto.exe: $(DIROBJ)\extras\get_disto.obj $(DIRBIN)\get_disto.exe: $(DIROBJ)\extras\get_disto.obj
$(DIRBIN)\get_disto.exe: $(IMAGEIO_DEC_OBJS) $(IMAGEIO_UTIL_OBJS) $(LIBWEBP) $(DIRBIN)\get_disto.exe: $(IMAGEIO_DEC_OBJS) $(IMAGEIO_UTIL_OBJS)
$(DIRBIN)\get_disto.exe: $(LIBWEBPDEMUX) $(LIBWEBP)
$(DIRBIN)\webp_quality.exe: $(DIROBJ)\extras\webp_quality.obj $(DIRBIN)\webp_quality.exe: $(DIROBJ)\extras\webp_quality.obj
$(DIRBIN)\webp_quality.exe: $(IMAGEIO_UTIL_OBJS) $(DIRBIN)\webp_quality.exe: $(IMAGEIO_UTIL_OBJS)
$(DIRBIN)\webp_quality.exe: $(EXTRAS_OBJS) $(LIBWEBP) $(DIRBIN)\webp_quality.exe: $(EXTRAS_OBJS) $(LIBWEBP)
$(DIRBIN)\webpinfo.exe: $(DIROBJ)\examples\webpinfo.obj $(DIRBIN)\webpinfo.exe: $(DIROBJ)\examples\webpinfo.obj
$(DIRBIN)\webpinfo.exe: $(IMAGEIO_DEC_OBJS) $(DIRBIN)\webpinfo.exe: $(IMAGEIO_DEC_OBJS)
$(DIRBIN)\webpinfo.exe: $(EX_UTIL_OBJS) $(IMAGEIO_UTIL_OBJS) $(LIBWEBP) $(DIRBIN)\webpinfo.exe: $(EX_UTIL_OBJS) $(IMAGEIO_UTIL_OBJS)
$(DIRBIN)\webpinfo.exe: $(LIBWEBPDEMUX) $(LIBWEBP)
$(OUT_EXAMPLES): $(EX_UTIL_OBJS) $(LIBWEBP) $(OUT_EXAMPLES): $(EX_UTIL_OBJS) $(LIBWEBP)
$(EX_UTIL_OBJS) $(IMAGEIO_UTIL_OBJS): $(OUTPUT_DIRS) $(EX_UTIL_OBJS) $(IMAGEIO_UTIL_OBJS): $(OUTPUT_DIRS)
$(IMAGEIO_DEC_OBJS) $(IMAGEIO_ENC_OBJS) $(EXTRAS_OBJS): $(OUTPUT_DIRS) $(IMAGEIO_DEC_OBJS) $(IMAGEIO_ENC_OBJS) $(EXTRAS_OBJS): $(OUTPUT_DIRS)
!ENDIF # ARCH == ARM !ENDIF # ARCH == ARM
experimental:
$(MAKE) /f Makefile.vc \
CFG=$(CFG) \
CFLAGS="$(CFLAGS) /DWEBP_EXPERIMENTAL_FEATURES" /$(MAKEFLAGS)
$(LIBWEBPDECODER): $(LIBWEBPDECODER_OBJS) $(LIBWEBPDECODER): $(LIBWEBPDECODER_OBJS)
$(LIBWEBP): $(LIBWEBP_OBJS) $(LIBWEBP): $(LIBWEBP_OBJS)
$(LIBWEBPMUX): $(LIBWEBPMUX_OBJS) $(LIBWEBPMUX): $(LIBWEBPMUX_OBJS)
@ -453,9 +448,6 @@ $(DIROBJ)\$(DLLINC):
.SUFFIXES: .c .obj .res .exe .SUFFIXES: .c .obj .res .exe
# File-specific flag builds. Note batch rules take precedence over wildcards, # File-specific flag builds. Note batch rules take precedence over wildcards,
# so for now name each file individually. # 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
$(DIROBJ)\examples\anim_diff.obj: examples\anim_diff.c $(DIROBJ)\examples\anim_diff.obj: examples\anim_diff.c
$(CC) $(CFLAGS) /DWEBP_HAVE_GIF /Fd$(LIBWEBP_PDBNAME) \ $(CC) $(CFLAGS) /DWEBP_HAVE_GIF /Fd$(LIBWEBP_PDBNAME) \
/Fo$(DIROBJ)\examples\ examples\$(@B).c /Fo$(DIROBJ)\examples\ examples\$(@B).c

22
NEWS
View File

@ -1,3 +1,25 @@
- 11/2/2018: version 1.0.1
This is a binary compatible release.
* lossless encoder speedups
* big-endian fix for alpha decoding (issue #393)
* gif2webp fix for loop count=65535 transcode (issue #382)
* further security related hardening in libwebp & libwebpmux
(issues #383, #385, #386, #387, #388, #391)
(oss-fuzz #9099, #9100, #9105, #9106, #9111, #9112, #9119, #9123, #9170,
#9178, #9179, #9183, #9186, #9191, #9364, #9417, #9496, #10349,
#10423, #10634, #10700, #10838, #10922, #11021, #11088, #11152)
* miscellaneous bug & build fixes (issues #381, #394, #396, #397, #400)
- 4/2/2018: version 1.0.0
This is a binary compatible release.
* lossy encoder improvements to avoid chroma shifts in various circumstances
(issues #308, #340)
* big-endian fixes for decode, RGBA import and WebPPictureDistortion
Tool updates:
gifwebp, anim_diff - default duration behavior (<= 10ms) changed to match
web browsers, transcoding tools (issue #379)
img2webp, webpmux - allow options to be passed in via a file (issue #355)
- 11/24/2017: version 0.6.1 - 11/24/2017: version 0.6.1
This is a binary compatible release. This is a binary compatible release.
* lossless performance and compression improvements + a new 'cruncher' mode * lossless performance and compression improvements + a new 'cruncher' mode

13
README
View File

@ -4,7 +4,7 @@
\__\__/\____/\_____/__/ ____ ___ \__\__/\____/\_____/__/ ____ ___
/ _/ / \ \ / _ \/ _/ / _/ / \ \ / _ \/ _/
/ \_/ / / \ \ __/ \__ / \_/ / / \ \ __/ \__
\____/____/\_____/_____/____/v0.6.1 \____/____/\_____/_____/____/v1.0.1
Description: Description:
============ ============
@ -402,12 +402,14 @@ Options are:
-nofilter .... disable in-loop filtering -nofilter .... disable in-loop filtering
-dither <int> dithering strength (0..100), default=50 -dither <int> dithering strength (0..100), default=50
-noalphadither disable alpha plane dithering -noalphadither disable alpha plane dithering
-usebgcolor .. display background color
-mt .......... use multi-threading -mt .......... use multi-threading
-info ........ print info -info ........ print info
-h ........... this help message -h ........... this help message
Keyboard shortcuts: Keyboard shortcuts:
'c' ................ toggle use of color profile 'c' ................ toggle use of color profile
'b' ................ toggle background color display
'i' ................ overlay file information 'i' ................ overlay file information
'd' ................ disable blending & disposal (debug) 'd' ................ disable blending & disposal (debug)
'q' / 'Q' / ESC .... quit 'q' / 'Q' / ESC .... quit
@ -458,6 +460,7 @@ File-level options (only used at the start of compression):
-mixed ............... use mixed lossy/lossless automatic mode -mixed ............... use mixed lossy/lossless automatic mode
-v ................... verbose mode -v ................... verbose mode
-h ................... this help -h ................... this help
-version ............. print version number and exit
Per-frame options (only used for subsequent images input): Per-frame options (only used for subsequent images input):
-d <int> ............. frame duration in ms (default: 100) -d <int> ............. frame duration in ms (default: 100)
@ -469,6 +472,9 @@ Per-frame options (only used for subsequent images input):
example: img2webp -loop 2 in0.png -lossy in1.jpg example: img2webp -loop 2 in0.png -lossy in1.jpg
-d 80 in2.tiff -o out.webp -d 80 in2.tiff -o out.webp
Note: if a single file name is passed as the argument, the arguments will be
tokenized from this file. The file name must not start with the character '-'.
Animated GIF conversion: Animated GIF conversion:
======================== ========================
Animated GIF files can be converted to WebP files with animation using the Animated GIF files can be converted to WebP files with animation using the
@ -524,6 +530,11 @@ Options:
-min_psnr <float> ... minimum per-frame PSNR -min_psnr <float> ... minimum per-frame PSNR
-raw_comparison ..... if this flag is not used, RGB is -raw_comparison ..... if this flag is not used, RGB is
premultiplied before comparison premultiplied before comparison
-max_diff <int> ..... maximum allowed difference per channel
between corresponding pixels in subsequent
frames
-h .................. this help
-version ............ print version number and exit
Building: Building:
--------- ---------

View File

@ -1,7 +1,7 @@
 __ __ ____ ____ ____ __ __ _ __ __  __ __ ____ ____ ____ __ __ _ __ __
/ \\/ \/ _ \/ _ \/ _ \/ \ \/ \___/_ / _\ / \\/ \/ _ \/ _ \/ _ \/ \ \/ \___/_ / _\
\ / __/ _ \ __/ / / (_/ /__ \ / __/ _ \ __/ / / (_/ /__
\__\__/\_____/_____/__/ \__//_/\_____/__/___/v0.4.1 \__\__/\_____/_____/__/ \__//_/\_____/__/___/v1.0.1
Description: Description:
@ -33,6 +33,7 @@ Usage: webpmux -get GET_OPTIONS INPUT -o OUTPUT
webpmux -info INPUT webpmux -info INPUT
webpmux [-h|-help] webpmux [-h|-help]
webpmux -version webpmux -version
webpmux argument_file_name
GET_OPTIONS: GET_OPTIONS:
Extract relevant data: Extract relevant data:
@ -92,6 +93,9 @@ INPUT & OUTPUT are in WebP format.
Note: The nature of EXIF, XMP and ICC data is not checked and is assumed to be Note: The nature of EXIF, XMP and ICC data is not checked and is assumed to be
valid. valid.
Note: if a single file name is passed as the argument, the arguments will be
tokenized from this file. The file name must not start with the character '-'.
Visualization tool: Visualization tool:
=================== ===================
@ -207,6 +211,35 @@ Code example:
For a detailed AnimEncoder API reference, please refer to the header file For a detailed AnimEncoder API reference, please refer to the header file
(src/webp/mux.h). (src/webp/mux.h).
AnimDecoder API:
================
This AnimDecoder API allows decoding (possibly) animated WebP images.
Code Example:
WebPAnimDecoderOptions dec_options;
WebPAnimDecoderOptionsInit(&dec_options);
// Tune 'dec_options' as needed.
WebPAnimDecoder* dec = WebPAnimDecoderNew(webp_data, &dec_options);
WebPAnimInfo anim_info;
WebPAnimDecoderGetInfo(dec, &anim_info);
for (uint32_t i = 0; i < anim_info.loop_count; ++i) {
while (WebPAnimDecoderHasMoreFrames(dec)) {
uint8_t* buf;
int timestamp;
WebPAnimDecoderGetNext(dec, &buf, &timestamp);
// ... (Render 'buf' based on 'timestamp').
// ... (Do NOT free 'buf', as it is owned by 'dec').
}
WebPAnimDecoderReset(dec);
}
const WebPDemuxer* demuxer = WebPAnimDecoderGetDemuxer(dec);
// ... (Do something using 'demuxer'; e.g. get EXIF/XMP/ICC data).
WebPAnimDecoderDelete(dec);
For a detailed AnimDecoder API reference, please refer to the header file
(src/webp/demux.h).
Bugs: Bugs:
===== =====

View File

@ -32,7 +32,8 @@ using Emscripten and CMake.
webp.js.mem files generated. webp.js.mem files generated.
The callable JavaScript function is WebPToSDL(), which decodes a raw WebP The callable JavaScript function is WebPToSDL(), which decodes a raw WebP
bitstream into a canvas. See webp_js/index.html for a simple usage sample. bitstream into a canvas. See webp_js/index.html for a simple usage sample
(see below for instructions).
Demo HTML page: Demo HTML page:
=============== ===============

View File

@ -152,11 +152,13 @@ model {
include "upsampling_msa.c" include "upsampling_msa.c"
include "upsampling_neon.$NEON" include "upsampling_neon.$NEON"
include "upsampling_sse2.c" include "upsampling_sse2.c"
include "upsampling_sse41.c"
include "yuv.c" include "yuv.c"
include "yuv_mips32.c" include "yuv_mips32.c"
include "yuv_mips_dsp_r2.c" include "yuv_mips_dsp_r2.c"
include "yuv_neon.$NEON" include "yuv_neon.$NEON"
include "yuv_sse2.c" include "yuv_sse2.c"
include "yuv_sse41.c"
srcDir "src/utils" srcDir "src/utils"
include "bit_reader_utils.c" include "bit_reader_utils.c"
include "color_cache_utils.c" include "color_cache_utils.c"
@ -173,7 +175,6 @@ model {
include "cost_mips_dsp_r2.c" include "cost_mips_dsp_r2.c"
include "cost_sse2.c" include "cost_sse2.c"
include "enc.c" include "enc.c"
include "enc_avx2.c"
include "enc_mips32.c" include "enc_mips32.c"
include "enc_mips_dsp_r2.c" include "enc_mips_dsp_r2.c"
include "enc_msa.c" include "enc_msa.c"
@ -196,7 +197,6 @@ model {
include "backward_references_enc.c" include "backward_references_enc.c"
include "config_enc.c" include "config_enc.c"
include "cost_enc.c" include "cost_enc.c"
include "delta_palettization_enc.c"
include "filter_enc.c" include "filter_enc.c"
include "frame_enc.c" include "frame_enc.c"
include "histogram_enc.c" include "histogram_enc.c"
@ -288,6 +288,7 @@ model {
imagedec(NativeLibrarySpec) { imagedec(NativeLibrarySpec) {
binaries { binaries {
all { all {
lib library: "webpdemux", linkage: "static"
lib library: "webp", linkage: "static" lib library: "webp", linkage: "static"
} }
} }
@ -330,6 +331,7 @@ model {
lib library: "example_util", linkage: "static" lib library: "example_util", linkage: "static"
lib library: "imagedec", linkage: "static" lib library: "imagedec", linkage: "static"
lib library: "imageio_util", linkage: "static" lib library: "imageio_util", linkage: "static"
lib library: "webpdemux", linkage: "static"
lib library: "webp", linkage: "static" lib library: "webp", linkage: "static"
} }
} }
@ -350,6 +352,7 @@ model {
lib library: "imagedec", linkage: "static" lib library: "imagedec", linkage: "static"
lib library: "imageenc", linkage: "static" lib library: "imageenc", linkage: "static"
lib library: "imageio_util", linkage: "static" lib library: "imageio_util", linkage: "static"
lib library: "webpdemux", linkage: "static"
lib library: "webp" lib library: "webp"
} }
} }
@ -389,6 +392,7 @@ model {
lib library: "imagedec", linkage: "static" lib library: "imagedec", linkage: "static"
lib library: "imageio_util", linkage: "static" lib library: "imageio_util", linkage: "static"
lib library: "webpmux", linkage: "static" lib library: "webpmux", linkage: "static"
lib library: "webpdemux", linkage: "static"
lib library: "webp" lib library: "webp"
} }
} }

View File

@ -3,17 +3,9 @@ set(WEBP_VERSION ${WebP_VERSION})
@PACKAGE_INIT@ @PACKAGE_INIT@
if(@WEBP_USE_THREAD@) include ("${CMAKE_CURRENT_LIST_DIR}/@PROJECT_NAME@Targets.cmake")
include(CMakeFindDependencyMacro)
find_dependency(Threads REQUIRED)
endif()
include("${CMAKE_CURRENT_LIST_DIR}/WebPTargets.cmake") set(WebP_INCLUDE_DIRS "webp")
set(WEBP_INCLUDE_DIRS ${WebP_INCLUDE_DIRS})
set_and_check(WebP_INCLUDE_DIR "@PACKAGE_CMAKE_INSTALL_INCLUDEDIR@")
set(WebP_INCLUDE_DIRS ${WebP_INCLUDE_DIR})
set(WEBP_INCLUDE_DIRS ${WebP_INCLUDE_DIR})
set(WebP_LIBRARIES "@INSTALLED_LIBRARIES@") set(WebP_LIBRARIES "@INSTALLED_LIBRARIES@")
set(WEBP_LIBRARIES "${WebP_LIBRARIES}") set(WEBP_LIBRARIES "${WebP_LIBRARIES}")
check_required_components(WebP)

View File

@ -103,12 +103,6 @@
/* Version number of package */ /* Version number of package */
#cmakedefine VERSION "@VERSION@" #cmakedefine VERSION "@VERSION@"
/* Enable experimental code */
#cmakedefine WEBP_EXPERIMENTAL_FEATURES 1
/* Set to 1 if AVX2 is supported */
#cmakedefine WEBP_HAVE_AVX2 1
/* Set to 1 if GIF library is installed */ /* Set to 1 if GIF library is installed */
#cmakedefine WEBP_HAVE_GIF 1 #cmakedefine WEBP_HAVE_GIF 1

View File

@ -1,4 +1,4 @@
## Check for SIMD extensions. # Check for SIMD extensions.
include(CMakePushCheckState) include(CMakePushCheckState)
function(webp_check_compiler_flag WEBP_SIMD_FLAG ENABLE_SIMD) function(webp_check_compiler_flag WEBP_SIMD_FLAG ENABLE_SIMD)
@ -18,8 +18,7 @@ function(webp_check_compiler_flag WEBP_SIMD_FLAG ENABLE_SIMD)
#endif #endif
return 0; return 0;
} }
" WEBP_HAVE_FLAG_${WEBP_SIMD_FLAG} " WEBP_HAVE_FLAG_${WEBP_SIMD_FLAG})
)
cmake_pop_check_state() cmake_pop_check_state()
if(WEBP_HAVE_FLAG_${WEBP_SIMD_FLAG}) if(WEBP_HAVE_FLAG_${WEBP_SIMD_FLAG})
set(WEBP_HAVE_${WEBP_SIMD_FLAG} 1 PARENT_SCOPE) set(WEBP_HAVE_${WEBP_SIMD_FLAG} 1 PARENT_SCOPE)
@ -29,16 +28,18 @@ function(webp_check_compiler_flag WEBP_SIMD_FLAG ENABLE_SIMD)
endfunction() endfunction()
# those are included in the names of WEBP_USE_* in c++ code. # those are included in the names of WEBP_USE_* in c++ code.
set(WEBP_SIMD_FLAGS "SSE2;SSE41;AVX2;MIPS32;MIPS_DSP_R2;NEON;MSA") set(WEBP_SIMD_FLAGS "SSE41;SSE2;MIPS32;MIPS_DSP_R2;NEON;MSA")
set(WEBP_SIMD_FILE_EXTENSIONS "_sse2.c;_sse41.c;_avx2.c;_mips32.c;_mips_dsp_r2.c;_neon.c;_msa.c") set(WEBP_SIMD_FILE_EXTENSIONS
"_sse41.c;_sse2.c;_mips32.c;_mips_dsp_r2.c;_neon.c;_msa.c")
if(MSVC) if(MSVC)
# MSVC does not have a SSE4 flag but AVX2 support implies # MSVC does not have a SSE4 flag but AVX support implies SSE4 support.
# SSE4 support. set(SIMD_ENABLE_FLAGS "/arch:AVX;/arch:SSE2;;;;")
set(SIMD_ENABLE_FLAGS "/arch:SSE2;/arch:AVX2;/arch:AVX2;;;;")
set(SIMD_DISABLE_FLAGS) set(SIMD_DISABLE_FLAGS)
else() else()
set(SIMD_ENABLE_FLAGS "-msse2;-msse4.1;-mavx2;-mips32;-mdspr2;-mfpu=neon;-mmsa") set(SIMD_ENABLE_FLAGS
set(SIMD_DISABLE_FLAGS "-mno-sse2;-mno-sse4.1;-mno-avx2;;-mno-dspr2;;-mno-msa") "-msse4.1;-msse2;-mips32;-mdspr2;-mfpu=neon;-mmsa")
set(SIMD_DISABLE_FLAGS
"-mno-sse4.1;-mno-sse2;;-mno-dspr2;;-mno-msa")
endif() endif()
set(WEBP_SIMD_FILES_TO_NOT_INCLUDE) set(WEBP_SIMD_FILES_TO_NOT_INCLUDE)
@ -47,16 +48,16 @@ set(WEBP_SIMD_FLAGS_TO_INCLUDE)
if(${ANDROID}) if(${ANDROID})
if(${ANDROID_ABI} STREQUAL "armeabi-v7a") if(${ANDROID_ABI} STREQUAL "armeabi-v7a")
# This is because Android studio uses the configuration # This is because Android studio uses the configuration "-march=armv7-a
# "-march=armv7-a -mfloat-abi=softfp -mfpu=vfpv3-d16" # -mfloat-abi=softfp -mfpu=vfpv3-d16" that does not trigger neon
# that does not trigger neon optimizations but should # optimizations but should (as this configuration does not exist anymore).
# (as this configuration does not exist anymore).
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -mfpu=neon ") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -mfpu=neon ")
endif() endif()
endif() endif()
list(LENGTH WEBP_SIMD_FLAGS WEBP_SIMD_FLAGS_LENGTH) list(LENGTH WEBP_SIMD_FLAGS WEBP_SIMD_FLAGS_LENGTH)
math(EXPR WEBP_SIMD_FLAGS_RANGE "${WEBP_SIMD_FLAGS_LENGTH} - 1") math(EXPR WEBP_SIMD_FLAGS_RANGE "${WEBP_SIMD_FLAGS_LENGTH} - 1")
unset(HIGHEST_SSE_FLAG)
foreach(I_SIMD RANGE ${WEBP_SIMD_FLAGS_RANGE}) foreach(I_SIMD RANGE ${WEBP_SIMD_FLAGS_RANGE})
list(GET WEBP_SIMD_FLAGS ${I_SIMD} WEBP_SIMD_FLAG) list(GET WEBP_SIMD_FLAGS ${I_SIMD} WEBP_SIMD_FLAG)
@ -72,18 +73,28 @@ foreach(I_SIMD RANGE ${WEBP_SIMD_FLAGS_RANGE})
set(CMAKE_REQUIRED_FLAGS ${SIMD_COMPILE_FLAG}) set(CMAKE_REQUIRED_FLAGS ${SIMD_COMPILE_FLAG})
webp_check_compiler_flag(${WEBP_SIMD_FLAG} ${WEBP_ENABLE_SIMD}) webp_check_compiler_flag(${WEBP_SIMD_FLAG} ${WEBP_ENABLE_SIMD})
else() else()
set(SIMD_COMPILE_FLAG " ") if(MSVC)
list(GET SIMD_ENABLE_FLAGS ${I_SIMD} SIMD_COMPILE_FLAG)
else()
set(SIMD_COMPILE_FLAG " ")
endif()
endif() endif()
# Check which files we should include or not. # Check which files we should include or not.
list(GET WEBP_SIMD_FILE_EXTENSIONS ${I_SIMD} WEBP_SIMD_FILE_EXTENSION) list(GET WEBP_SIMD_FILE_EXTENSIONS ${I_SIMD} WEBP_SIMD_FILE_EXTENSION)
file(GLOB SIMD_FILES "${CMAKE_CURRENT_LIST_DIR}/../" file(GLOB SIMD_FILES "${CMAKE_CURRENT_LIST_DIR}/../"
"src/dsp/*${WEBP_SIMD_FILE_EXTENSION}" "src/dsp/*${WEBP_SIMD_FILE_EXTENSION}")
)
if(WEBP_HAVE_${WEBP_SIMD_FLAG}) if(WEBP_HAVE_${WEBP_SIMD_FLAG})
if(${I_SIMD} LESS 2 AND NOT HIGHEST_SSE_FLAG)
set(HIGHEST_SSE_FLAG ${SIMD_COMPILE_FLAG})
endif()
# Memorize the file and flags. # Memorize the file and flags.
foreach(FILE ${SIMD_FILES}) foreach(FILE ${SIMD_FILES})
list(APPEND WEBP_SIMD_FILES_TO_INCLUDE ${FILE}) list(APPEND WEBP_SIMD_FILES_TO_INCLUDE ${FILE})
list(APPEND WEBP_SIMD_FLAGS_TO_INCLUDE ${SIMD_COMPILE_FLAG}) if(${I_SIMD} LESS 2)
list(APPEND WEBP_SIMD_FLAGS_TO_INCLUDE ${HIGHEST_SSE_FLAG})
else()
list(APPEND WEBP_SIMD_FLAGS_TO_INCLUDE ${SIMD_COMPILE_FLAG})
endif()
endforeach() endforeach()
else() else()
# Remove the file from the list. # Remove the file from the list.
@ -107,10 +118,10 @@ foreach(I_SIMD RANGE ${WEBP_SIMD_FLAGS_RANGE})
endif() endif()
set(CMAKE_REQUIRED_DEFINITIONS ${SIMD_COMPILE_FLAG}) set(CMAKE_REQUIRED_DEFINITIONS ${SIMD_COMPILE_FLAG})
check_c_source_compiles("int main(void) {return 0;}" check_c_source_compiles("int main(void) {return 0;}"
FLAG_${SIMD_COMPILE_FLAG} FLAG_${SIMD_COMPILE_FLAG}
FAIL_REGEX "warning: argument unused during compilation:" FAIL_REGEX
${COMMON_PATTERNS} "warning: argument unused during compilation:"
) ${COMMON_PATTERNS})
if(NOT FLAG_${SIMD_COMPILE_FLAG}) if(NOT FLAG_${SIMD_COMPILE_FLAG})
unset(HAS_COMPILE_FLAG CACHE) unset(HAS_COMPILE_FLAG CACHE)
endif() endif()

View File

@ -1,33 +1,27 @@
# Generate the config.h to compile with specific intrinsics / libs. # Generate the config.h to compile with specific intrinsics / libs.
## Check for compiler options. # Check for compiler options.
include(CheckCSourceCompiles) include(CheckCSourceCompiles)
check_c_source_compiles(" check_c_source_compiles("
int main(void) { int main(void) {
(void)__builtin_bswap16(0); (void)__builtin_bswap16(0);
return 0; return 0;
} }
" " HAVE_BUILTIN_BSWAP16)
HAVE_BUILTIN_BSWAP16
)
check_c_source_compiles(" check_c_source_compiles("
int main(void) { int main(void) {
(void)__builtin_bswap32(0); (void)__builtin_bswap32(0);
return 0; return 0;
} }
" " HAVE_BUILTIN_BSWAP32)
HAVE_BUILTIN_BSWAP32
)
check_c_source_compiles(" check_c_source_compiles("
int main(void) { int main(void) {
(void)__builtin_bswap64(0); (void)__builtin_bswap64(0);
return 0; return 0;
} }
" " HAVE_BUILTIN_BSWAP64)
HAVE_BUILTIN_BSWAP64
)
## Check for libraries. # Check for libraries.
find_package(Threads) find_package(Threads)
if(Threads_FOUND) if(Threads_FOUND)
if(CMAKE_USE_PTHREADS_INIT) if(CMAKE_USE_PTHREADS_INIT)
@ -40,8 +34,7 @@ if(Threads_FOUND)
int attr = ${PTHREAD_TEST}; int attr = ${PTHREAD_TEST};
return attr; return attr;
} }
" ${PTHREAD_TEST} " ${PTHREAD_TEST})
)
endforeach() endforeach()
list(APPEND WEBP_DEP_LIBRARIES ${CMAKE_THREAD_LIBS_INIT}) list(APPEND WEBP_DEP_LIBRARIES ${CMAKE_THREAD_LIBS_INIT})
endif() endif()
@ -51,15 +44,20 @@ set(WEBP_USE_THREAD ${Threads_FOUND})
set(LT_OBJDIR ".libs/") set(LT_OBJDIR ".libs/")
# Only useful for vwebp, so useless for now. # Only useful for vwebp, so useless for now.
# find_package(OpenGL) find_package(OpenGL)
# set(WEBP_HAVE_GL ${OPENGL_FOUND}) set(WEBP_HAVE_GL ${OPENGL_FOUND})
# set(WEBP_DEP_INCLUDE_DIRS ${WEBP_DEP_INCLUDE_DIRS} ${OPENGL_INCLUDE_DIRS})
# set(WEBP_DEP_LIBRARIES ${WEBP_DEP_LIBRARIES} ${OPENGL_LIBRARIES})
# Find the standard C math library. # Check if we need to link to the C math library. We do not look for it as it is
find_library(MATH_LIBRARY NAMES m) # not found when cross-compiling, while it is here.
if(MATH_LIBRARY) check_c_source_compiles("
list(APPEND WEBP_DEP_LIBRARIES ${MATH_LIBRARY}) #include <math.h>
int main(int argc, char** argv) {
return (int)pow(argc, 2.5);
}
" HAVE_MATH_LIBRARY)
if(NOT HAVE_MATH_LIBRARY)
message(STATUS "Adding -lm flag.")
list(APPEND WEBP_DEP_LIBRARIES m)
endif() endif()
# Find the standard image libraries. # Find the standard image libraries.
@ -70,8 +68,8 @@ foreach(I_LIB PNG JPEG TIFF)
set(WEBP_HAVE_${I_LIB} ${${I_LIB}_FOUND}) set(WEBP_HAVE_${I_LIB} ${${I_LIB}_FOUND})
if(${I_LIB}_FOUND) if(${I_LIB}_FOUND)
list(APPEND WEBP_DEP_IMG_LIBRARIES ${${I_LIB}_LIBRARIES}) list(APPEND WEBP_DEP_IMG_LIBRARIES ${${I_LIB}_LIBRARIES})
list(APPEND WEBP_DEP_IMG_INCLUDE_DIRS list(APPEND WEBP_DEP_IMG_INCLUDE_DIRS ${${I_LIB}_INCLUDE_DIR}
${${I_LIB}_INCLUDE_DIR} ${${I_LIB}_INCLUDE_DIRS}) ${${I_LIB}_INCLUDE_DIRS})
endif() endif()
endforeach() endforeach()
if(WEBP_DEP_IMG_INCLUDE_DIRS) if(WEBP_DEP_IMG_INCLUDE_DIRS)
@ -87,8 +85,8 @@ set(WEBP_HAVE_GIF ${GIF_FOUND})
if(GIF_FOUND) if(GIF_FOUND)
# GIF find_package only locates the header and library, it doesn't fail # GIF find_package only locates the header and library, it doesn't fail
# compile tests when detecting the version, but falls back to 3 (as of at # compile tests when detecting the version, but falls back to 3 (as of at
# least cmake 3.7.2). Make sure the library links to avoid incorrect # least cmake 3.7.2). Make sure the library links to avoid incorrect detection
# detection when cross compiling. # when cross compiling.
cmake_push_check_state() cmake_push_check_state()
set(CMAKE_REQUIRED_LIBRARIES ${GIF_LIBRARIES}) set(CMAKE_REQUIRED_LIBRARIES ${GIF_LIBRARIES})
set(CMAKE_REQUIRED_INCLUDES ${GIF_INCLUDE_DIR}) set(CMAKE_REQUIRED_INCLUDES ${GIF_INCLUDE_DIR})
@ -98,8 +96,7 @@ if(GIF_FOUND)
(void)DGifOpenFileHandle; (void)DGifOpenFileHandle;
return 0; return 0;
} }
" GIF_COMPILES " GIF_COMPILES)
)
cmake_pop_check_state() cmake_pop_check_state()
if(GIF_COMPILES) if(GIF_COMPILES)
list(APPEND WEBP_DEP_GIF_LIBRARIES ${GIF_LIBRARIES}) list(APPEND WEBP_DEP_GIF_LIBRARIES ${GIF_LIBRARIES})
@ -109,7 +106,7 @@ if(GIF_FOUND)
endif() endif()
endif() endif()
## Check for specific headers. # Check for specific headers.
include(CheckIncludeFiles) include(CheckIncludeFiles)
check_include_files("stdlib.h;stdarg.h;string.h;float.h" STDC_HEADERS) check_include_files("stdlib.h;stdarg.h;string.h;float.h" STDC_HEADERS)
check_include_files(dlfcn.h HAVE_DLFCN_H) check_include_files(dlfcn.h HAVE_DLFCN_H)
@ -131,25 +128,32 @@ check_include_files(windows.h HAVE_WINDOWS_H)
# Windows specifics # Windows specifics
if(HAVE_WINCODEC_H) if(HAVE_WINCODEC_H)
list(APPEND WEBP_DEP_LIBRARIES shlwapi ole32 windowscodecs) list(APPEND WEBP_DEP_LIBRARIES
shlwapi
ole32
windowscodecs)
endif() endif()
## Check for SIMD extensions. # Check for SIMD extensions.
include(${CMAKE_CURRENT_LIST_DIR}/cpu.cmake) include(${CMAKE_CURRENT_LIST_DIR}/cpu.cmake)
## Define extra info. # Define extra info.
set(PACKAGE ${PROJECT_NAME}) set(PACKAGE ${PROJECT_NAME})
set(PACKAGE_NAME ${PROJECT_NAME}) set(PACKAGE_NAME ${PROJECT_NAME})
# Read from configure.ac. # Read from configure.ac.
file(READ ${CMAKE_CURRENT_SOURCE_DIR}/configure.ac CONFIGURE_AC) file(READ ${CMAKE_CURRENT_SOURCE_DIR}/configure.ac CONFIGURE_AC)
string(REGEX MATCHALL "\\[([0-9a-z\\.:/]*)\\]" string(REGEX MATCHALL
CONFIGURE_AC_PACKAGE_INFO ${CONFIGURE_AC} "\\[([0-9a-z\\.:/]*)\\]"
) CONFIGURE_AC_PACKAGE_INFO
${CONFIGURE_AC})
function(strip_bracket VAR) function(strip_bracket VAR)
string(LENGTH ${${VAR}} TMP_LEN) string(LENGTH ${${VAR}} TMP_LEN)
math(EXPR TMP_LEN ${TMP_LEN}-2) math(EXPR TMP_LEN ${TMP_LEN}-2)
string(SUBSTRING ${${VAR}} 1 ${TMP_LEN} TMP_SUB) string(SUBSTRING ${${VAR}}
1
${TMP_LEN}
TMP_SUB)
set(${VAR} ${TMP_SUB} PARENT_SCOPE) set(${VAR} ${TMP_SUB} PARENT_SCOPE)
endfunction() endfunction()

View File

@ -1,4 +1,4 @@
AC_INIT([libwebp], [0.6.1], AC_INIT([libwebp], [1.0.1],
[https://bugs.chromium.org/p/webp],, [https://bugs.chromium.org/p/webp],,
[http://developers.google.com/speed/webp]) [http://developers.google.com/speed/webp])
AC_CANONICAL_HOST AC_CANONICAL_HOST
@ -122,31 +122,6 @@ AS_IF([test "$GCC" = "yes" ], [
AC_SUBST([AM_CFLAGS]) AC_SUBST([AM_CFLAGS])
dnl === Check for machine specific flags dnl === Check for machine specific flags
AC_ARG_ENABLE([avx2],
AS_HELP_STRING([--disable-avx2],
[Disable detection of AVX2 support
@<:@default=auto@:>@]))
AS_IF([test "x$enable_avx2" != "xno" -a "x$enable_sse4_1" != "xno" \
-a "x$enable_sse2" != "xno"], [
AVX2_CFLAGS="$INTRINSICS_CFLAGS $AVX2_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])])
AC_ARG_ENABLE([sse4.1], AC_ARG_ENABLE([sse4.1],
AS_HELP_STRING([--disable-sse4.1], AS_HELP_STRING([--disable-sse4.1],
[Disable detection of SSE4.1 support [Disable detection of SSE4.1 support
@ -347,6 +322,8 @@ AS_IF([test "x$enable_gl" != "xno"], [
# override with --with-gl* # override with --with-gl*
glut_cflags="$glut_cflags|-framework GLUT -framework OpenGL" glut_cflags="$glut_cflags|-framework GLUT -framework OpenGL"
glut_ldflags="$glut_ldflags|-framework GLUT -framework OpenGL" glut_ldflags="$glut_ldflags|-framework GLUT -framework OpenGL"
# quiet deprecation warnings for glut
TEST_AND_ADD_CFLAGS([AM_CFLAGS], [-Wno-deprecated-declarations])
;; ;;
esac esac
@ -443,31 +420,54 @@ AC_ARG_ENABLE([sdl],
@<:@default=auto@:>@])) @<:@default=auto@:>@]))
AS_IF([test "x$enable_sdl" != "xno"], [ AS_IF([test "x$enable_sdl" != "xno"], [
CLEAR_LIBVARS([SDL]) CLEAR_LIBVARS([SDL])
AC_PATH_PROGS([LIBSDL_CONFIG], [sdl-config])
if test -n "$LIBSDL_CONFIG"; then
SDL_INCLUDES=`$LIBSDL_CONFIG --cflags`
SDL_LIBS="`$LIBSDL_CONFIG --libs`"
fi
WITHLIB_OPTION([sdl], [SDL]) WITHLIB_OPTION([sdl], [SDL])
sdl_header="no" sdl_header="no"
LIBCHECK_PROLOGUE([SDL]) LIBCHECK_PROLOGUE([SDL])
AC_CHECK_HEADER([SDL/SDL.h], [sdl_header="SDL_SDL.h"], AC_CHECK_HEADER([SDL/SDL.h], [sdl_header="SDL/SDL.h"],
[AC_CHECK_HEADER([SDL.h], [sdl_header="SDL.h"], [AC_CHECK_HEADER([SDL.h], [sdl_header="SDL.h"],
[AC_MSG_WARN(SDL library not available - no sdl.h)])]) [AC_MSG_WARN(SDL library not available - no sdl.h)])])
if test x"$sdl_header" != "xno"; then if test x"$sdl_header" != "xno"; then
AC_CHECK_LIB(SDL, SDL_Init, AC_LANG_PUSH(C)
[SDL_LIBS="-lSDL" SDL_SAVED_LIBS="$LIBS"
SDL_INCLUDES="-DWEBP_HAVE_SDL" for lib in "" "-lSDL" "-lSDLmain -lSDL"; do
AC_DEFINE(WEBP_HAVE_SDL, [1], LIBS="$SDL_SAVED_LIBS $lib"
[Set to 1 if SDL library is installed]) # Perform a full link to ensure SDL_main is resolved if needed.
sdl_support=yes AC_LINK_IFELSE(
], [AC_LANG_SOURCE([
AC_MSG_WARN(Optional SDL library not found), #include <$sdl_header>
[$MATH_LIBS]) int main(int argc, char** argv) {
SDL_Init(0);
return 0;
}])],
[SDL_LIBS="$LDFLAGS $LIBS"
SDL_INCLUDES="$SDL_INCLUDES -DWEBP_HAVE_SDL"
AC_DEFINE(WEBP_HAVE_SDL, [1],
[Set to 1 if SDL library is installed])
sdl_support=yes]
)
if test x"$sdl_support" = "xyes"; then
break
fi
done
# LIBS is restored by LIBCHECK_EPILOGUE
AC_LANG_POP
if test x"$sdl_header" = "xSDL.h"; then if test x"$sdl_header" = "xSDL.h"; then
SDL_INCLUDES="$SDL_INCLUDES -DWEBP_HAVE_JUST_SDL_H" SDL_INCLUDES="$SDL_INCLUDES -DWEBP_HAVE_JUST_SDL_H"
fi fi
fi fi
LIBCHECK_EPILOGUE([SDL]) LIBCHECK_EPILOGUE([SDL])
if test "$sdl_support" = "yes"; then if test x"$sdl_support" = "xyes"; then
build_vwebp_sdl=yes build_vwebp_sdl=yes
else
AC_MSG_WARN(Optional SDL library not found)
fi fi
]) ])
@ -601,7 +601,7 @@ AS_IF([test "x$enable_gif" != "xno"], [
AM_CONDITIONAL([BUILD_ANIMDIFF], [test "${build_anim_diff}" = "yes"]) AM_CONDITIONAL([BUILD_ANIMDIFF], [test "${build_anim_diff}" = "yes"])
AM_CONDITIONAL([BUILD_GIF2WEBP], [test "${build_gif2webp}" = "yes"]) AM_CONDITIONAL([BUILD_GIF2WEBP], [test "${build_gif2webp}" = "yes"])
if test "$enable_libwebpmux" = "yes"; then if test "$enable_libwebpdemux" = "yes" -a "$enable_libwebpmux" = "yes"; then
build_img2webp=yes build_img2webp=yes
fi fi
AM_CONDITIONAL([BUILD_IMG2WEBP], [test "${build_img2webp}" = "yes"]) AM_CONDITIONAL([BUILD_IMG2WEBP], [test "${build_img2webp}" = "yes"])
@ -676,19 +676,6 @@ fi
AC_MSG_RESULT(${enable_swap_16bit_csp-no}) AC_MSG_RESULT(${enable_swap_16bit_csp-no})
AC_SUBST(USE_SWAP_16BIT_CSP) 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 === If --disable-near-lossless is defined, add -DWEBP_NEAR_LOSSLESS=0 dnl === If --disable-near-lossless is defined, add -DWEBP_NEAR_LOSSLESS=0
AC_DEFINE(WEBP_NEAR_LOSSLESS, [1], [Enable near lossless encoding]) AC_DEFINE(WEBP_NEAR_LOSSLESS, [1], [Enable near lossless encoding])
@ -710,15 +697,16 @@ AC_ARG_ENABLE([libwebpmux],
AS_HELP_STRING([--enable-libwebpmux], AS_HELP_STRING([--enable-libwebpmux],
[Build libwebpmux @<:@default=no@:>@])) [Build libwebpmux @<:@default=no@:>@]))
AC_MSG_RESULT(${enable_libwebpmux-no}) AC_MSG_RESULT(${enable_libwebpmux-no})
AM_CONDITIONAL([WANT_MUX], [test "$enable_libwebpmux" = "yes"]) AM_CONDITIONAL([BUILD_MUX], [test "$enable_libwebpmux" = "yes"])
dnl === Check whether libwebpdemux should be built dnl === Check whether libwebpdemux should be built
AC_MSG_CHECKING(whether libwebpdemux is to be built) AC_MSG_CHECKING(whether libwebpdemux is to be built)
AC_ARG_ENABLE([libwebpdemux], AC_ARG_ENABLE([libwebpdemux],
AS_HELP_STRING([--enable-libwebpdemux], AS_HELP_STRING([--disable-libwebpdemux],
[Build libwebpdemux @<:@default=no@:>@])) [Disable libwebpdemux @<:@default=no@:>@]),
[], [enable_libwebpdemux=yes])
AC_MSG_RESULT(${enable_libwebpdemux-no}) AC_MSG_RESULT(${enable_libwebpdemux-no})
AM_CONDITIONAL([WANT_DEMUX], [test "$enable_libwebpdemux" = "yes"]) AM_CONDITIONAL([BUILD_DEMUX], [test "$enable_libwebpdemux" = "yes"])
dnl === Check whether decoder library should be built. dnl === Check whether decoder library should be built.
AC_MSG_CHECKING(whether decoder library is to be built) AC_MSG_CHECKING(whether decoder library is to be built)
@ -734,7 +722,7 @@ AC_ARG_ENABLE([libwebpextras],
AS_HELP_STRING([--enable-libwebpextras], AS_HELP_STRING([--enable-libwebpextras],
[Build libwebpextras @<:@default=no@:>@])) [Build libwebpextras @<:@default=no@:>@]))
AC_MSG_RESULT(${enable_libwebpextras-no}) AC_MSG_RESULT(${enable_libwebpextras-no})
AM_CONDITIONAL([WANT_EXTRAS], [test "$enable_libwebpextras" = "yes"]) AM_CONDITIONAL([BUILD_EXTRAS], [test "$enable_libwebpextras" = "yes"])
dnl ========================= dnl =========================
@ -765,14 +753,14 @@ libwebpmux: ${enable_libwebpmux-no}
libwebpextras: ${enable_libwebpextras-no} libwebpextras: ${enable_libwebpextras-no}
Tools: Tools:
cwebp : yes cwebp : ${enable_libwebpdemux-no}
Input format support Input format support
==================== ====================
JPEG : ${jpeg_support-no} JPEG : ${jpeg_support-no}
PNG : ${png_support-no} PNG : ${png_support-no}
TIFF : ${tiff_support-no} TIFF : ${tiff_support-no}
WIC : ${wic_support-no} WIC : ${wic_support-no}
dwebp : yes dwebp : ${enable_libwebpdemux-no}
Output format support Output format support
===================== =====================
PNG : ${png_support-no} PNG : ${png_support-no}

View File

@ -446,8 +446,9 @@ Frame Height Minus One: 24 bits (_uint24_)
Frame Duration: 24 bits (_uint24_) Frame Duration: 24 bits (_uint24_)
: The time to wait before displaying the next frame, in 1 millisecond units. : 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 Note the interpretation of frame duration of 0 (and often <= 10) is
multiple areas of the canvas at once during the animation. implementation defined. Many tools and browsers assign a minimum duration
similar to GIF.
Reserved: 6 bits Reserved: 6 bits

View File

@ -26,8 +26,7 @@ LOCAL_SRC_FILES := \
cwebp.c \ cwebp.c \
LOCAL_CFLAGS := $(WEBP_CFLAGS) LOCAL_CFLAGS := $(WEBP_CFLAGS)
LOCAL_C_INCLUDES := $(LOCAL_PATH)/../src LOCAL_STATIC_LIBRARIES := example_util imageio_util imagedec webpdemux webp
LOCAL_STATIC_LIBRARIES := example_util imageio_util imagedec webp
LOCAL_MODULE := cwebp LOCAL_MODULE := cwebp
@ -42,9 +41,7 @@ LOCAL_SRC_FILES := \
dwebp.c \ dwebp.c \
LOCAL_CFLAGS := $(WEBP_CFLAGS) LOCAL_CFLAGS := $(WEBP_CFLAGS)
LOCAL_C_INCLUDES := $(LOCAL_PATH)/../src LOCAL_STATIC_LIBRARIES := example_util imagedec imageenc webpdemux webp
LOCAL_STATIC_LIBRARIES := example_util imagedec imageenc webp
LOCAL_MODULE := dwebp LOCAL_MODULE := dwebp
include $(BUILD_EXECUTABLE) include $(BUILD_EXECUTABLE)
@ -58,7 +55,6 @@ LOCAL_SRC_FILES := \
webpmux.c \ webpmux.c \
LOCAL_CFLAGS := $(WEBP_CFLAGS) LOCAL_CFLAGS := $(WEBP_CFLAGS)
LOCAL_C_INCLUDES := $(LOCAL_PATH)/../src
LOCAL_STATIC_LIBRARIES := example_util imageio_util webpmux webp LOCAL_STATIC_LIBRARIES := example_util imageio_util webpmux webp
LOCAL_MODULE := webpmux_example LOCAL_MODULE := webpmux_example
@ -74,8 +70,8 @@ LOCAL_SRC_FILES := \
img2webp.c \ img2webp.c \
LOCAL_CFLAGS := $(WEBP_CFLAGS) LOCAL_CFLAGS := $(WEBP_CFLAGS)
LOCAL_C_INCLUDES := $(LOCAL_PATH)/../src LOCAL_STATIC_LIBRARIES := example_util imageio_util imagedec webpmux webpdemux \
LOCAL_STATIC_LIBRARIES := example_util imageio_util imagedec webpmux webp webp
LOCAL_MODULE := img2webp_example LOCAL_MODULE := img2webp_example
@ -90,7 +86,6 @@ LOCAL_SRC_FILES := \
webpinfo.c \ webpinfo.c \
LOCAL_CFLAGS := $(WEBP_CFLAGS) LOCAL_CFLAGS := $(WEBP_CFLAGS)
LOCAL_C_INCLUDES := $(LOCAL_PATH)/../src
LOCAL_STATIC_LIBRARIES := example_util imageio_util webp LOCAL_STATIC_LIBRARIES := example_util imageio_util webp
LOCAL_MODULE := webpinfo_example LOCAL_MODULE := webpinfo_example

View File

@ -1,6 +1,9 @@
AM_CPPFLAGS += -I$(top_builddir)/src -I$(top_srcdir)/src AM_CPPFLAGS += -I$(top_builddir)/src -I$(top_srcdir)/src
bin_PROGRAMS = dwebp cwebp bin_PROGRAMS =
if BUILD_DEMUX
bin_PROGRAMS += dwebp cwebp
endif
if BUILD_ANIMDIFF if BUILD_ANIMDIFF
noinst_PROGRAMS = anim_diff anim_dump noinst_PROGRAMS = anim_diff anim_dump
endif endif
@ -10,7 +13,7 @@ endif
if BUILD_IMG2WEBP if BUILD_IMG2WEBP
bin_PROGRAMS += img2webp bin_PROGRAMS += img2webp
endif endif
if WANT_MUX if BUILD_MUX
bin_PROGRAMS += webpmux bin_PROGRAMS += webpmux
endif endif
if BUILD_VWEBP if BUILD_VWEBP
@ -25,16 +28,16 @@ noinst_LTLIBRARIES = libexample_util.la
libexample_util_la_SOURCES = example_util.c example_util.h libexample_util_la_SOURCES = example_util.c example_util.h
libexample_util_la_LIBADD = ../src/libwebp.la libexample_util_la_LIBADD = ../src/libwebp.la
anim_diff_SOURCES = anim_diff.c anim_util.c anim_util.h anim_diff_SOURCES = anim_diff.c anim_util.c anim_util.h gifdec.c gifdec.h
anim_diff_CPPFLAGS = $(AM_CPPFLAGS) $(USE_EXPERIMENTAL_CODE) $(GIF_INCLUDES) anim_diff_CPPFLAGS = $(AM_CPPFLAGS) $(GIF_INCLUDES)
anim_diff_LDADD = anim_diff_LDADD =
anim_diff_LDADD += ../src/demux/libwebpdemux.la anim_diff_LDADD += ../src/demux/libwebpdemux.la
anim_diff_LDADD += libexample_util.la anim_diff_LDADD += libexample_util.la
anim_diff_LDADD += ../imageio/libimageio_util.la anim_diff_LDADD += ../imageio/libimageio_util.la
anim_diff_LDADD += $(GIF_LIBS) -lm anim_diff_LDADD += $(GIF_LIBS) -lm
anim_dump_SOURCES = anim_dump.c anim_util.c anim_util.h anim_dump_SOURCES = anim_dump.c anim_util.c anim_util.h gifdec.c gifdec.h
anim_dump_CPPFLAGS = $(AM_CPPFLAGS) $(USE_EXPERIMENTAL_CODE) $(PNG_INCLUDES) anim_dump_CPPFLAGS = $(AM_CPPFLAGS) $(PNG_INCLUDES)
anim_dump_CPPFLAGS += $(GIF_INCLUDES) anim_dump_CPPFLAGS += $(GIF_INCLUDES)
anim_dump_LDADD = anim_dump_LDADD =
anim_dump_LDADD += ../src/demux/libwebpdemux.la anim_dump_LDADD += ../src/demux/libwebpdemux.la
@ -44,7 +47,7 @@ anim_dump_LDADD += ../imageio/libimageenc.la
anim_dump_LDADD += $(PNG_LIBS) $(GIF_LIBS) $(TIFF_LIBS) -lm anim_dump_LDADD += $(PNG_LIBS) $(GIF_LIBS) $(TIFF_LIBS) -lm
cwebp_SOURCES = cwebp.c stopwatch.h cwebp_SOURCES = cwebp.c stopwatch.h
cwebp_CPPFLAGS = $(AM_CPPFLAGS) $(USE_EXPERIMENTAL_CODE) cwebp_CPPFLAGS = $(AM_CPPFLAGS)
cwebp_LDADD = cwebp_LDADD =
cwebp_LDADD += libexample_util.la cwebp_LDADD += libexample_util.la
cwebp_LDADD += ../imageio/libimageio_util.la cwebp_LDADD += ../imageio/libimageio_util.la
@ -53,7 +56,7 @@ cwebp_LDADD += ../src/libwebp.la
cwebp_LDADD += $(JPEG_LIBS) $(PNG_LIBS) $(TIFF_LIBS) cwebp_LDADD += $(JPEG_LIBS) $(PNG_LIBS) $(TIFF_LIBS)
dwebp_SOURCES = dwebp.c stopwatch.h dwebp_SOURCES = dwebp.c stopwatch.h
dwebp_CPPFLAGS = $(AM_CPPFLAGS) $(USE_EXPERIMENTAL_CODE) dwebp_CPPFLAGS = $(AM_CPPFLAGS)
dwebp_CPPFLAGS += $(JPEG_INCLUDES) $(PNG_INCLUDES) dwebp_CPPFLAGS += $(JPEG_INCLUDES) $(PNG_INCLUDES)
dwebp_LDADD = dwebp_LDADD =
dwebp_LDADD += libexample_util.la dwebp_LDADD += libexample_util.la
@ -64,7 +67,7 @@ dwebp_LDADD += ../src/libwebp.la
dwebp_LDADD +=$(PNG_LIBS) $(JPEG_LIBS) dwebp_LDADD +=$(PNG_LIBS) $(JPEG_LIBS)
gif2webp_SOURCES = gif2webp.c gifdec.c gifdec.h gif2webp_SOURCES = gif2webp.c gifdec.c gifdec.h
gif2webp_CPPFLAGS = $(AM_CPPFLAGS) $(USE_EXPERIMENTAL_CODE) $(GIF_INCLUDES) gif2webp_CPPFLAGS = $(AM_CPPFLAGS) $(GIF_INCLUDES)
gif2webp_LDADD = gif2webp_LDADD =
gif2webp_LDADD += libexample_util.la gif2webp_LDADD += libexample_util.la
gif2webp_LDADD += ../imageio/libimageio_util.la gif2webp_LDADD += ../imageio/libimageio_util.la
@ -73,7 +76,7 @@ gif2webp_LDADD += ../src/libwebp.la
gif2webp_LDADD += $(GIF_LIBS) gif2webp_LDADD += $(GIF_LIBS)
vwebp_SOURCES = vwebp.c vwebp_SOURCES = vwebp.c
vwebp_CPPFLAGS = $(AM_CPPFLAGS) $(USE_EXPERIMENTAL_CODE) $(GL_INCLUDES) vwebp_CPPFLAGS = $(AM_CPPFLAGS) $(GL_INCLUDES)
vwebp_LDADD = vwebp_LDADD =
vwebp_LDADD += libexample_util.la vwebp_LDADD += libexample_util.la
vwebp_LDADD += ../imageio/libimageio_util.la vwebp_LDADD += ../imageio/libimageio_util.la
@ -81,7 +84,7 @@ vwebp_LDADD += ../src/demux/libwebpdemux.la
vwebp_LDADD += $(GL_LIBS) vwebp_LDADD += $(GL_LIBS)
webpmux_SOURCES = webpmux.c webpmux_SOURCES = webpmux.c
webpmux_CPPFLAGS = $(AM_CPPFLAGS) $(USE_EXPERIMENTAL_CODE) webpmux_CPPFLAGS = $(AM_CPPFLAGS)
webpmux_LDADD = webpmux_LDADD =
webpmux_LDADD += libexample_util.la webpmux_LDADD += libexample_util.la
webpmux_LDADD += ../imageio/libimageio_util.la webpmux_LDADD += ../imageio/libimageio_util.la
@ -89,7 +92,7 @@ webpmux_LDADD += ../src/mux/libwebpmux.la
webpmux_LDADD += ../src/libwebp.la webpmux_LDADD += ../src/libwebp.la
img2webp_SOURCES = img2webp.c img2webp_SOURCES = img2webp.c
img2webp_CPPFLAGS = $(AM_CPPFLAGS) $(USE_EXPERIMENTAL_CODE) img2webp_CPPFLAGS = $(AM_CPPFLAGS)
img2webp_LDADD = img2webp_LDADD =
img2webp_LDADD += libexample_util.la img2webp_LDADD += libexample_util.la
img2webp_LDADD += ../imageio/libimageio_util.la img2webp_LDADD += ../imageio/libimageio_util.la
@ -99,7 +102,7 @@ img2webp_LDADD += ../src/libwebp.la
img2webp_LDADD += $(PNG_LIBS) $(JPEG_LIBS) $(TIFF_LIBS) img2webp_LDADD += $(PNG_LIBS) $(JPEG_LIBS) $(TIFF_LIBS)
webpinfo_SOURCES = webpinfo.c webpinfo_SOURCES = webpinfo.c
webpinfo_CPPFLAGS = $(AM_CPPFLAGS) $(USE_EXPERIMENTAL_CODE) webpinfo_CPPFLAGS = $(AM_CPPFLAGS)
webpinfo_LDADD = webpinfo_LDADD =
webpinfo_LDADD += libexample_util.la webpinfo_LDADD += libexample_util.la
webpinfo_LDADD += ../imageio/libimageio_util.la webpinfo_LDADD += ../imageio/libimageio_util.la

View File

@ -20,6 +20,7 @@
#include <string.h> // for 'strcmp'. #include <string.h> // for 'strcmp'.
#include "./anim_util.h" #include "./anim_util.h"
#include "./example_util.h"
#if defined(_MSC_VER) && _MSC_VER < 1900 #if defined(_MSC_VER) && _MSC_VER < 1900
#define snprintf _snprintf #define snprintf _snprintf
@ -197,11 +198,11 @@ static void Help(void) {
printf(" -min_psnr <float> ... minimum per-frame PSNR\n"); printf(" -min_psnr <float> ... minimum per-frame PSNR\n");
printf(" -raw_comparison ..... if this flag is not used, RGB is\n"); printf(" -raw_comparison ..... if this flag is not used, RGB is\n");
printf(" premultiplied before comparison\n"); printf(" premultiplied before comparison\n");
#ifdef WEBP_EXPERIMENTAL_FEATURES printf(" -max_diff <int> ..... maximum allowed difference per channel\n"
printf(" -max_diff <int> ..... maximum allowed difference per channel " " between corresponding pixels in subsequent\n"
" between corresponding pixels in subsequent"
" frames\n"); " frames\n");
#endif printf(" -h .................. this help\n");
printf(" -version ............ print version number and exit\n");
} }
int main(int argc, const char* argv[]) { int main(int argc, const char* argv[]) {
@ -217,11 +218,6 @@ int main(int argc, const char* argv[]) {
const char* files[2] = { NULL, NULL }; const char* files[2] = { NULL, NULL };
AnimatedImage images[2]; AnimatedImage images[2];
if (argc < 3) {
Help();
return -1;
}
for (c = 1; c < argc; ++c) { for (c = 1; c < argc; ++c) {
int parse_error = 0; int parse_error = 0;
if (!strcmp(argv[c], "-dump_frames")) { if (!strcmp(argv[c], "-dump_frames")) {
@ -233,34 +229,30 @@ int main(int argc, const char* argv[]) {
} }
} else if (!strcmp(argv[c], "-min_psnr")) { } else if (!strcmp(argv[c], "-min_psnr")) {
if (c < argc - 1) { if (c < argc - 1) {
const char* const v = argv[++c]; min_psnr = ExUtilGetFloat(argv[++c], &parse_error);
char* end = NULL;
const double d = strtod(v, &end);
if (end == v) {
parse_error = 1;
fprintf(stderr, "Error! '%s' is not a floating point number.\n", v);
}
min_psnr = d;
} else { } else {
parse_error = 1; parse_error = 1;
} }
} else if (!strcmp(argv[c], "-raw_comparison")) { } else if (!strcmp(argv[c], "-raw_comparison")) {
premultiply = 0; premultiply = 0;
#ifdef WEBP_EXPERIMENTAL_FEATURES
} else if (!strcmp(argv[c], "-max_diff")) { } else if (!strcmp(argv[c], "-max_diff")) {
if (c < argc - 1) { if (c < argc - 1) {
const char* const v = argv[++c]; max_diff = ExUtilGetInt(argv[++c], 0, &parse_error);
char* end = NULL;
const int n = (int)strtol(v, &end, 10);
if (end == v) {
parse_error = 1;
fprintf(stderr, "Error! '%s' is not an integer.\n", v);
}
max_diff = n;
} else { } else {
parse_error = 1; parse_error = 1;
} }
#endif } else if (!strcmp(argv[c], "-h") || !strcmp(argv[c], "-help")) {
Help();
return 0;
} else if (!strcmp(argv[c], "-version")) {
int dec_version, demux_version;
GetAnimatedImageVersions(&dec_version, &demux_version);
printf("WebP Decoder version: %d.%d.%d\nWebP Demux version: %d.%d.%d\n",
(dec_version >> 16) & 0xff, (dec_version >> 8) & 0xff,
(dec_version >> 0) & 0xff,
(demux_version >> 16) & 0xff, (demux_version >> 8) & 0xff,
(demux_version >> 0) & 0xff);
return 0;
} else { } else {
if (!got_input1) { if (!got_input1) {
files[0] = argv[c]; files[0] = argv[c];
@ -277,6 +269,12 @@ int main(int argc, const char* argv[]) {
return -1; return -1;
} }
} }
if (argc < 3) {
Help();
return -1;
}
if (!got_input2) { if (!got_input2) {
Help(); Help();
return -1; return -1;

View File

@ -30,6 +30,8 @@ static void Help(void) {
"(default: 'dump_')\n"); "(default: 'dump_')\n");
printf(" -tiff ............... save frames as TIFF\n"); printf(" -tiff ............... save frames as TIFF\n");
printf(" -pam ................ save frames as PAM\n"); printf(" -pam ................ save frames as PAM\n");
printf(" -h .................. this help\n");
printf(" -version ............ print version number and exit\n");
} }
int main(int argc, const char* argv[]) { int main(int argc, const char* argv[]) {
@ -66,6 +68,18 @@ int main(int argc, const char* argv[]) {
} else if (!strcmp(argv[c], "-pam")) { } else if (!strcmp(argv[c], "-pam")) {
format = PAM; format = PAM;
suffix = "pam"; suffix = "pam";
} else if (!strcmp(argv[c], "-h") || !strcmp(argv[c], "-help")) {
Help();
return 0;
} else if (!strcmp(argv[c], "-version")) {
int dec_version, demux_version;
GetAnimatedImageVersions(&dec_version, &demux_version);
printf("WebP Decoder version: %d.%d.%d\nWebP Demux version: %d.%d.%d\n",
(dec_version >> 16) & 0xff, (dec_version >> 8) & 0xff,
(dec_version >> 0) & 0xff,
(demux_version >> 16) & 0xff, (demux_version >> 8) & 0xff,
(demux_version >> 0) & 0xff);
return 0;
} else { } else {
uint32_t i; uint32_t i;
AnimatedImage image; AnimatedImage image;

View File

@ -23,6 +23,7 @@
#include "webp/decode.h" #include "webp/decode.h"
#include "webp/demux.h" #include "webp/demux.h"
#include "../imageio/imageio_util.h" #include "../imageio/imageio_util.h"
#include "./gifdec.h"
#if defined(_MSC_VER) && _MSC_VER < 1900 #if defined(_MSC_VER) && _MSC_VER < 1900
#define snprintf _snprintf #define snprintf _snprintf
@ -370,26 +371,6 @@ static int DGifSavedExtensionToGCB(GifFileType* GifFile, int ImageIndex,
#define DGifCloseFile(a, b) DGifCloseFile(a) #define DGifCloseFile(a, b) DGifCloseFile(a)
#endif #endif
static void GIFDisplayError(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)
const char* error_str =
GifErrorString((gif == NULL) ? gif_error : gif->Error);
#else
const char* error_str = 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 int IsKeyFrameGIF(const GifImageDesc* prev_desc, int prev_dispose, static int IsKeyFrameGIF(const GifImageDesc* prev_desc, int prev_dispose,
const DecodedFrame* const prev_frame, const DecodedFrame* const prev_frame,
int canvas_width, int canvas_height) { int canvas_width, int canvas_height) {
@ -594,6 +575,9 @@ static int ReadAnimatedGIF(const char filename[], AnimatedImage* const image,
curr_frame = &image->frames[i]; curr_frame = &image->frames[i];
curr_rgba = curr_frame->rgba; curr_rgba = curr_frame->rgba;
curr_frame->duration = GetFrameDurationGIF(gif, i); curr_frame->duration = GetFrameDurationGIF(gif, i);
// Force frames with a small or no duration to 100ms to be consistent
// with web browsers and other transcoding tools (like gif2webp itself).
if (curr_frame->duration <= 10) curr_frame->duration = 100;
if (i == 0) { // Initialize as transparent. if (i == 0) { // Initialize as transparent.
curr_frame->is_key_frame = 1; curr_frame->is_key_frame = 1;
@ -785,3 +769,9 @@ void GetDiffAndPSNR(const uint8_t rgba1[], const uint8_t rgba2[],
*psnr = 4.3429448 * log(255. * 255. / sse); *psnr = 4.3429448 * log(255. * 255. / sse);
} }
} }
void GetAnimatedImageVersions(int* const decoder_version,
int* const demux_version) {
*decoder_version = WebPGetDecoderVersion();
*demux_version = WebPGetDemuxVersion();
}

View File

@ -62,6 +62,10 @@ void GetDiffAndPSNR(const uint8_t rgba1[], const uint8_t rgba2[],
uint32_t width, uint32_t height, int premultiply, uint32_t width, uint32_t height, int premultiply,
int* const max_diff, double* const psnr); int* const max_diff, double* const psnr);
// Return library versions used by anim_util.
void GetAnimatedImageVersions(int* const decoder_version,
int* const demux_version);
#ifdef __cplusplus #ifdef __cplusplus
} // extern "C" } // extern "C"
#endif #endif

View File

@ -140,10 +140,11 @@ static void PrintByteCount(const int bytes[4], int total_size,
fprintf(stderr, "| %7d (%.1f%%)\n", total, 100.f * total / total_size); fprintf(stderr, "| %7d (%.1f%%)\n", total, 100.f * total / total_size);
} }
static void PrintPercents(const int counts[4], int total) { static void PrintPercents(const int counts[4]) {
int s; int s;
const int total = counts[0] + counts[1] + counts[2] + counts[3];
for (s = 0; s < 4; ++s) { for (s = 0; s < 4; ++s) {
fprintf(stderr, "| %2d%%", 100 * counts[s] / total); fprintf(stderr, "| %2d%%", (int)(100. * counts[s] / total + .5));
} }
fprintf(stderr, "| %7d\n", total); fprintf(stderr, "| %7d\n", total);
} }
@ -186,7 +187,8 @@ static void PrintExtraInfoLossless(const WebPPicture* const pic,
} else { } else {
fprintf(stderr, "File: %s\n", file_name); fprintf(stderr, "File: %s\n", file_name);
fprintf(stderr, "Dimension: %d x %d\n", pic->width, pic->height); fprintf(stderr, "Dimension: %d x %d\n", pic->width, pic->height);
fprintf(stderr, "Output: %d bytes\n", stats->coded_size); fprintf(stderr, "Output: %d bytes (%.2f bpp)\n", stats->coded_size,
8.f * stats->coded_size / pic->width / pic->height);
PrintFullLosslessInfo(stats, "ARGB"); PrintFullLosslessInfo(stats, "ARGB");
} }
} }
@ -207,15 +209,18 @@ static void PrintExtraInfoLossy(const WebPPicture* const pic, int short_output,
pic->width, pic->height, pic->width, pic->height,
stats->alpha_data_size ? " (with alpha)" : ""); stats->alpha_data_size ? " (with alpha)" : "");
fprintf(stderr, "Output: " fprintf(stderr, "Output: "
"%d bytes Y-U-V-All-PSNR %2.2f %2.2f %2.2f %2.2f dB\n", "%d bytes Y-U-V-All-PSNR %2.2f %2.2f %2.2f %2.2f dB\n"
" (%.2f bpp)\n",
stats->coded_size, stats->coded_size,
stats->PSNR[0], stats->PSNR[1], stats->PSNR[2], stats->PSNR[3]); stats->PSNR[0], stats->PSNR[1], stats->PSNR[2], stats->PSNR[3],
8.f * stats->coded_size / pic->width / pic->height);
if (total > 0) { if (total > 0) {
int totals[4] = { 0, 0, 0, 0 }; int totals[4] = { 0, 0, 0, 0 };
fprintf(stderr, "block count: intra4: %d\n" fprintf(stderr, "block count: intra4: %6d (%.2f%%)\n"
" intra16: %d (-> %.2f%%)\n", " intra16: %6d (%.2f%%)\n"
num_i4, num_i16, 100.f * num_i16 / total); " skipped: %6d (%.2f%%)\n",
fprintf(stderr, " skipped block: %d (%.2f%%)\n", num_i4, 100.f * num_i4 / total,
num_i16, 100.f * num_i16 / total,
num_skip, 100.f * num_skip / total); num_skip, 100.f * num_skip / total);
fprintf(stderr, "bytes used: header: %6d (%.1f%%)\n" fprintf(stderr, "bytes used: header: %6d (%.1f%%)\n"
" mode-partition: %6d (%.1f%%)\n", " mode-partition: %6d (%.1f%%)\n",
@ -239,7 +244,7 @@ static void PrintExtraInfoLossy(const WebPPicture* const pic, int short_output,
PrintByteCount(stats->residual_bytes[2], stats->coded_size, totals); PrintByteCount(stats->residual_bytes[2], stats->coded_size, totals);
} }
fprintf(stderr, " macroblocks: "); fprintf(stderr, " macroblocks: ");
PrintPercents(stats->segment_size, total); PrintPercents(stats->segment_size);
fprintf(stderr, " quantizer: "); fprintf(stderr, " quantizer: ");
PrintValues(stats->segment_quant); PrintValues(stats->segment_quant);
fprintf(stderr, " filter level: "); fprintf(stderr, " filter level: ");
@ -580,9 +585,6 @@ static void HelpLong(void) {
printf(" -near_lossless <int> ... use near-lossless image\n" printf(" -near_lossless <int> ... use near-lossless image\n"
" preprocessing (0..100=off), " " preprocessing (0..100=off), "
"default=100\n"); "default=100\n");
#ifdef WEBP_EXPERIMENTAL_FEATURES /* not documented yet */
printf(" -delta_palette ......... use delta palettization\n");
#endif // WEBP_EXPERIMENTAL_FEATURES
printf(" -hint <string> ......... specify image characteristics hint,\n"); printf(" -hint <string> ......... specify image characteristics hint,\n");
printf(" one of: photo, picture or graph\n"); printf(" one of: photo, picture or graph\n");
@ -751,11 +753,6 @@ int main(int argc, const char *argv[]) {
} else if (!strcmp(argv[c], "-near_lossless") && c < argc - 1) { } else if (!strcmp(argv[c], "-near_lossless") && c < argc - 1) {
config.near_lossless = ExUtilGetInt(argv[++c], 0, &parse_error); config.near_lossless = ExUtilGetInt(argv[++c], 0, &parse_error);
config.lossless = 1; // use near-lossless only with lossless config.lossless = 1; // use near-lossless only with lossless
#ifdef WEBP_EXPERIMENTAL_FEATURES
} else if (!strcmp(argv[c], "-delta_palette")) {
config.use_delta_palette = 1;
config.lossless = 1; // delta-palette is for lossless only
#endif // WEBP_EXPERIMENTAL_FEATURES
} else if (!strcmp(argv[c], "-hint") && c < argc - 1) { } else if (!strcmp(argv[c], "-hint") && c < argc - 1) {
++c; ++c;
if (!strcmp(argv[c], "photo")) { if (!strcmp(argv[c], "photo")) {
@ -1015,10 +1012,53 @@ int main(int argc, const char *argv[]) {
} }
} }
if ((resize_w | resize_h) > 0) { if ((resize_w | resize_h) > 0) {
WebPPicture picture_no_alpha;
if (config.exact) {
// If -exact, we can't premultiply RGB by A otherwise RGB is lost if A=0.
// We rescale an opaque copy and assemble scaled A and non-premultiplied
// RGB channels. This is slower but it's a very uncommon use case. Color
// leak at sharp alpha edges is possible.
if (!WebPPictureCopy(&picture, &picture_no_alpha)) {
fprintf(stderr, "Error! Cannot copy temporary picture\n");
goto Error;
}
// We enforced picture.use_argb = 1 above. Now, remove the alpha values.
{
int x, y;
uint32_t* argb_no_alpha = picture_no_alpha.argb;
for (y = 0; y < picture_no_alpha.height; ++y) {
for (x = 0; x < picture_no_alpha.width; ++x) {
argb_no_alpha[x] |= 0xff000000; // Opaque copy.
}
argb_no_alpha += picture_no_alpha.argb_stride;
}
}
if (!WebPPictureRescale(&picture_no_alpha, resize_w, resize_h)) {
fprintf(stderr, "Error! Cannot resize temporary picture\n");
goto Error;
}
}
if (!WebPPictureRescale(&picture, resize_w, resize_h)) { if (!WebPPictureRescale(&picture, resize_w, resize_h)) {
fprintf(stderr, "Error! Cannot resize picture\n"); fprintf(stderr, "Error! Cannot resize picture\n");
goto Error; goto Error;
} }
if (config.exact) { // Put back the alpha information.
int x, y;
uint32_t* argb_no_alpha = picture_no_alpha.argb;
uint32_t* argb = picture.argb;
for (y = 0; y < picture_no_alpha.height; ++y) {
for (x = 0; x < picture_no_alpha.width; ++x) {
argb[x] = (argb[x] & 0xff000000) | (argb_no_alpha[x] & 0x00ffffff);
}
argb_no_alpha += picture_no_alpha.argb_stride;
argb += picture.argb_stride;
}
WebPPictureFree(&picture_no_alpha);
}
} }
if (verbose && (crop != 0 || (resize_w | resize_h) > 0)) { if (verbose && (crop != 0 || (resize_w | resize_h) > 0)) {
const double preproc_time = StopwatchReadAndReset(&stop_watch); const double preproc_time = StopwatchReadAndReset(&stop_watch);
@ -1050,7 +1090,8 @@ int main(int argc, const char *argv[]) {
// Write info // Write info
if (dump_file) { if (dump_file) {
if (picture.use_argb) { if (picture.use_argb) {
fprintf(stderr, "Warning: can't dump file (-d option) in lossless mode."); fprintf(stderr, "Warning: can't dump file (-d option) "
"in lossless mode.\n");
} else if (!DumpPicture(&picture, dump_file)) { } else if (!DumpPicture(&picture, dump_file)) {
fprintf(stderr, "Warning, couldn't dump picture %s\n", dump_file); fprintf(stderr, "Warning, couldn't dump picture %s\n", dump_file);
} }

View File

@ -12,10 +12,14 @@
#include "./example_util.h" #include "./example_util.h"
#include <assert.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include "webp/mux_types.h"
#include "../imageio/imageio_util.h"
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// String parsing // String parsing
@ -56,3 +60,68 @@ float ExUtilGetFloat(const char* const v, int* const error) {
} }
return f; return f;
} }
//------------------------------------------------------------------------------
static void ResetCommandLineArguments(int argc, const char* argv[],
CommandLineArguments* const args) {
assert(args != NULL);
args->argc_ = argc;
args->argv_ = argv;
args->own_argv_ = 0;
WebPDataInit(&args->argv_data_);
}
void ExUtilDeleteCommandLineArguments(CommandLineArguments* const args) {
if (args != NULL) {
if (args->own_argv_) {
free((void*)args->argv_);
WebPDataClear(&args->argv_data_);
}
ResetCommandLineArguments(0, NULL, args);
}
}
#define MAX_ARGC 16384
int ExUtilInitCommandLineArguments(int argc, const char* argv[],
CommandLineArguments* const args) {
if (args == NULL || argv == NULL) return 0;
ResetCommandLineArguments(argc, argv, args);
if (argc == 1 && argv[0][0] != '-') {
char* cur;
const char sep[] = " \t\r\n\f\v";
if (!ExUtilReadFileToWebPData(argv[0], &args->argv_data_)) {
return 0;
}
args->own_argv_ = 1;
args->argv_ = (const char**)malloc(MAX_ARGC * sizeof(*args->argv_));
if (args->argv_ == NULL) return 0;
argc = 0;
for (cur = strtok((char*)args->argv_data_.bytes, sep);
cur != NULL;
cur = strtok(NULL, sep)) {
if (argc == MAX_ARGC) {
fprintf(stderr, "ERROR: Arguments limit %d reached\n", MAX_ARGC);
return 0;
}
assert(strlen(cur) != 0);
args->argv_[argc++] = cur;
}
args->argc_ = argc;
}
return 1;
}
//------------------------------------------------------------------------------
int ExUtilReadFileToWebPData(const char* const filename,
WebPData* const webp_data) {
const uint8_t* data;
size_t size;
if (webp_data == NULL) return 0;
if (!ImgIoUtilReadFile(filename, &data, &size)) return 0;
webp_data->bytes = data;
webp_data->size = size;
return 1;
}

View File

@ -14,6 +14,7 @@
#define WEBP_EXAMPLES_EXAMPLE_UTIL_H_ #define WEBP_EXAMPLES_EXAMPLE_UTIL_H_
#include "webp/types.h" #include "webp/types.h"
#include "webp/mux_types.h"
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
@ -35,6 +36,33 @@ float ExUtilGetFloat(const char* const v, int* const error);
// actually parsed is returned, or -1 if an error occurred. // actually parsed is returned, or -1 if an error occurred.
int ExUtilGetInts(const char* v, int base, int max_output, int output[]); int ExUtilGetInts(const char* v, int base, int max_output, int output[]);
// Reads a file named 'filename' into a WebPData structure. The content of
// webp_data is overwritten. Returns false in case of error.
int ExUtilReadFileToWebPData(const char* const filename,
WebPData* const webp_data);
//------------------------------------------------------------------------------
// Command-line arguments
typedef struct {
int argc_;
const char** argv_;
WebPData argv_data_;
int own_argv_;
} CommandLineArguments;
// Initializes the structure from the command-line parameters. If there is
// only one parameter and it does not start with a '-', then it is assumed to
// be a file name. This file will be read and tokenized into command-line
// arguments. The content of 'args' is overwritten.
// Returns false in case of error (memory allocation failure, non
// existing file, too many arguments, ...).
int ExUtilInitCommandLineArguments(int argc, const char* argv[],
CommandLineArguments* const args);
// Deallocate all memory and reset 'args'.
void ExUtilDeleteCommandLineArguments(CommandLineArguments* const args);
#ifdef __cplusplus #ifdef __cplusplus
} // extern "C" } // extern "C"
#endif #endif

View File

@ -23,6 +23,10 @@
#ifdef WEBP_HAVE_GIF #ifdef WEBP_HAVE_GIF
#if defined(HAVE_UNISTD_H) && HAVE_UNISTD_H
#include <unistd.h>
#endif
#include <gif_lib.h> #include <gif_lib.h>
#include "webp/encode.h" #include "webp/encode.h"
#include "webp/mux.h" #include "webp/mux.h"
@ -30,6 +34,10 @@
#include "../imageio/imageio_util.h" #include "../imageio/imageio_util.h"
#include "./gifdec.h" #include "./gifdec.h"
#if !defined(STDIN_FILENO)
#define STDIN_FILENO 0
#endif
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
static int transparent_index = GIF_INDEX_INVALID; // Opaque by default. static int transparent_index = GIF_INDEX_INVALID; // Opaque by default.
@ -92,7 +100,6 @@ int main(int argc, const char *argv[]) {
WebPMuxError err = WEBP_MUX_OK; WebPMuxError err = WEBP_MUX_OK;
int ok = 0; int ok = 0;
const char *in_file = NULL, *out_file = NULL; const char *in_file = NULL, *out_file = NULL;
FILE* out = NULL;
GifFileType* gif = NULL; GifFileType* gif = NULL;
int frame_duration = 0; int frame_duration = 0;
int frame_timestamp = 0; int frame_timestamp = 0;
@ -263,9 +270,11 @@ int main(int argc, const char *argv[]) {
// Start the decoder object // Start the decoder object
#if LOCAL_GIF_PREREQ(5,0) #if LOCAL_GIF_PREREQ(5,0)
gif = DGifOpenFileName(in_file, &gif_error); gif = !strcmp(in_file, "-") ? DGifOpenFileHandle(STDIN_FILENO, &gif_error)
: DGifOpenFileName(in_file, &gif_error);
#else #else
gif = DGifOpenFileName(in_file); gif = !strcmp(in_file, "-") ? DGifOpenFileHandle(STDIN_FILENO)
: DGifOpenFileName(in_file);
#endif #endif
if (gif == NULL) goto End; if (gif == NULL) goto End;
@ -351,6 +360,14 @@ int main(int argc, const char *argv[]) {
GIFDisposeFrame(orig_dispose, &gif_rect, &prev_canvas, &curr_canvas); GIFDisposeFrame(orig_dispose, &gif_rect, &prev_canvas, &curr_canvas);
GIFCopyPixels(&curr_canvas, &prev_canvas); GIFCopyPixels(&curr_canvas, &prev_canvas);
// Force frames with a small or no duration to 100ms to be consistent
// with web browsers and other transcoding tools. This also avoids
// incorrect durations between frames when padding frames are
// discarded.
if (frame_duration <= 10) {
frame_duration = 100;
}
// Update timestamp (for next frame). // Update timestamp (for next frame).
frame_timestamp += frame_duration; frame_timestamp += frame_duration;
@ -532,8 +549,13 @@ int main(int argc, const char *argv[]) {
goto End; goto End;
} }
if (!quiet) { if (!quiet) {
fprintf(stderr, "Saved output file (%d bytes): %s\n", if (!strcmp(out_file, "-")) {
(int)webp_data.size, out_file); fprintf(stderr, "Saved %d bytes to STDIO\n",
(int)webp_data.size);
} else {
fprintf(stderr, "Saved output file (%d bytes): %s\n",
(int)webp_data.size, out_file);
}
} }
} else { } else {
if (!quiet) { if (!quiet) {
@ -555,7 +577,6 @@ int main(int argc, const char *argv[]) {
WebPPictureFree(&curr_canvas); WebPPictureFree(&curr_canvas);
WebPPictureFree(&prev_canvas); WebPPictureFree(&prev_canvas);
WebPAnimEncoderDelete(enc); WebPAnimEncoderDelete(enc);
if (out != NULL && out_file != NULL) fclose(out);
if (gif_error != GIF_OK) { if (gif_error != GIF_OK) {
GIFDisplayError(gif, gif_error); GIFDisplayError(gif, gif_error);

View File

@ -48,6 +48,7 @@ static void Help(void) {
printf(" -mixed ............... use mixed lossy/lossless automatic mode\n"); printf(" -mixed ............... use mixed lossy/lossless automatic mode\n");
printf(" -v ................... verbose mode\n"); printf(" -v ................... verbose mode\n");
printf(" -h ................... this help\n"); printf(" -h ................... this help\n");
printf(" -version ............. print version number and exit\n");
printf("\n"); printf("\n");
printf("Per-frame options (only used for subsequent images input):\n"); printf("Per-frame options (only used for subsequent images input):\n");
@ -60,6 +61,10 @@ static void Help(void) {
printf("\n"); printf("\n");
printf("example: img2webp -loop 2 in0.png -lossy in1.jpg\n" printf("example: img2webp -loop 2 in0.png -lossy in1.jpg\n"
" -d 80 in2.tiff -o out.webp\n"); " -d 80 in2.tiff -o out.webp\n");
printf("\nNote: if a single file name is passed as the argument, the "
"arguments will be\n");
printf("tokenized from this file. The file name must not start with "
"the character '-'.\n");
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
@ -117,14 +122,13 @@ static int SetLoopCount(int loop_count, WebPData* const webp_data) {
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
int main(int argc, char* argv[]) { int main(int argc, const char* argv[]) {
const char* output = NULL; const char* output = NULL;
WebPAnimEncoder* enc = NULL; WebPAnimEncoder* enc = NULL;
int verbose = 0; int verbose = 0;
int pic_num = 0; int pic_num = 0;
int duration = 100; int duration = 100;
int timestamp_ms = 0; int timestamp_ms = 0;
int ok = 1;
int loop_count = 0; int loop_count = 0;
int width = 0, height = 0; int width = 0, height = 0;
WebPAnimEncoderOptions anim_config; WebPAnimEncoderOptions anim_config;
@ -133,17 +137,23 @@ int main(int argc, char* argv[]) {
WebPData webp_data; WebPData webp_data;
int c; int c;
int have_input = 0; int have_input = 0;
CommandLineArguments cmd_args;
int ok = ExUtilInitCommandLineArguments(argc - 1, argv + 1, &cmd_args);
if (!ok) return 1;
argc = cmd_args.argc_;
argv = cmd_args.argv_;
WebPDataInit(&webp_data); WebPDataInit(&webp_data);
if (!WebPAnimEncoderOptionsInit(&anim_config) || if (!WebPAnimEncoderOptionsInit(&anim_config) ||
!WebPConfigInit(&config) || !WebPConfigInit(&config) ||
!WebPPictureInit(&pic)) { !WebPPictureInit(&pic)) {
fprintf(stderr, "Library version mismatch!\n"); fprintf(stderr, "Library version mismatch!\n");
return 1; ok = 0;
goto End;
} }
// 1st pass of option parsing // 1st pass of option parsing
for (c = 1; ok && c < argc; ++c) { for (c = 0; ok && c < argc; ++c) {
if (argv[c][0] == '-') { if (argv[c][0] == '-') {
int parse_error = 0; int parse_error = 0;
if (!strcmp(argv[c], "-o") && c + 1 < argc) { if (!strcmp(argv[c], "-o") && c + 1 < argc) {
@ -171,7 +181,15 @@ int main(int argc, char* argv[]) {
verbose = 1; verbose = 1;
} else if (!strcmp(argv[c], "-h") || !strcmp(argv[c], "-help")) { } else if (!strcmp(argv[c], "-h") || !strcmp(argv[c], "-help")) {
Help(); Help();
return 0; goto End;
} 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);
goto End;
} else { } else {
continue; continue;
} }
@ -184,13 +202,13 @@ int main(int argc, char* argv[]) {
} }
if (!have_input) { if (!have_input) {
fprintf(stderr, "No input file(s) for generating animation!\n"); fprintf(stderr, "No input file(s) for generating animation!\n");
return 0; goto End;
} }
// image-reading pass // image-reading pass
pic_num = 0; pic_num = 0;
config.lossless = 1; config.lossless = 1;
for (c = 1; ok && c < argc; ++c) { for (c = 0; ok && c < argc; ++c) {
if (argv[c] == NULL) continue; if (argv[c] == NULL) continue;
if (argv[c][0] == '-') { // parse local options if (argv[c][0] == '-') { // parse local options
int parse_error = 0; int parse_error = 0;
@ -294,7 +312,7 @@ int main(int argc, char* argv[]) {
fprintf(stderr, "[%d frames, %u bytes].\n", fprintf(stderr, "[%d frames, %u bytes].\n",
pic_num, (unsigned int)webp_data.size); pic_num, (unsigned int)webp_data.size);
} }
WebPDataClear(&webp_data); WebPDataClear(&webp_data);
ExUtilDeleteCommandLineArguments(&cmd_args);
return ok ? 0 : 1; return ok ? 0 : 1;
} }

View File

@ -60,4 +60,4 @@ static WEBP_INLINE double StopwatchReadAndReset(Stopwatch* watch) {
#endif /* _WIN32 */ #endif /* _WIN32 */
#endif /* WEBP_EXAMPLES_STOPWATCH_H_ */ #endif // WEBP_EXAMPLES_STOPWATCH_H_

View File

@ -56,6 +56,7 @@ static struct {
int print_info; int print_info;
int only_deltas; int only_deltas;
int use_color_profile; int use_color_profile;
int draw_anim_background_color;
int canvas_width, canvas_height; int canvas_width, canvas_height;
int loop_count; int loop_count;
@ -205,6 +206,11 @@ static void decode_callback(int what) {
} }
} }
duration = curr->duration; duration = curr->duration;
// Behavior copied from Chrome, cf:
// https://cs.chromium.org/chromium/src/third_party/WebKit/Source/
// platform/graphics/DeferredImageDecoder.cpp?
// rcl=b4c33049f096cd283f32be9a58b9a9e768227c26&l=246
if (duration <= 10) duration = 100;
} }
if (!Decode()) { if (!Decode()) {
kParams.decoding_error = 1; kParams.decoding_error = 1;
@ -220,6 +226,9 @@ static void decode_callback(int what) {
// Callbacks // Callbacks
static void HandleKey(unsigned char key, int pos_x, int pos_y) { static void HandleKey(unsigned char key, int pos_x, int pos_y) {
// Note: rescaling the window or toggling some features during an animation
// generates visual artifacts. This is not fixed because refreshing the frame
// may require rendering the whole animation from start till current frame.
(void)pos_x; (void)pos_x;
(void)pos_y; (void)pos_y;
if (key == 'q' || key == 'Q' || key == 27 /* Esc */) { if (key == 'q' || key == 'Q' || key == 27 /* Esc */) {
@ -247,9 +256,11 @@ static void HandleKey(unsigned char key, int pos_x, int pos_y) {
glutPostRedisplay(); glutPostRedisplay();
} }
} }
} else if (key == 'b') {
kParams.draw_anim_background_color = 1 - kParams.draw_anim_background_color;
if (!kParams.has_animation) ClearPreviousFrame();
glutPostRedisplay();
} else if (key == 'i') { } else if (key == 'i') {
// Note: doesn't handle refresh of animation's last-frame (it's quite
// more involved to do, since you need to save the previous frame).
kParams.print_info = 1 - kParams.print_info; kParams.print_info = 1 - kParams.print_info;
if (!kParams.has_animation) ClearPreviousFrame(); if (!kParams.has_animation) ClearPreviousFrame();
glutPostRedisplay(); glutPostRedisplay();
@ -281,7 +292,7 @@ static void PrintString(const char* const text) {
} }
static float GetColorf(uint32_t color, int shift) { static float GetColorf(uint32_t color, int shift) {
return (color >> shift) / 255.f; return ((color >> shift) & 0xff) / 255.f;
} }
static void DrawCheckerBoard(void) { static void DrawCheckerBoard(void) {
@ -304,6 +315,43 @@ static void DrawCheckerBoard(void) {
glPopMatrix(); glPopMatrix();
} }
static void DrawBackground(void) {
// Whole window cleared with clear color, checkerboard rendered on top of it.
glClear(GL_COLOR_BUFFER_BIT);
DrawCheckerBoard();
// ANIM background color rendered (blend) on top. Default is white for still
// images (without ANIM chunk). glClear() can't be used for that (no blend).
if (kParams.draw_anim_background_color) {
glPushMatrix();
glLoadIdentity();
glColor4f(GetColorf(kParams.bg_color, 16), // BGRA from spec
GetColorf(kParams.bg_color, 8),
GetColorf(kParams.bg_color, 0),
GetColorf(kParams.bg_color, 24));
glRecti(-1, -1, +1, +1);
glPopMatrix();
}
}
// Draw background in a scissored rectangle.
static void DrawBackgroundScissored(int window_x, int window_y, int frame_w,
int frame_h) {
// Only update the requested area, not the whole canvas.
window_x = window_x * kParams.viewport_width / kParams.canvas_width;
window_y = window_y * kParams.viewport_height / kParams.canvas_height;
frame_w = frame_w * kParams.viewport_width / kParams.canvas_width;
frame_h = frame_h * kParams.viewport_height / kParams.canvas_height;
// glScissor() takes window coordinates (0,0 at bottom left).
window_y = kParams.viewport_height - window_y - frame_h;
glEnable(GL_SCISSOR_TEST);
glScissor(window_x, window_y, frame_w, frame_h);
DrawBackground();
glDisable(GL_SCISSOR_TEST);
}
static void HandleDisplay(void) { static void HandleDisplay(void) {
const WebPDecBuffer* const pic = kParams.pic; const WebPDecBuffer* const pic = kParams.pic;
const WebPIterator* const curr = &kParams.curr_frame; const WebPIterator* const curr = &kParams.curr_frame;
@ -320,38 +368,21 @@ static void HandleDisplay(void) {
glPixelStorei(GL_UNPACK_ROW_LENGTH, pic->u.RGBA.stride / 4); glPixelStorei(GL_UNPACK_ROW_LENGTH, pic->u.RGBA.stride / 4);
if (kParams.only_deltas) { if (kParams.only_deltas) {
DrawCheckerBoard(); DrawBackground();
} else if (prev->dispose_method == WEBP_MUX_DISPOSE_BACKGROUND || } else {
curr->blend_method == WEBP_MUX_NO_BLEND) { // The rectangle of the previous frame might be different than the current
// glScissor() takes window coordinates (0,0 at bottom left). // frame, so we may need to DrawBackgroundScissored for both.
int window_x, window_y;
int frame_w, frame_h;
if (prev->dispose_method == WEBP_MUX_DISPOSE_BACKGROUND) { if (prev->dispose_method == WEBP_MUX_DISPOSE_BACKGROUND) {
// Clear the previous frame rectangle. // Clear the previous frame rectangle.
window_x = prev->x_offset; DrawBackgroundScissored(prev->x_offset, prev->y_offset, prev->width,
window_y = kParams.canvas_height - prev->y_offset - prev->height; prev->height);
frame_w = prev->width; }
frame_h = prev->height; if (curr->blend_method == WEBP_MUX_NO_BLEND) {
} else { // curr->blend_method == WEBP_MUX_NO_BLEND. // We simulate no-blending behavior by first clearing the current frame
// We simulate no-blending behavior by first clearing the current frame // rectangle and then alpha-blending against it.
// rectangle (to a checker-board) and then alpha-blending against it. DrawBackgroundScissored(curr->x_offset, curr->y_offset, curr->width,
window_x = curr->x_offset; curr->height);
window_y = kParams.canvas_height - curr->y_offset - curr->height;
frame_w = curr->width;
frame_h = curr->height;
} }
glEnable(GL_SCISSOR_TEST);
// Only update the requested area, not the whole canvas.
window_x = window_x * kParams.viewport_width / kParams.canvas_width;
window_y = window_y * kParams.viewport_height / kParams.canvas_height;
frame_w = frame_w * kParams.viewport_width / kParams.canvas_width;
frame_h = frame_h * kParams.viewport_height / kParams.canvas_height;
glScissor(window_x, window_y, frame_w, frame_h);
glClear(GL_COLOR_BUFFER_BIT); // use clear color
DrawCheckerBoard();
glDisable(GL_SCISSOR_TEST);
} }
*prev = *curr; *prev = *curr;
@ -403,37 +434,35 @@ static void StartDisplay(void) {
glutKeyboardFunc(HandleKey); glutKeyboardFunc(HandleKey);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_BLEND); glEnable(GL_BLEND);
glClearColor(GetColorf(kParams.bg_color, 0), glClearColor(0, 0, 0, 0); // window will be cleared to black (no blend)
GetColorf(kParams.bg_color, 8), DrawBackground();
GetColorf(kParams.bg_color, 16),
GetColorf(kParams.bg_color, 24));
glClear(GL_COLOR_BUFFER_BIT);
DrawCheckerBoard();
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// Main // Main
static void Help(void) { static void Help(void) {
printf("Usage: vwebp in_file [options]\n\n" printf(
"Decodes the WebP image file and visualize it using OpenGL\n" "Usage: vwebp in_file [options]\n\n"
"Options are:\n" "Decodes the WebP image file and visualize it using OpenGL\n"
" -version ..... print version number and exit\n" "Options are:\n"
" -noicc ....... don't use the icc profile if present\n" " -version ..... print version number and exit\n"
" -nofancy ..... don't use the fancy YUV420 upscaler\n" " -noicc ....... don't use the icc profile if present\n"
" -nofilter .... disable in-loop filtering\n" " -nofancy ..... don't use the fancy YUV420 upscaler\n"
" -dither <int> dithering strength (0..100), default=50\n" " -nofilter .... disable in-loop filtering\n"
" -noalphadither disable alpha plane dithering\n" " -dither <int> dithering strength (0..100), default=50\n"
" -mt .......... use multi-threading\n" " -noalphadither disable alpha plane dithering\n"
" -info ........ print info\n" " -usebgcolor .. display background color\n"
" -h ........... this help message\n" " -mt .......... use multi-threading\n"
"\n" " -info ........ print info\n"
"Keyboard shortcuts:\n" " -h ........... this help message\n"
" 'c' ................ toggle use of color profile\n" "\n"
" 'i' ................ overlay file information\n" "Keyboard shortcuts:\n"
" 'd' ................ disable blending & disposal (debug)\n" " 'c' ................ toggle use of color profile\n"
" 'q' / 'Q' / ESC .... quit\n" " 'b' ................ toggle background color display\n"
); " 'i' ................ overlay file information\n"
" 'd' ................ disable blending & disposal (debug)\n"
" 'q' / 'Q' / ESC .... quit\n");
} }
int main(int argc, char *argv[]) { int main(int argc, char *argv[]) {
@ -448,6 +477,8 @@ int main(int argc, char *argv[]) {
config->options.dithering_strength = 50; config->options.dithering_strength = 50;
config->options.alpha_dithering_strength = 100; config->options.alpha_dithering_strength = 100;
kParams.use_color_profile = 1; kParams.use_color_profile = 1;
// Background color hidden by default to see transparent areas.
kParams.draw_anim_background_color = 0;
for (c = 1; c < argc; ++c) { for (c = 1; c < argc; ++c) {
int parse_error = 0; int parse_error = 0;
@ -462,6 +493,8 @@ int main(int argc, char *argv[]) {
config->options.bypass_filtering = 1; config->options.bypass_filtering = 1;
} else if (!strcmp(argv[c], "-noalphadither")) { } else if (!strcmp(argv[c], "-noalphadither")) {
config->options.alpha_dithering_strength = 0; config->options.alpha_dithering_strength = 0;
} else if (!strcmp(argv[c], "-usebgcolor")) {
kParams.draw_anim_background_color = 1;
} else if (!strcmp(argv[c], "-dither") && c + 1 < argc) { } else if (!strcmp(argv[c], "-dither") && c + 1 < argc) {
config->options.dithering_strength = config->options.dithering_strength =
ExUtilGetInt(argv[++c], 0, &parse_error); ExUtilGetInt(argv[++c], 0, &parse_error);

View File

@ -340,7 +340,7 @@ static WebPInfoStatus ParseLossyHeader(const ChunkData* const chunk_data,
WebPInfoStatus status = WEBP_INFO_OK; WebPInfoStatus status = WEBP_INFO_OK;
uint64_t bit_position = 0; uint64_t bit_position = 0;
uint64_t* const bit_pos = &bit_position; uint64_t* const bit_pos = &bit_position;
int color_space, clamp_type; int colorspace, clamp_type;
printf(" Parsing lossy bitstream...\n"); printf(" Parsing lossy bitstream...\n");
// Calling WebPGetFeatures() in ProcessImageChunk() should ensure this. // Calling WebPGetFeatures() in ProcessImageChunk() should ensure this.
assert(chunk_data->size_ >= CHUNK_HEADER_SIZE + 10); assert(chunk_data->size_ >= CHUNK_HEADER_SIZE + 10);
@ -381,9 +381,9 @@ static WebPInfoStatus ParseLossyHeader(const ChunkData* const chunk_data,
LOG_ERROR("Bad partition length."); LOG_ERROR("Bad partition length.");
return WEBP_INFO_BITSTREAM_ERROR; return WEBP_INFO_BITSTREAM_ERROR;
} }
GET_BITS(color_space, 1); GET_BITS(colorspace, 1);
GET_BITS(clamp_type, 1); GET_BITS(clamp_type, 1);
printf(" Color space: %d\n", color_space); printf(" Color space: %d\n", colorspace);
printf(" Clamp type: %d\n", clamp_type); printf(" Clamp type: %d\n", clamp_type);
status = ParseLossySegmentHeader(webp_info, data, data_size, bit_pos); status = ParseLossySegmentHeader(webp_info, data, data_size, bit_pos);
if (status != WEBP_INFO_OK) return status; if (status != WEBP_INFO_OK) return status;

View File

@ -47,6 +47,7 @@
webpmux -info in.webp webpmux -info in.webp
webpmux [ -h | -help ] webpmux [ -h | -help ]
webpmux -version webpmux -version
webpmux argument_file_name
*/ */
#ifdef HAVE_CONFIG_H #ifdef HAVE_CONFIG_H
@ -108,28 +109,26 @@ static const char* const kDescriptions[LAST_FEATURE] = {
}; };
typedef struct { typedef struct {
FeatureType type_; CommandLineArguments cmd_args_;
FeatureArg* args_;
int arg_count_;
} Feature;
typedef struct {
ActionType action_type_; ActionType action_type_;
const char* input_; const char* input_;
const char* output_; const char* output_;
Feature feature_; FeatureType type_;
} WebPMuxConfig; FeatureArg* args_;
int arg_count_;
} Config;
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// Helper functions. // Helper functions.
static int CountOccurrences(const char* arglist[], int list_length, static int CountOccurrences(const CommandLineArguments* const args,
const char* arg) { const char* const arg) {
int i; int i;
int num_occurences = 0; int num_occurences = 0;
for (i = 0; i < list_length; ++i) { for (i = 0; i < args->argc_; ++i) {
if (!strcmp(arglist[i], arg)) { if (!strcmp(args->argv_[i], arg)) {
++num_occurences; ++num_occurences;
} }
} }
@ -301,6 +300,7 @@ static void PrintHelp(void) {
printf(" webpmux -info INPUT\n"); printf(" webpmux -info INPUT\n");
printf(" webpmux [-h|-help]\n"); printf(" webpmux [-h|-help]\n");
printf(" webpmux -version\n"); printf(" webpmux -version\n");
printf(" webpmux argument_file_name\n");
printf("\n"); printf("\n");
printf("GET_OPTIONS:\n"); printf("GET_OPTIONS:\n");
@ -369,6 +369,10 @@ static void PrintHelp(void) {
printf("\nNote: The nature of EXIF, XMP and ICC data is not checked"); printf("\nNote: The nature of EXIF, XMP and ICC data is not checked");
printf(" and is assumed to be\nvalid.\n"); printf(" and is assumed to be\nvalid.\n");
printf("\nNote: if a single file name is passed as the argument, the "
"arguments will be\n");
printf("tokenized from this file. The file name must not start with "
"the character '-'.\n");
} }
static void WarnAboutOddOffset(const WebPMuxFrameInfo* const info) { static void WarnAboutOddOffset(const WebPMuxFrameInfo* const info) {
@ -379,22 +383,12 @@ static void WarnAboutOddOffset(const WebPMuxFrameInfo* const info) {
} }
} }
static int ReadFileToWebPData(const char* const filename,
WebPData* const webp_data) {
const uint8_t* data;
size_t size;
if (!ImgIoUtilReadFile(filename, &data, &size)) return 0;
webp_data->bytes = data;
webp_data->size = size;
return 1;
}
static int CreateMux(const char* const filename, WebPMux** mux) { static int CreateMux(const char* const filename, WebPMux** mux) {
WebPData bitstream; WebPData bitstream;
assert(mux != NULL); assert(mux != NULL);
if (!ReadFileToWebPData(filename, &bitstream)) return 0; if (!ExUtilReadFileToWebPData(filename, &bitstream)) return 0;
*mux = WebPMuxCreate(&bitstream, 1); *mux = WebPMuxCreate(&bitstream, 1);
free((void*)bitstream.bytes); WebPDataClear(&bitstream);
if (*mux != NULL) return 1; if (*mux != NULL) return 1;
fprintf(stderr, "Failed to create mux object from file %s.\n", filename); fprintf(stderr, "Failed to create mux object from file %s.\n", filename);
return 0; return 0;
@ -517,9 +511,10 @@ static int ParseBgcolorArgs(const char* args, uint32_t* const bgcolor) {
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// Clean-up. // Clean-up.
static void DeleteConfig(WebPMuxConfig* config) { static void DeleteConfig(Config* const config) {
if (config != NULL) { if (config != NULL) {
free(config->feature_.args_); free(config->args_);
ExUtilDeleteCommandLineArguments(&config->cmd_args_);
memset(config, 0, sizeof(*config)); memset(config, 0, sizeof(*config));
} }
} }
@ -531,7 +526,7 @@ static void DeleteConfig(WebPMuxConfig* config) {
// Returns 1 on valid, 0 otherwise. // Returns 1 on valid, 0 otherwise.
// Also fills up num_feature_args to be number of feature arguments given. // Also fills up num_feature_args to be number of feature arguments given.
// (e.g. if there are 4 '-frame's and 1 '-loop', then num_feature_args = 5). // (e.g. if there are 4 '-frame's and 1 '-loop', then num_feature_args = 5).
static int ValidateCommandLine(int argc, const char* argv[], static int ValidateCommandLine(const CommandLineArguments* const cmd_args,
int* num_feature_args) { int* num_feature_args) {
int num_frame_args; int num_frame_args;
int num_loop_args; int num_loop_args;
@ -543,27 +538,27 @@ static int ValidateCommandLine(int argc, const char* argv[],
*num_feature_args = 0; *num_feature_args = 0;
// Simple checks. // Simple checks.
if (CountOccurrences(argv, argc, "-get") > 1) { if (CountOccurrences(cmd_args, "-get") > 1) {
ERROR_GOTO1("ERROR: Multiple '-get' arguments specified.\n", ErrValidate); ERROR_GOTO1("ERROR: Multiple '-get' arguments specified.\n", ErrValidate);
} }
if (CountOccurrences(argv, argc, "-set") > 1) { if (CountOccurrences(cmd_args, "-set") > 1) {
ERROR_GOTO1("ERROR: Multiple '-set' arguments specified.\n", ErrValidate); ERROR_GOTO1("ERROR: Multiple '-set' arguments specified.\n", ErrValidate);
} }
if (CountOccurrences(argv, argc, "-strip") > 1) { if (CountOccurrences(cmd_args, "-strip") > 1) {
ERROR_GOTO1("ERROR: Multiple '-strip' arguments specified.\n", ErrValidate); ERROR_GOTO1("ERROR: Multiple '-strip' arguments specified.\n", ErrValidate);
} }
if (CountOccurrences(argv, argc, "-info") > 1) { if (CountOccurrences(cmd_args, "-info") > 1) {
ERROR_GOTO1("ERROR: Multiple '-info' arguments specified.\n", ErrValidate); ERROR_GOTO1("ERROR: Multiple '-info' arguments specified.\n", ErrValidate);
} }
if (CountOccurrences(argv, argc, "-o") > 1) { if (CountOccurrences(cmd_args, "-o") > 1) {
ERROR_GOTO1("ERROR: Multiple output files specified.\n", ErrValidate); ERROR_GOTO1("ERROR: Multiple output files specified.\n", ErrValidate);
} }
// Compound checks. // Compound checks.
num_frame_args = CountOccurrences(argv, argc, "-frame"); num_frame_args = CountOccurrences(cmd_args, "-frame");
num_loop_args = CountOccurrences(argv, argc, "-loop"); num_loop_args = CountOccurrences(cmd_args, "-loop");
num_bgcolor_args = CountOccurrences(argv, argc, "-bgcolor"); num_bgcolor_args = CountOccurrences(cmd_args, "-bgcolor");
num_durations_args = CountOccurrences(argv, argc, "-duration"); num_durations_args = CountOccurrences(cmd_args, "-duration");
if (num_loop_args > 1) { if (num_loop_args > 1) {
ERROR_GOTO1("ERROR: Multiple loop counts specified.\n", ErrValidate); ERROR_GOTO1("ERROR: Multiple loop counts specified.\n", ErrValidate);
@ -598,31 +593,35 @@ static int ValidateCommandLine(int argc, const char* argv[],
#define ACTION_IS_NIL (config->action_type_ == NIL_ACTION) #define ACTION_IS_NIL (config->action_type_ == NIL_ACTION)
#define FEATURETYPE_IS_NIL (feature->type_ == NIL_FEATURE) #define FEATURETYPE_IS_NIL (config->type_ == NIL_FEATURE)
#define CHECK_NUM_ARGS_LESS(NUM, LABEL) \ #define CHECK_NUM_ARGS_AT_LEAST(NUM, LABEL) \
if (argc < i + (NUM)) { \ if (argc < i + (NUM)) { \
fprintf(stderr, "ERROR: Too few arguments for '%s'.\n", argv[i]); \ fprintf(stderr, "ERROR: Too few arguments for '%s'.\n", argv[i]); \
goto LABEL; \ goto LABEL; \
} }
#define CHECK_NUM_ARGS_NOT_EQUAL(NUM, LABEL) \ #define CHECK_NUM_ARGS_AT_MOST(NUM, LABEL) \
if (argc != i + (NUM)) { \ if (argc > i + (NUM)) { \
fprintf(stderr, "ERROR: Too many arguments for '%s'.\n", argv[i]); \ fprintf(stderr, "ERROR: Too many arguments for '%s'.\n", argv[i]); \
goto LABEL; \ goto LABEL; \
} }
#define CHECK_NUM_ARGS_EXACTLY(NUM, LABEL) \
CHECK_NUM_ARGS_AT_LEAST(NUM, LABEL); \
CHECK_NUM_ARGS_AT_MOST(NUM, LABEL);
// Parses command-line arguments to fill up config object. Also performs some // Parses command-line arguments to fill up config object. Also performs some
// semantic checks. // semantic checks.
static int ParseCommandLine(int argc, const char* argv[], static int ParseCommandLine(Config* config) {
WebPMuxConfig* config) {
int i = 0; int i = 0;
int feature_arg_index = 0; int feature_arg_index = 0;
int ok = 1; int ok = 1;
int argc = config->cmd_args_.argc_;
const char* const* argv = config->cmd_args_.argv_;
while (i < argc) { while (i < argc) {
Feature* const feature = &config->feature_; FeatureArg* const arg = &config->args_[feature_arg_index];
FeatureArg* const arg = &feature->args_[feature_arg_index];
if (argv[i][0] == '-') { // One of the action types or output. if (argv[i][0] == '-') { // One of the action types or output.
if (!strcmp(argv[i], "-set")) { if (!strcmp(argv[i], "-set")) {
if (ACTION_IS_NIL) { if (ACTION_IS_NIL) {
@ -632,14 +631,14 @@ static int ParseCommandLine(int argc, const char* argv[],
} }
++i; ++i;
} else if (!strcmp(argv[i], "-duration")) { } else if (!strcmp(argv[i], "-duration")) {
CHECK_NUM_ARGS_LESS(2, ErrParse); CHECK_NUM_ARGS_AT_LEAST(2, ErrParse);
if (ACTION_IS_NIL || config->action_type_ == ACTION_DURATION) { if (ACTION_IS_NIL || config->action_type_ == ACTION_DURATION) {
config->action_type_ = ACTION_DURATION; config->action_type_ = ACTION_DURATION;
} else { } else {
ERROR_GOTO1("ERROR: Multiple actions specified.\n", ErrParse); ERROR_GOTO1("ERROR: Multiple actions specified.\n", ErrParse);
} }
if (FEATURETYPE_IS_NIL || feature->type_ == FEATURE_DURATION) { if (FEATURETYPE_IS_NIL || config->type_ == FEATURE_DURATION) {
feature->type_ = FEATURE_DURATION; config->type_ = FEATURE_DURATION;
} else { } else {
ERROR_GOTO1("ERROR: Multiple features specified.\n", ErrParse); ERROR_GOTO1("ERROR: Multiple features specified.\n", ErrParse);
} }
@ -656,20 +655,20 @@ static int ParseCommandLine(int argc, const char* argv[],
} else if (!strcmp(argv[i], "-strip")) { } else if (!strcmp(argv[i], "-strip")) {
if (ACTION_IS_NIL) { if (ACTION_IS_NIL) {
config->action_type_ = ACTION_STRIP; config->action_type_ = ACTION_STRIP;
feature->arg_count_ = 0; config->arg_count_ = 0;
} else { } else {
ERROR_GOTO1("ERROR: Multiple actions specified.\n", ErrParse); ERROR_GOTO1("ERROR: Multiple actions specified.\n", ErrParse);
} }
++i; ++i;
} else if (!strcmp(argv[i], "-frame")) { } else if (!strcmp(argv[i], "-frame")) {
CHECK_NUM_ARGS_LESS(3, ErrParse); CHECK_NUM_ARGS_AT_LEAST(3, ErrParse);
if (ACTION_IS_NIL || config->action_type_ == ACTION_SET) { if (ACTION_IS_NIL || config->action_type_ == ACTION_SET) {
config->action_type_ = ACTION_SET; config->action_type_ = ACTION_SET;
} else { } else {
ERROR_GOTO1("ERROR: Multiple actions specified.\n", ErrParse); ERROR_GOTO1("ERROR: Multiple actions specified.\n", ErrParse);
} }
if (FEATURETYPE_IS_NIL || feature->type_ == FEATURE_ANMF) { if (FEATURETYPE_IS_NIL || config->type_ == FEATURE_ANMF) {
feature->type_ = FEATURE_ANMF; config->type_ = FEATURE_ANMF;
} else { } else {
ERROR_GOTO1("ERROR: Multiple features specified.\n", ErrParse); ERROR_GOTO1("ERROR: Multiple features specified.\n", ErrParse);
} }
@ -679,14 +678,14 @@ static int ParseCommandLine(int argc, const char* argv[],
++feature_arg_index; ++feature_arg_index;
i += 3; i += 3;
} else if (!strcmp(argv[i], "-loop") || !strcmp(argv[i], "-bgcolor")) { } else if (!strcmp(argv[i], "-loop") || !strcmp(argv[i], "-bgcolor")) {
CHECK_NUM_ARGS_LESS(2, ErrParse); CHECK_NUM_ARGS_AT_LEAST(2, ErrParse);
if (ACTION_IS_NIL || config->action_type_ == ACTION_SET) { if (ACTION_IS_NIL || config->action_type_ == ACTION_SET) {
config->action_type_ = ACTION_SET; config->action_type_ = ACTION_SET;
} else { } else {
ERROR_GOTO1("ERROR: Multiple actions specified.\n", ErrParse); ERROR_GOTO1("ERROR: Multiple actions specified.\n", ErrParse);
} }
if (FEATURETYPE_IS_NIL || feature->type_ == FEATURE_ANMF) { if (FEATURETYPE_IS_NIL || config->type_ == FEATURE_ANMF) {
feature->type_ = FEATURE_ANMF; config->type_ = FEATURE_ANMF;
} else { } else {
ERROR_GOTO1("ERROR: Multiple features specified.\n", ErrParse); ERROR_GOTO1("ERROR: Multiple features specified.\n", ErrParse);
} }
@ -696,16 +695,16 @@ static int ParseCommandLine(int argc, const char* argv[],
++feature_arg_index; ++feature_arg_index;
i += 2; i += 2;
} else if (!strcmp(argv[i], "-o")) { } else if (!strcmp(argv[i], "-o")) {
CHECK_NUM_ARGS_LESS(2, ErrParse); CHECK_NUM_ARGS_AT_LEAST(2, ErrParse);
config->output_ = argv[i + 1]; config->output_ = argv[i + 1];
i += 2; i += 2;
} else if (!strcmp(argv[i], "-info")) { } else if (!strcmp(argv[i], "-info")) {
CHECK_NUM_ARGS_NOT_EQUAL(2, ErrParse); CHECK_NUM_ARGS_EXACTLY(2, ErrParse);
if (config->action_type_ != NIL_ACTION) { if (config->action_type_ != NIL_ACTION) {
ERROR_GOTO1("ERROR: Multiple actions specified.\n", ErrParse); ERROR_GOTO1("ERROR: Multiple actions specified.\n", ErrParse);
} else { } else {
config->action_type_ = ACTION_INFO; config->action_type_ = ACTION_INFO;
feature->arg_count_ = 0; config->arg_count_ = 0;
config->input_ = argv[i + 1]; config->input_ = argv[i + 1];
} }
i += 2; i += 2;
@ -741,13 +740,13 @@ static int ParseCommandLine(int argc, const char* argv[],
if (!strcmp(argv[i], "icc") || !strcmp(argv[i], "exif") || if (!strcmp(argv[i], "icc") || !strcmp(argv[i], "exif") ||
!strcmp(argv[i], "xmp")) { !strcmp(argv[i], "xmp")) {
if (FEATURETYPE_IS_NIL) { if (FEATURETYPE_IS_NIL) {
feature->type_ = (!strcmp(argv[i], "icc")) ? FEATURE_ICCP : config->type_ = (!strcmp(argv[i], "icc")) ? FEATURE_ICCP :
(!strcmp(argv[i], "exif")) ? FEATURE_EXIF : FEATURE_XMP; (!strcmp(argv[i], "exif")) ? FEATURE_EXIF : FEATURE_XMP;
} else { } else {
ERROR_GOTO1("ERROR: Multiple features specified.\n", ErrParse); ERROR_GOTO1("ERROR: Multiple features specified.\n", ErrParse);
} }
if (config->action_type_ == ACTION_SET) { if (config->action_type_ == ACTION_SET) {
CHECK_NUM_ARGS_LESS(2, ErrParse); CHECK_NUM_ARGS_AT_LEAST(2, ErrParse);
arg->filename_ = argv[i + 1]; arg->filename_ = argv[i + 1];
++feature_arg_index; ++feature_arg_index;
i += 2; i += 2;
@ -756,8 +755,8 @@ static int ParseCommandLine(int argc, const char* argv[],
} }
} else if (!strcmp(argv[i], "frame") && } else if (!strcmp(argv[i], "frame") &&
(config->action_type_ == ACTION_GET)) { (config->action_type_ == ACTION_GET)) {
CHECK_NUM_ARGS_LESS(2, ErrParse); CHECK_NUM_ARGS_AT_LEAST(2, ErrParse);
feature->type_ = FEATURE_ANMF; config->type_ = FEATURE_ANMF;
arg->params_ = argv[i + 1]; arg->params_ = argv[i + 1];
++feature_arg_index; ++feature_arg_index;
i += 2; i += 2;
@ -777,9 +776,8 @@ static int ParseCommandLine(int argc, const char* argv[],
} }
// Additional checks after config is filled. // Additional checks after config is filled.
static int ValidateConfig(WebPMuxConfig* config) { static int ValidateConfig(Config* const config) {
int ok = 1; int ok = 1;
Feature* const feature = &config->feature_;
// Action. // Action.
if (ACTION_IS_NIL) { if (ACTION_IS_NIL) {
@ -795,7 +793,7 @@ static int ValidateConfig(WebPMuxConfig* config) {
if (config->input_ == NULL) { if (config->input_ == NULL) {
if (config->action_type_ != ACTION_SET) { if (config->action_type_ != ACTION_SET) {
ERROR_GOTO1("ERROR: No input file specified.\n", ErrValidate2); ERROR_GOTO1("ERROR: No input file specified.\n", ErrValidate2);
} else if (feature->type_ != FEATURE_ANMF) { } else if (config->type_ != FEATURE_ANMF) {
ERROR_GOTO1("ERROR: No input file specified.\n", ErrValidate2); ERROR_GOTO1("ERROR: No input file specified.\n", ErrValidate2);
} }
} }
@ -811,27 +809,28 @@ static int ValidateConfig(WebPMuxConfig* config) {
// Create config object from command-line arguments. // Create config object from command-line arguments.
static int InitializeConfig(int argc, const char* argv[], static int InitializeConfig(int argc, const char* argv[],
WebPMuxConfig* config) { Config* const config) {
int num_feature_args = 0; int num_feature_args = 0;
int ok = 1; int ok;
assert(config != NULL);
memset(config, 0, sizeof(*config)); memset(config, 0, sizeof(*config));
ok = ExUtilInitCommandLineArguments(argc, argv, &config->cmd_args_);
if (!ok) return 0;
// Validate command-line arguments. // Validate command-line arguments.
if (!ValidateCommandLine(argc, argv, &num_feature_args)) { if (!ValidateCommandLine(&config->cmd_args_, &num_feature_args)) {
ERROR_GOTO1("Exiting due to command-line parsing error.\n", Err1); ERROR_GOTO1("Exiting due to command-line parsing error.\n", Err1);
} }
config->feature_.arg_count_ = num_feature_args; config->arg_count_ = num_feature_args;
config->feature_.args_ = config->args_ = (FeatureArg*)calloc(num_feature_args, sizeof(*config->args_));
(FeatureArg*)calloc(num_feature_args, sizeof(*config->feature_.args_)); if (config->args_ == NULL) {
if (config->feature_.args_ == NULL) {
ERROR_GOTO1("ERROR: Memory allocation error.\n", Err1); ERROR_GOTO1("ERROR: Memory allocation error.\n", Err1);
} }
// Parse command-line. // Parse command-line.
if (!ParseCommandLine(argc, argv, config) || !ValidateConfig(config)) { if (!ParseCommandLine(config) || !ValidateConfig(config)) {
ERROR_GOTO1("Exiting due to command-line parsing error.\n", Err1); ERROR_GOTO1("Exiting due to command-line parsing error.\n", Err1);
} }
@ -841,13 +840,14 @@ static int InitializeConfig(int argc, const char* argv[],
#undef ACTION_IS_NIL #undef ACTION_IS_NIL
#undef FEATURETYPE_IS_NIL #undef FEATURETYPE_IS_NIL
#undef CHECK_NUM_ARGS_LESS #undef CHECK_NUM_ARGS_AT_LEAST
#undef CHECK_NUM_ARGS_MORE #undef CHECK_NUM_ARGS_AT_MOST
#undef CHECK_NUM_ARGS_EXACTLY
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// Processing. // Processing.
static int GetFrame(const WebPMux* mux, const WebPMuxConfig* config) { static int GetFrame(const WebPMux* mux, const Config* config) {
WebPMuxError err = WEBP_MUX_OK; WebPMuxError err = WEBP_MUX_OK;
WebPMux* mux_single = NULL; WebPMux* mux_single = NULL;
int num = 0; int num = 0;
@ -857,7 +857,7 @@ static int GetFrame(const WebPMux* mux, const WebPMuxConfig* config) {
WebPMuxFrameInfo info; WebPMuxFrameInfo info;
WebPDataInit(&info.bitstream); WebPDataInit(&info.bitstream);
num = ExUtilGetInt(config->feature_.args_[0].params_, 10, &parse_error); num = ExUtilGetInt(config->args_[0].params_, 10, &parse_error);
if (num < 0) { if (num < 0) {
ERROR_GOTO1("ERROR: Frame/Fragment index must be non-negative.\n", ErrGet); ERROR_GOTO1("ERROR: Frame/Fragment index must be non-negative.\n", ErrGet);
} }
@ -891,18 +891,17 @@ static int GetFrame(const WebPMux* mux, const WebPMuxConfig* config) {
} }
// Read and process config. // Read and process config.
static int Process(const WebPMuxConfig* config) { static int Process(const Config* config) {
WebPMux* mux = NULL; WebPMux* mux = NULL;
WebPData chunk; WebPData chunk;
WebPMuxError err = WEBP_MUX_OK; WebPMuxError err = WEBP_MUX_OK;
int ok = 1; int ok = 1;
const Feature* const feature = &config->feature_;
switch (config->action_type_) { switch (config->action_type_) {
case ACTION_GET: { case ACTION_GET: {
ok = CreateMux(config->input_, &mux); ok = CreateMux(config->input_, &mux);
if (!ok) goto Err2; if (!ok) goto Err2;
switch (feature->type_) { switch (config->type_) {
case FEATURE_ANMF: case FEATURE_ANMF:
ok = GetFrame(mux, config); ok = GetFrame(mux, config);
break; break;
@ -910,10 +909,10 @@ static int Process(const WebPMuxConfig* config) {
case FEATURE_ICCP: case FEATURE_ICCP:
case FEATURE_EXIF: case FEATURE_EXIF:
case FEATURE_XMP: case FEATURE_XMP:
err = WebPMuxGetChunk(mux, kFourccList[feature->type_], &chunk); err = WebPMuxGetChunk(mux, kFourccList[config->type_], &chunk);
if (err != WEBP_MUX_OK) { if (err != WEBP_MUX_OK) {
ERROR_GOTO3("ERROR (%s): Could not get the %s.\n", ERROR_GOTO3("ERROR (%s): Could not get the %s.\n",
ErrorString(err), kDescriptions[feature->type_], Err2); ErrorString(err), kDescriptions[config->type_], Err2);
} }
ok = WriteData(config->output_, &chunk); ok = WriteData(config->output_, &chunk);
break; break;
@ -925,7 +924,7 @@ static int Process(const WebPMuxConfig* config) {
break; break;
} }
case ACTION_SET: { case ACTION_SET: {
switch (feature->type_) { switch (config->type_) {
case FEATURE_ANMF: { case FEATURE_ANMF: {
int i; int i;
WebPMuxAnimParams params = { 0xFFFFFFFF, 0 }; WebPMuxAnimParams params = { 0xFFFFFFFF, 0 };
@ -934,11 +933,11 @@ static int Process(const WebPMuxConfig* config) {
ERROR_GOTO2("ERROR (%s): Could not allocate a mux object.\n", ERROR_GOTO2("ERROR (%s): Could not allocate a mux object.\n",
ErrorString(WEBP_MUX_MEMORY_ERROR), Err2); ErrorString(WEBP_MUX_MEMORY_ERROR), Err2);
} }
for (i = 0; i < feature->arg_count_; ++i) { for (i = 0; i < config->arg_count_; ++i) {
switch (feature->args_[i].subtype_) { switch (config->args_[i].subtype_) {
case SUBTYPE_BGCOLOR: { case SUBTYPE_BGCOLOR: {
uint32_t bgcolor; uint32_t bgcolor;
ok = ParseBgcolorArgs(feature->args_[i].params_, &bgcolor); ok = ParseBgcolorArgs(config->args_[i].params_, &bgcolor);
if (!ok) { if (!ok) {
ERROR_GOTO1("ERROR: Could not parse the background color \n", ERROR_GOTO1("ERROR: Could not parse the background color \n",
Err2); Err2);
@ -949,7 +948,7 @@ static int Process(const WebPMuxConfig* config) {
case SUBTYPE_LOOP: { case SUBTYPE_LOOP: {
int parse_error = 0; int parse_error = 0;
const int loop_count = const int loop_count =
ExUtilGetInt(feature->args_[i].params_, 10, &parse_error); ExUtilGetInt(config->args_[i].params_, 10, &parse_error);
if (loop_count < 0 || loop_count > 65535) { if (loop_count < 0 || loop_count > 65535) {
// Note: This is only a 'necessary' condition for loop_count // Note: This is only a 'necessary' condition for loop_count
// to be valid. The 'sufficient' conditioned in checked in // to be valid. The 'sufficient' conditioned in checked in
@ -965,10 +964,10 @@ static int Process(const WebPMuxConfig* config) {
case SUBTYPE_ANMF: { case SUBTYPE_ANMF: {
WebPMuxFrameInfo frame; WebPMuxFrameInfo frame;
frame.id = WEBP_CHUNK_ANMF; frame.id = WEBP_CHUNK_ANMF;
ok = ReadFileToWebPData(feature->args_[i].filename_, ok = ExUtilReadFileToWebPData(config->args_[i].filename_,
&frame.bitstream); &frame.bitstream);
if (!ok) goto Err2; if (!ok) goto Err2;
ok = ParseFrameArgs(feature->args_[i].params_, &frame); ok = ParseFrameArgs(config->args_[i].params_, &frame);
if (!ok) { if (!ok) {
WebPDataClear(&frame.bitstream); WebPDataClear(&frame.bitstream);
ERROR_GOTO1("ERROR: Could not parse frame properties.\n", ERROR_GOTO1("ERROR: Could not parse frame properties.\n",
@ -1001,13 +1000,13 @@ static int Process(const WebPMuxConfig* config) {
case FEATURE_XMP: { case FEATURE_XMP: {
ok = CreateMux(config->input_, &mux); ok = CreateMux(config->input_, &mux);
if (!ok) goto Err2; if (!ok) goto Err2;
ok = ReadFileToWebPData(feature->args_[0].filename_, &chunk); ok = ExUtilReadFileToWebPData(config->args_[0].filename_, &chunk);
if (!ok) goto Err2; if (!ok) goto Err2;
err = WebPMuxSetChunk(mux, kFourccList[feature->type_], &chunk, 1); err = WebPMuxSetChunk(mux, kFourccList[config->type_], &chunk, 1);
free((void*)chunk.bytes); free((void*)chunk.bytes);
if (err != WEBP_MUX_OK) { if (err != WEBP_MUX_OK) {
ERROR_GOTO3("ERROR (%s): Could not set the %s.\n", ERROR_GOTO3("ERROR (%s): Could not set the %s.\n",
ErrorString(err), kDescriptions[feature->type_], Err2); ErrorString(err), kDescriptions[config->type_], Err2);
} }
break; break;
} }
@ -1043,11 +1042,11 @@ static int Process(const WebPMuxConfig* config) {
for (i = 0; i < num_frames; ++i) durations[i] = -1; for (i = 0; i < num_frames; ++i) durations[i] = -1;
// Parse intervals to process. // Parse intervals to process.
for (i = 0; i < feature->arg_count_; ++i) { for (i = 0; i < config->arg_count_; ++i) {
int k; int k;
int args[3]; int args[3];
int duration, start, end; int duration, start, end;
const int nb_args = ExUtilGetInts(feature->args_[i].params_, const int nb_args = ExUtilGetInts(config->args_[i].params_,
10, 3, args); 10, 3, args);
ok = (nb_args >= 1); ok = (nb_args >= 1);
if (!ok) goto Err3; if (!ok) goto Err3;
@ -1105,12 +1104,12 @@ static int Process(const WebPMuxConfig* config) {
case ACTION_STRIP: { case ACTION_STRIP: {
ok = CreateMux(config->input_, &mux); ok = CreateMux(config->input_, &mux);
if (!ok) goto Err2; if (!ok) goto Err2;
if (feature->type_ == FEATURE_ICCP || feature->type_ == FEATURE_EXIF || if (config->type_ == FEATURE_ICCP || config->type_ == FEATURE_EXIF ||
feature->type_ == FEATURE_XMP) { config->type_ == FEATURE_XMP) {
err = WebPMuxDeleteChunk(mux, kFourccList[feature->type_]); err = WebPMuxDeleteChunk(mux, kFourccList[config->type_]);
if (err != WEBP_MUX_OK) { if (err != WEBP_MUX_OK) {
ERROR_GOTO3("ERROR (%s): Could not strip the %s.\n", ERROR_GOTO3("ERROR (%s): Could not strip the %s.\n",
ErrorString(err), kDescriptions[feature->type_], Err2); ErrorString(err), kDescriptions[config->type_], Err2);
} }
} else { } else {
ERROR_GOTO1("ERROR: Invalid feature for action 'strip'.\n", Err2); ERROR_GOTO1("ERROR: Invalid feature for action 'strip'.\n", Err2);
@ -1140,7 +1139,7 @@ static int Process(const WebPMuxConfig* config) {
// Main. // Main.
int main(int argc, const char* argv[]) { int main(int argc, const char* argv[]) {
WebPMuxConfig config; Config config;
int ok = InitializeConfig(argc - 1, argv + 1, &config); int ok = InitializeConfig(argc - 1, argv + 1, &config);
if (ok) { if (ok) {
ok = Process(&config); ok = Process(&config);

View File

@ -13,7 +13,10 @@ libwebpextras_la_LDFLAGS = -lm
libwebpextras_la_LIBADD = ../src/libwebp.la libwebpextras_la_LIBADD = ../src/libwebp.la
noinst_PROGRAMS = noinst_PROGRAMS =
noinst_PROGRAMS += get_disto webp_quality noinst_PROGRAMS += webp_quality
if BUILD_DEMUX
noinst_PROGRAMS += get_disto
endif
if BUILD_VWEBP_SDL if BUILD_VWEBP_SDL
noinst_PROGRAMS += vwebp_sdl noinst_PROGRAMS += vwebp_sdl
endif endif
@ -27,7 +30,7 @@ get_disto_LDADD += ../src/libwebp.la
get_disto_LDADD += $(PNG_LIBS) $(JPEG_LIBS) $(TIFF_LIBS) get_disto_LDADD += $(PNG_LIBS) $(JPEG_LIBS) $(TIFF_LIBS)
webp_quality_SOURCES = webp_quality.c webp_quality_SOURCES = webp_quality.c
webp_quality_CPPFLAGS = $(AM_CPPFLAGS) $(USE_EXPERIMENTAL_CODE) webp_quality_CPPFLAGS = $(AM_CPPFLAGS)
webp_quality_LDADD = webp_quality_LDADD =
webp_quality_LDADD += ../imageio/libimageio_util.la webp_quality_LDADD += ../imageio/libimageio_util.la
webp_quality_LDADD += libwebpextras.la webp_quality_LDADD += libwebpextras.la

View File

@ -16,8 +16,8 @@
#include <assert.h> #include <assert.h>
#include <string.h> #include <string.h>
#define XTRA_MAJ_VERSION 0 #define XTRA_MAJ_VERSION 1
#define XTRA_MIN_VERSION 1 #define XTRA_MIN_VERSION 0
#define XTRA_REV_VERSION 1 #define XTRA_REV_VERSION 1
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
@ -48,13 +48,14 @@ int WebPImportGray(const uint8_t* gray_data, WebPPicture* pic) {
int WebPImportRGB565(const uint8_t* rgb565, WebPPicture* pic) { int WebPImportRGB565(const uint8_t* rgb565, WebPPicture* pic) {
int x, y; int x, y;
uint32_t* dst;
if (pic == NULL || rgb565 == NULL) return 0; if (pic == NULL || rgb565 == NULL) return 0;
pic->colorspace = WEBP_YUV420; pic->colorspace = WEBP_YUV420;
pic->use_argb = 1; pic->use_argb = 1;
if (!WebPPictureAlloc(pic)) return 0; if (!WebPPictureAlloc(pic)) return 0;
dst = pic->argb;
for (y = 0; y < pic->height; ++y) { for (y = 0; y < pic->height; ++y) {
const int width = pic->width; const int width = pic->width;
uint32_t* dst = pic->argb + y * pic->argb_stride;
for (x = 0; x < width; ++x) { for (x = 0; x < width; ++x) {
#ifdef WEBP_SWAP_16BIT_CSP #ifdef WEBP_SWAP_16BIT_CSP
const uint32_t rg = rgb565[2 * x + 1]; const uint32_t rg = rgb565[2 * x + 1];
@ -70,22 +71,24 @@ int WebPImportRGB565(const uint8_t* rgb565, WebPPicture* pic) {
r = r | (r >> 5); r = r | (r >> 5);
g = g | (g >> 6); g = g | (g >> 6);
b = b | (b >> 5); b = b | (b >> 5);
dst[x] = (r << 16) | (g << 8) | b; dst[x] = (0xffu << 24) | (r << 16) | (g << 8) | b;
} }
rgb565 += 2 * width; rgb565 += 2 * width;
dst += pic->argb_stride;
} }
return 1; return 1;
} }
int WebPImportRGB4444(const uint8_t* rgb4444, WebPPicture* pic) { int WebPImportRGB4444(const uint8_t* rgb4444, WebPPicture* pic) {
int x, y; int x, y;
uint32_t* dst;
if (pic == NULL || rgb4444 == NULL) return 0; if (pic == NULL || rgb4444 == NULL) return 0;
pic->colorspace = WEBP_YUV420; pic->colorspace = WEBP_YUV420;
pic->use_argb = 1; pic->use_argb = 1;
if (!WebPPictureAlloc(pic)) return 0; if (!WebPPictureAlloc(pic)) return 0;
dst = pic->argb;
for (y = 0; y < pic->height; ++y) { for (y = 0; y < pic->height; ++y) {
const int width = pic->width; const int width = pic->width;
uint32_t* dst = pic->argb + y * pic->argb_stride;
for (x = 0; x < width; ++x) { for (x = 0; x < width; ++x) {
#ifdef WEBP_SWAP_16BIT_CSP #ifdef WEBP_SWAP_16BIT_CSP
const uint32_t rg = rgb4444[2 * x + 1]; const uint32_t rg = rgb4444[2 * x + 1];
@ -106,6 +109,7 @@ int WebPImportRGB4444(const uint8_t* rgb4444, WebPPicture* pic) {
dst[x] = (a << 24) | (r << 16) | (g << 8) | b; dst[x] = (a << 24) | (r << 16) | (g << 8) | b;
} }
rgb4444 += 2 * width; rgb4444 += 2 * width;
dst += pic->argb_stride;
} }
return 1; return 1;
} }

View File

@ -67,4 +67,4 @@ WEBP_EXTERN int VP8EstimateQuality(const uint8_t* const data, size_t size);
} // extern "C" } // extern "C"
#endif #endif
#endif /* WEBP_EXTRAS_EXTRAS_H_ */ #endif // WEBP_EXTRAS_EXTRAS_H_

View File

@ -290,9 +290,10 @@ int main(int argc, const char *argv[]) {
fprintf(stderr, "Error while computing the distortion.\n"); fprintf(stderr, "Error while computing the distortion.\n");
goto End; goto End;
} }
printf("%u %.2f %.2f %.2f %.2f %.2f\n", printf("%u %.2f %.2f %.2f %.2f %.2f [ %.2f bpp ]\n",
(unsigned int)size1, (unsigned int)size1,
disto[4], disto[0], disto[1], disto[2], disto[3]); disto[4], disto[0], disto[1], disto[2], disto[3],
8.f * size1 / pic1.width / pic1.height);
if (output != NULL) { if (output != NULL) {
uint8_t* data = NULL; uint8_t* data = NULL;

View File

@ -73,7 +73,7 @@ int VP8EstimateQuality(const uint8_t* const data, size_t size) {
pos += 4; pos += 4;
bit_pos = pos * 8; bit_pos = pos * 8;
GET_BIT(2); // color_space + clamp type GET_BIT(2); // colorspace + clamp type
// Segment header // Segment header
if (GET_BIT(1)) { // use_segment_ if (GET_BIT(1)) { // use_segment_

View File

@ -12,7 +12,7 @@
// Author: James Zern (jzern@google.com) // Author: James Zern (jzern@google.com)
#ifdef HAVE_CONFIG_H #ifdef HAVE_CONFIG_H
#include "webp/config.h" #include "src/webp/config.h"
#endif #endif
#if defined(WEBP_HAVE_SDL) #if defined(WEBP_HAVE_SDL)
@ -20,7 +20,7 @@
#include "webp_to_sdl.h" #include "webp_to_sdl.h"
#include <stdio.h> #include <stdio.h>
#include "webp/decode.h" #include "src/webp/decode.h"
#if defined(WEBP_HAVE_JUST_SDL_H) #if defined(WEBP_HAVE_JUST_SDL_H)
#include <SDL.h> #include <SDL.h>
@ -40,7 +40,7 @@ int WebpToSDL(const char* data, unsigned int data_size) {
if (!WebPInitDecoderConfig(&config)) { if (!WebPInitDecoderConfig(&config)) {
fprintf(stderr, "Library version mismatch!\n"); fprintf(stderr, "Library version mismatch!\n");
return 1; return 0;
} }
if (!init_ok) { if (!init_ok) {

View File

@ -1,7 +1,9 @@
AM_CPPFLAGS += -I$(top_builddir)/src -I$(top_srcdir)/src AM_CPPFLAGS += -I$(top_builddir)/src -I$(top_srcdir)/src
noinst_LTLIBRARIES = noinst_LTLIBRARIES =
noinst_LTLIBRARIES += libimageio_util.la noinst_LTLIBRARIES += libimageio_util.la
noinst_LTLIBRARIES += libimagedec.la if BUILD_DEMUX
noinst_LTLIBRARIES += libimagedec.la
endif
noinst_LTLIBRARIES += libimageenc.la noinst_LTLIBRARIES += libimageenc.la
noinst_HEADERS = noinst_HEADERS =
@ -21,9 +23,10 @@ libimagedec_la_SOURCES += tiffdec.c tiffdec.h
libimagedec_la_SOURCES += webpdec.c webpdec.h libimagedec_la_SOURCES += webpdec.c webpdec.h
libimagedec_la_SOURCES += wicdec.c wicdec.h libimagedec_la_SOURCES += wicdec.c wicdec.h
libimagedec_la_CPPFLAGS = $(JPEG_INCLUDES) $(PNG_INCLUDES) $(TIFF_INCLUDES) libimagedec_la_CPPFLAGS = $(JPEG_INCLUDES) $(PNG_INCLUDES) $(TIFF_INCLUDES)
libimagedec_la_CPPFLAGS += $(AM_CPPFLAGS) $(USE_EXPERIMENTAL_CODE) libimagedec_la_CPPFLAGS += $(AM_CPPFLAGS)
libimagedec_la_LIBADD = ../src/demux/libwebpdemux.la
libimageenc_la_SOURCES = libimageenc_la_SOURCES =
libimageenc_la_SOURCES += image_enc.c image_enc.h libimageenc_la_SOURCES += image_enc.c image_enc.h
libimageenc_la_CPPFLAGS = $(JPEG_INCLUDES) $(PNG_INCLUDES) $(TIFF_INCLUDES) libimageenc_la_CPPFLAGS = $(JPEG_INCLUDES) $(PNG_INCLUDES) $(TIFF_INCLUDES)
libimageenc_la_CPPFLAGS += $(AM_CPPFLAGS) $(USE_EXPERIMENTAL_CODE) libimageenc_la_CPPFLAGS += $(AM_CPPFLAGS)

View File

@ -158,14 +158,8 @@ static void PNGAPI PNGErrorFunction(png_structp png, png_const_charp dummy) {
} }
int WebPWritePNG(FILE* out_file, const WebPDecBuffer* const buffer) { int WebPWritePNG(FILE* out_file, const WebPDecBuffer* const buffer) {
const uint32_t width = buffer->width;
const uint32_t height = buffer->height;
png_bytep row = buffer->u.RGBA.rgba;
const int stride = buffer->u.RGBA.stride;
const int has_alpha = WebPIsAlphaMode(buffer->colorspace);
volatile png_structp png; volatile png_structp png;
volatile png_infop info; volatile png_infop info;
png_uint_32 y;
if (out_file == NULL || buffer == NULL) return 0; if (out_file == NULL || buffer == NULL) return 0;
@ -184,14 +178,23 @@ int WebPWritePNG(FILE* out_file, const WebPDecBuffer* const buffer) {
return 0; return 0;
} }
png_init_io(png, out_file); png_init_io(png, out_file);
png_set_IHDR(png, info, width, height, 8, {
has_alpha ? PNG_COLOR_TYPE_RGBA : PNG_COLOR_TYPE_RGB, const uint32_t width = buffer->width;
PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, const uint32_t height = buffer->height;
PNG_FILTER_TYPE_DEFAULT); png_bytep row = buffer->u.RGBA.rgba;
png_write_info(png, info); const int stride = buffer->u.RGBA.stride;
for (y = 0; y < height; ++y) { const int has_alpha = WebPIsAlphaMode(buffer->colorspace);
png_write_rows(png, &row, 1); uint32_t y;
row += stride;
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);
for (y = 0; y < height; ++y) {
png_write_rows(png, &row, 1);
row += stride;
}
} }
png_write_end(png, info); png_write_end(png, info);
png_destroy_write_struct((png_structpp)&png, (png_infopp)&info); png_destroy_write_struct((png_structpp)&png, (png_infopp)&info);

View File

@ -47,7 +47,8 @@ int ImgIoUtilReadFromStdin(const uint8_t** data, size_t* data_size) {
while (!feof(stdin)) { while (!feof(stdin)) {
// We double the buffer size each time and read as much as possible. // We double the buffer size each time and read as much as possible.
const size_t extra_size = (max_size == 0) ? kBlockSize : max_size; const size_t extra_size = (max_size == 0) ? kBlockSize : max_size;
void* const new_data = realloc(input, max_size + extra_size); // we allocate one extra byte for the \0 terminator
void* const new_data = realloc(input, max_size + extra_size + 1);
if (new_data == NULL) goto Error; if (new_data == NULL) goto Error;
input = (uint8_t*)new_data; input = (uint8_t*)new_data;
max_size += extra_size; max_size += extra_size;
@ -55,6 +56,7 @@ int ImgIoUtilReadFromStdin(const uint8_t** data, size_t* data_size) {
if (size < max_size) break; if (size < max_size) break;
} }
if (ferror(stdin)) goto Error; if (ferror(stdin)) goto Error;
if (input != NULL) input[size] = '\0'; // convenient 0-terminator
*data = input; *data = input;
*data_size = size; *data_size = size;
return 1; return 1;
@ -68,7 +70,7 @@ int ImgIoUtilReadFromStdin(const uint8_t** data, size_t* data_size) {
int ImgIoUtilReadFile(const char* const file_name, int ImgIoUtilReadFile(const char* const file_name,
const uint8_t** data, size_t* data_size) { const uint8_t** data, size_t* data_size) {
int ok; int ok;
void* file_data; uint8_t* file_data;
size_t file_size; size_t file_size;
FILE* in; FILE* in;
const int from_stdin = (file_name == NULL) || !strcmp(file_name, "-"); const int from_stdin = (file_name == NULL) || !strcmp(file_name, "-");
@ -87,8 +89,14 @@ int ImgIoUtilReadFile(const char* const file_name,
fseek(in, 0, SEEK_END); fseek(in, 0, SEEK_END);
file_size = ftell(in); file_size = ftell(in);
fseek(in, 0, SEEK_SET); fseek(in, 0, SEEK_SET);
file_data = malloc(file_size); // we allocate one extra byte for the \0 terminator
if (file_data == NULL) return 0; file_data = (uint8_t*)malloc(file_size + 1);
if (file_data == NULL) {
fclose(in);
fprintf(stderr, "memory allocation failure when reading file %s\n",
file_name);
return 0;
}
ok = (fread(file_data, file_size, 1, in) == 1); ok = (fread(file_data, file_size, 1, in) == 1);
fclose(in); fclose(in);
@ -98,11 +106,14 @@ int ImgIoUtilReadFile(const char* const file_name,
free(file_data); free(file_data);
return 0; return 0;
} }
*data = (uint8_t*)file_data; file_data[file_size] = '\0'; // convenient 0-terminator
*data = file_data;
*data_size = file_size; *data_size = file_size;
return 1; return 1;
} }
// -----------------------------------------------------------------------------
int ImgIoUtilWriteFile(const char* const file_name, int ImgIoUtilWriteFile(const char* const file_name,
const uint8_t* data, size_t data_size) { const uint8_t* data, size_t data_size) {
int ok; int ok;

View File

@ -30,6 +30,9 @@ FILE* ImgIoUtilSetBinaryMode(FILE* file);
// Allocates storage for entire file 'file_name' and returns contents and size // Allocates storage for entire file 'file_name' and returns contents and size
// in 'data' and 'data_size'. Returns 1 on success, 0 otherwise. '*data' should // in 'data' and 'data_size'. Returns 1 on success, 0 otherwise. '*data' should
// be deleted using free(). // be deleted using free().
// Note: for convenience, the data will be null-terminated with an extra byte
// (not accounted for in *data_size), in case the file is text and intended
// to be used as a C-string.
// If 'file_name' is NULL or equal to "-", input is read from stdin by calling // If 'file_name' is NULL or equal to "-", input is read from stdin by calling
// the function ImgIoUtilReadFromStdin(). // the function ImgIoUtilReadFromStdin().
int ImgIoUtilReadFile(const char* const file_name, int ImgIoUtilReadFile(const char* const file_name,

View File

@ -18,6 +18,9 @@
#include <stdio.h> #include <stdio.h>
#ifdef WEBP_HAVE_PNG #ifdef WEBP_HAVE_PNG
#ifndef PNG_USER_MEM_SUPPORTED
#define PNG_USER_MEM_SUPPORTED // for png_create_read_struct_2
#endif
#include <png.h> #include <png.h>
#include <setjmp.h> // note: this must be included *after* png.h #include <setjmp.h> // note: this must be included *after* png.h
#include <stdlib.h> #include <stdlib.h>
@ -27,11 +30,33 @@
#include "./imageio_util.h" #include "./imageio_util.h"
#include "./metadata.h" #include "./metadata.h"
#define LOCAL_PNG_VERSION ((PNG_LIBPNG_VER_MAJOR << 8) | PNG_LIBPNG_VER_MINOR)
#define LOCAL_PNG_PREREQ(maj, min) \
(LOCAL_PNG_VERSION >= (((maj) << 8) | (min)))
static void PNGAPI error_function(png_structp png, png_const_charp error) { static void PNGAPI error_function(png_structp png, png_const_charp error) {
if (error != NULL) fprintf(stderr, "libpng error: %s\n", error); if (error != NULL) fprintf(stderr, "libpng error: %s\n", error);
longjmp(png_jmpbuf(png), 1); longjmp(png_jmpbuf(png), 1);
} }
#if LOCAL_PNG_PREREQ(1,4)
typedef png_alloc_size_t LocalPngAllocSize;
#else
typedef png_size_t LocalPngAllocSize;
#endif
static png_voidp MallocFunc(png_structp png_ptr, LocalPngAllocSize size) {
(void)png_ptr;
if (size != (size_t)size) return NULL;
if (!ImgIoUtilCheckSizeArgumentsOverflow(size, 1)) return NULL;
return (png_voidp)malloc((size_t)size);
}
static void FreeFunc(png_structp png_ptr, png_voidp ptr) {
(void)png_ptr;
free(ptr);
}
// Converts the NULL terminated 'hexstring' which contains 2-byte character // Converts the NULL terminated 'hexstring' which contains 2-byte character
// representations of hex values to raw data. // representations of hex values to raw data.
// 'hexstring' may contain values consisting of [A-F][a-f][0-9] in pairs, // 'hexstring' may contain values consisting of [A-F][a-f][0-9] in pairs,
@ -171,11 +196,10 @@ static int ExtractMetadataFromPNG(png_structp png,
{ {
png_charp name; png_charp name;
int comp_type; int comp_type;
#if ((PNG_LIBPNG_VER_MAJOR << 8) | PNG_LIBPNG_VER_MINOR << 0) < \ #if LOCAL_PNG_PREREQ(1,5)
((1 << 8) | (5 << 0))
png_charp profile;
#else // >= libpng 1.5.0
png_bytep profile; png_bytep profile;
#else
png_charp profile;
#endif #endif
png_uint_32 len; png_uint_32 len;
@ -185,7 +209,6 @@ static int ExtractMetadataFromPNG(png_structp png,
} }
} }
} }
return 1; return 1;
} }
@ -225,7 +248,8 @@ int ReadPNG(const uint8_t* const data, size_t data_size,
context.data = data; context.data = data;
context.data_size = data_size; context.data_size = data_size;
png = png_create_read_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0); png = png_create_read_struct_2(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL,
NULL, MallocFunc, FreeFunc);
if (png == NULL) goto End; if (png == NULL) goto End;
png_set_error_fn(png, 0, error_function, NULL); png_set_error_fn(png, 0, error_function, NULL);
@ -265,6 +289,16 @@ int ReadPNG(const uint8_t* const data, size_t data_size,
has_alpha = !!(color_type & PNG_COLOR_MASK_ALPHA); has_alpha = !!(color_type & PNG_COLOR_MASK_ALPHA);
} }
// Apply gamma correction if needed.
{
double image_gamma = 1 / 2.2, screen_gamma = 2.2;
int srgb_intent;
if (png_get_sRGB(png, info, &srgb_intent) ||
png_get_gAMA(png, info, &image_gamma)) {
png_set_gamma(png, screen_gamma, image_gamma);
}
}
if (!keep_alpha) { if (!keep_alpha) {
png_set_strip_alpha(png); png_set_strip_alpha(png);
has_alpha = 0; has_alpha = 0;

View File

@ -117,7 +117,7 @@ static size_t ReadPAMFields(PNMInfo* const info, size_t off) {
} }
} }
if (!(info->seen_flags & TUPLE_FLAG)) { if (!(info->seen_flags & TUPLE_FLAG)) {
if (info->depth > 0 && info->depth <= 4) { if (info->depth > 0 && info->depth <= 4 && info->depth != 2) {
info->seen_flags |= TUPLE_FLAG; info->seen_flags |= TUPLE_FLAG;
info->bytes_per_px = info->depth * (info->max_value > 255 ? 2 : 1); info->bytes_per_px = info->depth * (info->max_value > 255 ? 2 : 1);
} else { } else {
@ -165,7 +165,7 @@ static size_t ReadHeader(PNMInfo* const info) {
// perform some basic numerical validation // perform some basic numerical validation
if (info->width <= 0 || info->height <= 0 || if (info->width <= 0 || info->height <= 0 ||
info->type <= 0 || info->type >= 9 || info->type <= 0 || info->type >= 9 ||
info->depth <= 0 || info->depth > 4 || info->depth <= 0 || info->depth == 2 || info->depth > 4 ||
info->bytes_per_px < info->depth || info->bytes_per_px < info->depth ||
info->max_value <= 0 || info->max_value >= 65536) { info->max_value <= 0 || info->max_value >= 65536) {
return 0; return 0;

View File

@ -121,7 +121,6 @@ static tsize_t MyRead(thandle_t opaque, void* dst, tsize_t size) {
// (we don't want to force a dependency to a libdspdec library). // (we don't want to force a dependency to a libdspdec library).
#define MFIX 24 // 24bit fixed-point arithmetic #define MFIX 24 // 24bit fixed-point arithmetic
#define HALF ((1u << MFIX) >> 1) #define HALF ((1u << MFIX) >> 1)
#define KINV_255 ((1u << MFIX) / 255u)
static uint32_t Unmult(uint8_t x, uint32_t mult) { static uint32_t Unmult(uint8_t x, uint32_t mult) {
const uint32_t v = (x * mult + HALF) >> MFIX; const uint32_t v = (x * mult + HALF) >> MFIX;
@ -132,6 +131,9 @@ static WEBP_INLINE uint32_t GetScale(uint32_t a) {
return (255u << MFIX) / a; return (255u << MFIX) / a;
} }
#undef MFIX
#undef HALF
static void MultARGBRow(uint8_t* ptr, int width) { static void MultARGBRow(uint8_t* ptr, int width) {
int x; int x;
for (x = 0; x < width; ++x, ptr += 4) { for (x = 0; x < width; ++x, ptr += 4) {

View File

@ -15,10 +15,12 @@
#include "./webpdec.h" #include "./webpdec.h"
#include <assert.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include "webp/decode.h" #include "webp/decode.h"
#include "webp/demux.h"
#include "webp/encode.h" #include "webp/encode.h"
#include "./imageio_util.h" #include "./imageio_util.h"
#include "./metadata.h" #include "./metadata.h"
@ -95,25 +97,47 @@ VP8StatusCode DecodeWebPIncremental(
fprintf(stderr, "Failed during WebPINewDecoder().\n"); fprintf(stderr, "Failed during WebPINewDecoder().\n");
return VP8_STATUS_OUT_OF_MEMORY; return VP8_STATUS_OUT_OF_MEMORY;
} else { } else {
#ifdef WEBP_EXPERIMENTAL_FEATURES
size_t size = 0;
const size_t incr = 2 + (data_size / 20);
while (size < data_size) {
size_t next_size = size + (rand() % incr);
if (next_size > data_size) next_size = data_size;
status = WebPIUpdate(idec, data, next_size);
if (status != VP8_STATUS_OK && status != VP8_STATUS_SUSPENDED) break;
size = next_size;
}
#else
status = WebPIUpdate(idec, data, data_size); status = WebPIUpdate(idec, data, data_size);
#endif
WebPIDelete(idec); WebPIDelete(idec);
} }
} }
return status; return status;
} }
// -----------------------------------------------------------------------------
// Metadata
static int ExtractMetadata(const uint8_t* const data, size_t data_size,
Metadata* const metadata) {
WebPData webp_data = { data, data_size };
WebPDemuxer* const demux = WebPDemux(&webp_data);
WebPChunkIterator chunk_iter;
uint32_t flags;
if (demux == NULL) return 0;
assert(metadata != NULL);
flags = WebPDemuxGetI(demux, WEBP_FF_FORMAT_FLAGS);
if ((flags & ICCP_FLAG) && WebPDemuxGetChunk(demux, "ICCP", 1, &chunk_iter)) {
MetadataCopy((const char*)chunk_iter.chunk.bytes, chunk_iter.chunk.size,
&metadata->iccp);
WebPDemuxReleaseChunkIterator(&chunk_iter);
}
if ((flags & EXIF_FLAG) && WebPDemuxGetChunk(demux, "EXIF", 1, &chunk_iter)) {
MetadataCopy((const char*)chunk_iter.chunk.bytes, chunk_iter.chunk.size,
&metadata->exif);
WebPDemuxReleaseChunkIterator(&chunk_iter);
}
if ((flags & XMP_FLAG) && WebPDemuxGetChunk(demux, "XMP ", 1, &chunk_iter)) {
MetadataCopy((const char*)chunk_iter.chunk.bytes, chunk_iter.chunk.size,
&metadata->xmp);
WebPDemuxReleaseChunkIterator(&chunk_iter);
}
WebPDemuxDelete(demux);
return 1;
}
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
int ReadWebP(const uint8_t* const data, size_t data_size, int ReadWebP(const uint8_t* const data, size_t data_size,
@ -127,11 +151,6 @@ int ReadWebP(const uint8_t* const data, size_t data_size,
if (data == NULL || data_size == 0 || pic == NULL) return 0; if (data == NULL || data_size == 0 || pic == NULL) return 0;
// TODO(jzern): add Exif/XMP/ICC extraction.
if (metadata != NULL) {
fprintf(stderr, "Warning: metadata extraction from WebP is unsupported.\n");
}
if (!WebPInitDecoderConfig(&config)) { if (!WebPInitDecoderConfig(&config)) {
fprintf(stderr, "Library version mismatch!\n"); fprintf(stderr, "Library version mismatch!\n");
return 0; return 0;
@ -193,7 +212,6 @@ int ReadWebP(const uint8_t* const data, size_t data_size,
status = DecodeWebP(data, data_size, &config); status = DecodeWebP(data, data_size, &config);
ok = (status == VP8_STATUS_OK); ok = (status == VP8_STATUS_OK);
if (!ok) WebPPictureFree(pic);
if (ok && !keep_alpha && pic->use_argb) { if (ok && !keep_alpha && pic->use_argb) {
// Need to wipe out the alpha value, as requested. // Need to wipe out the alpha value, as requested.
int x, y; int x, y;
@ -207,9 +225,18 @@ int ReadWebP(const uint8_t* const data, size_t data_size,
if (status != VP8_STATUS_OK) { if (status != VP8_STATUS_OK) {
PrintWebPError("input data", status); PrintWebPError("input data", status);
ok = 0;
} }
WebPFreeDecBuffer(output_buffer); WebPFreeDecBuffer(output_buffer);
if (ok && metadata != NULL) {
ok = ExtractMetadata(data, data_size, metadata);
if (!ok) {
PrintWebPError("metadata", VP8_STATUS_BITSTREAM_ERROR);
}
}
if (!ok) WebPPictureFree(pic);
return ok; return ok;
} }

View File

@ -25,6 +25,7 @@ ifeq ($(strip $(shell uname)), Darwin)
# Failure observed with: gcc 4.2.1 and 4.0.1. # Failure observed with: gcc 4.2.1 and 4.0.1.
EXTRA_FLAGS += -fno-common EXTRA_FLAGS += -fno-common
EXTRA_FLAGS += -DHAVE_GLUT_GLUT_H EXTRA_FLAGS += -DHAVE_GLUT_GLUT_H
EXTRA_FLAGS += -Wno-deprecated-declarations
EXTRA_FLAGS += -I/opt/local/include EXTRA_FLAGS += -I/opt/local/include
EXTRA_LIBS += -L/opt/local/lib EXTRA_LIBS += -L/opt/local/lib
GL_LIBS = -framework GLUT -framework OpenGL GL_LIBS = -framework GLUT -framework OpenGL
@ -63,9 +64,6 @@ endif
# 'make -f makefile.unix EXTRA_FLAGS=-m32' to that effect. # 'make -f makefile.unix EXTRA_FLAGS=-m32' to that effect.
# EXTRA_FLAGS += -m32 # 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 to enable byte swap for 16 bit colorspaces.
# EXTRA_FLAGS += -DWEBP_SWAP_16BIT_CSP=1 # EXTRA_FLAGS += -DWEBP_SWAP_16BIT_CSP=1
@ -91,12 +89,6 @@ EXTRA_FLAGS += -DWEBP_HAVE_SSE41
src/dsp/%_sse41.o: EXTRA_FLAGS += -msse4.1 src/dsp/%_sse41.o: EXTRA_FLAGS += -msse4.1
endif endif
# AVX2-specific flags:
ifeq ($(HAVE_AVX2), 1)
EXTRA_FLAGS += -DWEBP_HAVE_AVX2
src/dsp/%_avx2.o: EXTRA_FLAGS += -mavx2
endif
# NEON-specific flags: # NEON-specific flags:
# EXTRA_FLAGS += -march=armv7-a -mfloat-abi=hard -mfpu=neon -mtune=cortex-a8 # EXTRA_FLAGS += -march=armv7-a -mfloat-abi=hard -mfpu=neon -mtune=cortex-a8
# -> seems to make the overall lib slower: -fno-split-wide-types # -> seems to make the overall lib slower: -fno-split-wide-types
@ -114,7 +106,12 @@ endif
AR = ar AR = ar
ARFLAGS = r ARFLAGS = r
CPPFLAGS = -I. -Isrc/ -Wall CPPFLAGS = -I. -Isrc/ -Wall
CFLAGS = -O3 -DNDEBUG $(EXTRA_FLAGS) ifeq ($(DEBUG), 1)
CFLAGS = -g
else
CFLAGS = -O3 -DNDEBUG
endif
CFLAGS += $(EXTRA_FLAGS)
CC = gcc CC = gcc
INSTALL = install INSTALL = install
GROFF = /usr/bin/groff GROFF = /usr/bin/groff
@ -176,11 +173,13 @@ DSP_DEC_OBJS = \
src/dsp/upsampling_msa.o \ src/dsp/upsampling_msa.o \
src/dsp/upsampling_neon.o \ src/dsp/upsampling_neon.o \
src/dsp/upsampling_sse2.o \ src/dsp/upsampling_sse2.o \
src/dsp/upsampling_sse41.o \
src/dsp/yuv.o \ src/dsp/yuv.o \
src/dsp/yuv_mips32.o \ src/dsp/yuv_mips32.o \
src/dsp/yuv_mips_dsp_r2.o \ src/dsp/yuv_mips_dsp_r2.o \
src/dsp/yuv_neon.o \ src/dsp/yuv_neon.o \
src/dsp/yuv_sse2.o \ src/dsp/yuv_sse2.o \
src/dsp/yuv_sse41.o \
DSP_ENC_OBJS = \ DSP_ENC_OBJS = \
src/dsp/cost.o \ src/dsp/cost.o \
@ -188,7 +187,6 @@ DSP_ENC_OBJS = \
src/dsp/cost_mips_dsp_r2.o \ src/dsp/cost_mips_dsp_r2.o \
src/dsp/cost_sse2.o \ src/dsp/cost_sse2.o \
src/dsp/enc.o \ src/dsp/enc.o \
src/dsp/enc_avx2.o \
src/dsp/enc_mips32.o \ src/dsp/enc_mips32.o \
src/dsp/enc_mips_dsp_r2.o \ src/dsp/enc_mips_dsp_r2.o \
src/dsp/enc_msa.o \ src/dsp/enc_msa.o \
@ -212,7 +210,6 @@ ENC_OBJS = \
src/enc/backward_references_enc.o \ src/enc/backward_references_enc.o \
src/enc/config_enc.o \ src/enc/config_enc.o \
src/enc/cost_enc.o \ src/enc/cost_enc.o \
src/enc/delta_palettization_enc.o \
src/enc/filter_enc.o \ src/enc/filter_enc.o \
src/enc/frame_enc.o \ src/enc/frame_enc.o \
src/enc/histogram_enc.o \ src/enc/histogram_enc.o \
@ -310,7 +307,6 @@ HDRS = \
src/dsp/yuv.h \ src/dsp/yuv.h \
src/enc/backward_references_enc.h \ src/enc/backward_references_enc.h \
src/enc/cost_enc.h \ src/enc/cost_enc.h \
src/enc/delta_palettization_enc.h \
src/enc/histogram_enc.h \ src/enc/histogram_enc.h \
src/enc/vp8i_enc.h \ src/enc/vp8i_enc.h \
src/enc/vp8li_enc.h \ src/enc/vp8li_enc.h \
@ -389,7 +385,7 @@ src/demux/libwebpdemux.a: $(LIBWEBPDEMUX_OBJS)
$(AR) $(ARFLAGS) $@ $^ $(AR) $(ARFLAGS) $@ $^
examples/anim_diff: examples/anim_diff.o $(ANIM_UTIL_OBJS) $(GIFDEC_OBJS) examples/anim_diff: examples/anim_diff.o $(ANIM_UTIL_OBJS) $(GIFDEC_OBJS)
examples/anim_dump: examples/anim_dump.o $(ANIM_UTIL_OBJS) examples/anim_dump: examples/anim_dump.o $(ANIM_UTIL_OBJS) $(GIFDEC_OBJS)
examples/cwebp: examples/cwebp.o examples/cwebp: examples/cwebp.o
examples/dwebp: examples/dwebp.o examples/dwebp: examples/dwebp.o
examples/gif2webp: examples/gif2webp.o $(GIFDEC_OBJS) examples/gif2webp: examples/gif2webp.o $(GIFDEC_OBJS)
@ -403,7 +399,7 @@ examples/anim_diff: src/demux/libwebpdemux.a examples/libexample_util.a
examples/anim_diff: imageio/libimageio_util.a src/libwebp.a examples/anim_diff: imageio/libimageio_util.a src/libwebp.a
examples/anim_diff: EXTRA_LIBS += $(GIF_LIBS) examples/anim_diff: EXTRA_LIBS += $(GIF_LIBS)
examples/anim_diff: EXTRA_FLAGS += -DWEBP_HAVE_GIF examples/anim_diff: EXTRA_FLAGS += -DWEBP_HAVE_GIF
examples/anim_dump: examples/libanim_util.a examples/anim_dump: examples/libanim_util.a examples/libgifdec.a
examples/anim_dump: src/demux/libwebpdemux.a examples/anim_dump: src/demux/libwebpdemux.a
examples/anim_dump: examples/libexample_util.a examples/anim_dump: examples/libexample_util.a
examples/anim_dump: imageio/libimageio_util.a examples/anim_dump: imageio/libimageio_util.a
@ -412,11 +408,13 @@ examples/anim_dump: src/libwebp.a
examples/anim_dump: EXTRA_LIBS += $(GIF_LIBS) $(DWEBP_LIBS) examples/anim_dump: EXTRA_LIBS += $(GIF_LIBS) $(DWEBP_LIBS)
examples/cwebp: examples/libexample_util.a examples/cwebp: examples/libexample_util.a
examples/cwebp: imageio/libimagedec.a examples/cwebp: imageio/libimagedec.a
examples/cwebp: src/demux/libwebpdemux.a
examples/cwebp: imageio/libimageio_util.a examples/cwebp: imageio/libimageio_util.a
examples/cwebp: src/libwebp.a examples/cwebp: src/libwebp.a
examples/cwebp: EXTRA_LIBS += $(CWEBP_LIBS) examples/cwebp: EXTRA_LIBS += $(CWEBP_LIBS)
examples/dwebp: examples/libexample_util.a examples/dwebp: examples/libexample_util.a
examples/dwebp: imageio/libimagedec.a examples/dwebp: imageio/libimagedec.a
examples/dwebp: src/demux/libwebpdemux.a
examples/dwebp: imageio/libimageenc.a examples/dwebp: imageio/libimageenc.a
examples/dwebp: imageio/libimageio_util.a examples/dwebp: imageio/libimageio_util.a
examples/dwebp: src/libwebp.a examples/dwebp: src/libwebp.a
@ -433,13 +431,17 @@ examples/webpmux: examples/libexample_util.a imageio/libimageio_util.a
examples/webpmux: src/mux/libwebpmux.a src/libwebpdecoder.a examples/webpmux: src/mux/libwebpmux.a src/libwebpdecoder.a
examples/img2webp: examples/libexample_util.a imageio/libimageio_util.a examples/img2webp: examples/libexample_util.a imageio/libimageio_util.a
examples/img2webp: imageio/libimagedec.a examples/img2webp: imageio/libimagedec.a
examples/img2webp: src/demux/libwebpdemux.a
examples/img2webp: src/mux/libwebpmux.a src/libwebp.a examples/img2webp: src/mux/libwebpmux.a src/libwebp.a
examples/img2webp: EXTRA_LIBS += $(CWEBP_LIBS) examples/img2webp: EXTRA_LIBS += $(CWEBP_LIBS)
examples/webpinfo: examples/libexample_util.a imageio/libimageio_util.a examples/webpinfo: examples/libexample_util.a imageio/libimageio_util.a
examples/webpinfo: src/libwebpdecoder.a examples/webpinfo: src/libwebpdecoder.a
extras/get_disto: extras/get_disto.o extras/get_disto: extras/get_disto.o
extras/get_disto: imageio/libimagedec.a imageio/libimageio_util.a src/libwebp.a extras/get_disto: imageio/libimagedec.a
extras/get_disto: src/demux/libwebpdemux.a
extras/get_disto: imageio/libimageio_util.a
extras/get_disto: src/libwebp.a
extras/get_disto: EXTRA_LIBS += $(CWEBP_LIBS) extras/get_disto: EXTRA_LIBS += $(CWEBP_LIBS)
extras/webp_quality: extras/webp_quality.o extras/webp_quality: extras/webp_quality.o
@ -470,7 +472,7 @@ dist: all
for m in man/[cdv]webp.1 man/gif2webp.1 man/webpmux.1 \ for m in man/[cdv]webp.1 man/gif2webp.1 man/webpmux.1 \
man/img2webp.1 man/webpinfo.1; do \ man/img2webp.1 man/webpinfo.1; do \
basenam=$$(basename $$m .1); \ basenam=$$(basename $$m .1); \
$(GROFF) -t -e -man -T utf8 $$m \ $(GROFF) -t -e -man -T ascii $$m \
| $(COL) -bx >$(DESTDIR)/doc/$${basenam}.txt; \ | $(COL) -bx >$(DESTDIR)/doc/$${basenam}.txt; \
$(GROFF) -t -e -man -T html $$m \ $(GROFF) -t -e -man -T html $$m \
| $(COL) -bx >$(DESTDIR)/doc/$${basenam}.html; \ | $(COL) -bx >$(DESTDIR)/doc/$${basenam}.html; \

View File

@ -1,10 +1,13 @@
man_MANS = cwebp.1 dwebp.1 man_MANS = cwebp.1 dwebp.1
if WANT_MUX if BUILD_MUX
man_MANS += webpmux.1 man_MANS += webpmux.1
endif endif
if BUILD_GIF2WEBP if BUILD_GIF2WEBP
man_MANS += gif2webp.1 man_MANS += gif2webp.1
endif endif
if BUILD_IMG2WEBP
man_MANS += img2webp.1
endif
if BUILD_VWEBP if BUILD_VWEBP
man_MANS += vwebp.1 man_MANS += vwebp.1
endif endif

View File

@ -1,5 +1,5 @@
.\" Hey, EMACS: -*- nroff -*- .\" Hey, EMACS: -*- nroff -*-
.TH GIF2WEBP 1 "September 20, 2017" .TH GIF2WEBP 1 "January 25, 2018"
.SH NAME .SH NAME
gif2webp \- Convert a GIF image to WebP gif2webp \- Convert a GIF image to WebP
.SH SYNOPSIS .SH SYNOPSIS
@ -20,6 +20,12 @@ Specify the name of the output WebP file. If omitted, \fBgif2webp\fP will
perform conversion but only report statistics. perform conversion but only report statistics.
Using "\-" as output name will direct output to 'stdout'. Using "\-" as output name will direct output to 'stdout'.
.TP .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 \-h, \-help .B \-h, \-help
Usage information. Usage information.
.TP .TP
@ -109,6 +115,7 @@ the range of 20 to 50.
.TP .TP
.B \-mt .B \-mt
Use multi-threading for encoding, if possible. Use multi-threading for encoding, if possible.
.TP
.B \-loop_compatibility .B \-loop_compatibility
If enabled, handle the loop information in a compatible fashion for Chrome If enabled, handle the loop information in a compatible fashion for Chrome
version prior to M62 (inclusive) and Firefox. version prior to M62 (inclusive) and Firefox.
@ -136,6 +143,8 @@ gif2webp \-lossy \-m 3 picture.gif \-o picture_lossy.webp
gif2webp \-lossy \-f 50 picture.gif \-o picture.webp gif2webp \-lossy \-f 50 picture.gif \-o picture.webp
.br .br
gif2webp \-q 70 \-o picture.webp \-\- \-\-\-picture.gif gif2webp \-q 70 \-o picture.webp \-\- \-\-\-picture.gif
.br
cat picture.gif | gif2webp \-o \- \-\- \- > output.webp
.SH AUTHORS .SH AUTHORS
\fBgif2webp\fP is a part of libwebp and was written by the WebP team. \fBgif2webp\fP is a part of libwebp and was written by the WebP team.

View File

@ -1,11 +1,13 @@
.\" Hey, EMACS: -*- nroff -*- .\" Hey, EMACS: -*- nroff -*-
.TH IMG2WEBP 1 "January 23, 2017" .TH IMG2WEBP 1 "April 3, 2018"
.SH NAME .SH NAME
img2webp \- create animated WebP file from a sequence of input images. img2webp \- create animated WebP file from a sequence of input images.
.SH SYNOPSIS .SH SYNOPSIS
.B img2webp .B img2webp
[file_level_options] [files] [per_frame_options...] [file_level_options] [files] [per_frame_options...]
.br .br
.B img2webp argument_file_name
.br
.SH DESCRIPTION .SH DESCRIPTION
This manual page documents the This manual page documents the
.B img2webp .B img2webp
@ -13,6 +15,9 @@ command.
.PP .PP
\fBimg2webp\fP compresses a sequence of images using the animated WebP format. \fBimg2webp\fP compresses a sequence of images using the animated WebP format.
Input images can either be PNG, JPEG, TIFF or WebP. Input images can either be PNG, JPEG, TIFF or WebP.
If a single file name (not starting with the character '\-') is supplied as
the argument, the command line argument are actually tokenized from this file.
This allows for easy scripting or using large number of arguments.
.SH FILE-LEVEL OPTIONS .SH FILE-LEVEL OPTIONS
The file-level options are applied at the beginning of the compression process, The file-level options are applied at the beginning of the compression process,
before the input frames are read. before the input frames are read.
@ -40,14 +45,17 @@ lossy or lossless compression for each frame heuristically. This global
option disables the local option \fB-lossy\fP and \fB-lossless\fP . option disables the local option \fB-lossy\fP and \fB-lossless\fP .
.TP .TP
.BI \-loop " int .BI \-loop " int
Specifies the number of times the animation should loop. Using '0' means Specifies the number of times the animation should loop. Using '0'
'loop indefinitely'. means 'loop indefinitely'.
.TP .TP
.BI \-v .BI \-v
Be more verbose. Be more verbose.
.TP .TP
.B \-h, \-help .B \-h, \-help
A short usage summary. A short usage summary.
.TP
.B \-version
Print the version numbers of the relevant libraries used.
.SH PER-FRAME OPTIONS .SH PER-FRAME OPTIONS
The per-frame options are applied for the images following as arguments in the The per-frame options are applied for the images following as arguments in the

View File

@ -1,5 +1,5 @@
.\" Hey, EMACS: -*- nroff -*- .\" Hey, EMACS: -*- nroff -*-
.TH VWEBP 1 "November 25, 2016" .TH VWEBP 1 "July 20, 2018"
.SH NAME .SH NAME
vwebp \- decompress a WebP file and display it in a window vwebp \- decompress a WebP file and display it in a window
.SH SYNOPSIS .SH SYNOPSIS
@ -38,6 +38,10 @@ It helps by smoothing gradients and avoiding banding artifacts. Default: 50.
By default, quantized transparency planes are dithered during decompression, By default, quantized transparency planes are dithered during decompression,
to smooth the gradients. This flag will prevent this dithering. to smooth the gradients. This flag will prevent this dithering.
.TP .TP
.B \-usebgcolor
Fill transparent areas with the bitstream's own background color instead of
checkerboard only. Default is white for non-animated images.
.TP
.B \-mt .B \-mt
Use multi-threading for decoding, if possible. Use multi-threading for decoding, if possible.
.TP .TP
@ -56,6 +60,9 @@ the data will be read from \fIstdin\fP instead of a file.
.B 'c' .B 'c'
Toggle use of color profile. Toggle use of color profile.
.TP .TP
.B 'b'
Toggle display of background color.
.TP
.B 'i' .B 'i'
Overlay file information. Overlay file information.
.TP .TP

View File

@ -1,5 +1,5 @@
.\" Hey, EMACS: -*- nroff -*- .\" Hey, EMACS: -*- nroff -*-
.TH WEBPMUX 1 "November 10, 2016" .TH WEBPMUX 1 "April 23, 2018"
.SH NAME .SH NAME
webpmux \- create animated WebP files from non\-animated WebP images, extract webpmux \- create animated WebP files from non\-animated WebP images, extract
frames from animated WebP images, and manage XMP/EXIF metadata and ICC profile. frames from animated WebP images, and manage XMP/EXIF metadata and ICC profile.
@ -48,6 +48,8 @@ frames from animated WebP images, and manage XMP/EXIF metadata and ICC profile.
.B webpmux [\-h|\-help] .B webpmux [\-h|\-help]
.br .br
.B webpmux \-version .B webpmux \-version
.br
.B webpmux argument_file_name
.SH DESCRIPTION .SH DESCRIPTION
This manual page documents the This manual page documents the
.B webpmux .B webpmux
@ -55,6 +57,9 @@ command.
.PP .PP
\fBwebpmux\fP can be used to create/extract from animated WebP files, as well as \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. to add/extract/strip XMP/EXIF metadata and ICC profile.
If a single file name (not starting with the character '\-') is supplied as
the argument, the command line arguments are actually tokenized from this file.
This allows for easy scripting or using large number of arguments.
.SH OPTIONS .SH OPTIONS
.SS GET_OPTIONS (\-get): .SS GET_OPTIONS (\-get):
.TP .TP

View File

@ -1,10 +1,10 @@
# The mux and demux libraries depend on libwebp, thus the '.' to force # The mux and demux libraries depend on libwebp, thus the '.' to force
# the build order so it's available to them. # the build order so it's available to them.
SUBDIRS = dec enc dsp utils . SUBDIRS = dec enc dsp utils .
if WANT_MUX if BUILD_MUX
SUBDIRS += mux SUBDIRS += mux
endif endif
if WANT_DEMUX if BUILD_DEMUX
SUBDIRS += demux SUBDIRS += demux
endif endif
@ -36,7 +36,7 @@ libwebp_la_LIBADD += utils/libwebputils.la
# other than the ones listed on the command line, i.e., after linking, it will # other than the ones listed on the command line, i.e., after linking, it will
# not have unresolved symbols. Some platforms (Windows among them) require all # not have unresolved symbols. Some platforms (Windows among them) require all
# symbols in shared libraries to be resolved at library creation. # symbols in shared libraries to be resolved at library creation.
libwebp_la_LDFLAGS = -no-undefined -version-info 7:1:0 libwebp_la_LDFLAGS = -no-undefined -version-info 7:3:0
libwebpincludedir = $(includedir)/webp libwebpincludedir = $(includedir)/webp
pkgconfig_DATA = libwebp.pc pkgconfig_DATA = libwebp.pc
@ -48,7 +48,7 @@ if BUILD_LIBWEBPDECODER
libwebpdecoder_la_LIBADD += dsp/libwebpdspdecode.la libwebpdecoder_la_LIBADD += dsp/libwebpdspdecode.la
libwebpdecoder_la_LIBADD += utils/libwebputilsdecode.la libwebpdecoder_la_LIBADD += utils/libwebputilsdecode.la
libwebpdecoder_la_LDFLAGS = -no-undefined -version-info 3:1:0 libwebpdecoder_la_LDFLAGS = -no-undefined -version-info 3:3:0
pkgconfig_DATA += libwebpdecoder.pc pkgconfig_DATA += libwebpdecoder.pc
endif endif

View File

@ -25,5 +25,5 @@ libwebpdecodeinclude_HEADERS += ../webp/types.h
noinst_HEADERS = noinst_HEADERS =
noinst_HEADERS += ../webp/format_constants.h noinst_HEADERS += ../webp/format_constants.h
libwebpdecode_la_CPPFLAGS = $(AM_CPPFLAGS) $(USE_EXPERIMENTAL_CODE) libwebpdecode_la_CPPFLAGS = $(AM_CPPFLAGS)
libwebpdecodeincludedir = $(includedir)/webp libwebpdecodeincludedir = $(includedir)/webp

View File

@ -51,4 +51,4 @@ void WebPDeallocateAlphaMemory(VP8Decoder* const dec);
} // extern "C" } // extern "C"
#endif #endif
#endif /* WEBP_DEC_ALPHAI_DEC_H_ */ #endif // WEBP_DEC_ALPHAI_DEC_H_

View File

@ -51,4 +51,4 @@ enum { MB_FEATURE_TREE_PROBS = 3,
NUM_PROBAS = 11 NUM_PROBAS = 11
}; };
#endif // WEBP_DEC_COMMON_DEC_H_ #endif // WEBP_DEC_COMMON_DEC_H_

View File

@ -338,7 +338,6 @@ void VP8InitDithering(const WebPDecoderOptions* const options,
for (s = 0; s < NUM_MB_SEGMENTS; ++s) { for (s = 0; s < NUM_MB_SEGMENTS; ++s) {
VP8QuantMatrix* const dqm = &dec->dqm_[s]; VP8QuantMatrix* const dqm = &dec->dqm_[s];
if (dqm->uv_quant_ < DITHER_AMP_TAB_SIZE) { if (dqm->uv_quant_ < DITHER_AMP_TAB_SIZE) {
// TODO(skal): should we specially dither more for uv_quant_ < 0?
const int idx = (dqm->uv_quant_ < 0) ? 0 : dqm->uv_quant_; const int idx = (dqm->uv_quant_ < 0) ? 0 : dqm->uv_quant_;
dqm->dither_ = (f * kQuantToDitherAmp[idx]) >> 3; dqm->dither_ = (f * kQuantToDitherAmp[idx]) >> 3;
} }
@ -400,7 +399,9 @@ static void DitherRow(VP8Decoder* const dec) {
#define MACROBLOCK_VPOS(mb_y) ((mb_y) * 16) // vertical position of a MB #define MACROBLOCK_VPOS(mb_y) ((mb_y) * 16) // vertical position of a MB
// Finalize and transmit a complete row. Return false in case of user-abort. // Finalize and transmit a complete row. Return false in case of user-abort.
static int FinishRow(VP8Decoder* const dec, VP8Io* const io) { static int FinishRow(void* arg1, void* arg2) {
VP8Decoder* const dec = (VP8Decoder*)arg1;
VP8Io* const io = (VP8Io*)arg2;
int ok = 1; int ok = 1;
const VP8ThreadContext* const ctx = &dec->thread_ctx_; const VP8ThreadContext* const ctx = &dec->thread_ctx_;
const int cache_id = ctx->id_; const int cache_id = ctx->id_;
@ -448,10 +449,9 @@ static int FinishRow(VP8Decoder* const dec, VP8Io* const io) {
if (y_end > io->crop_bottom) { if (y_end > io->crop_bottom) {
y_end = io->crop_bottom; // make sure we don't overflow on last row. y_end = io->crop_bottom; // make sure we don't overflow on last row.
} }
// If dec->alpha_data_ is not NULL, we have some alpha plane present.
io->a = NULL; io->a = NULL;
if (dec->alpha_data_ != NULL && y_start < y_end) { if (dec->alpha_data_ != NULL && y_start < y_end) {
// TODO(skal): testing presence of alpha with dec->alpha_data_ is not a
// good idea.
io->a = VP8DecompressAlphaRows(dec, io, y_start, y_end - y_start); io->a = VP8DecompressAlphaRows(dec, io, y_start, y_end - y_start);
if (io->a == NULL) { if (io->a == NULL) {
return VP8SetError(dec, VP8_STATUS_BITSTREAM_ERROR, return VP8SetError(dec, VP8_STATUS_BITSTREAM_ERROR,
@ -558,7 +558,6 @@ VP8StatusCode VP8EnterCritical(VP8Decoder* const dec, VP8Io* const io) {
if (io->bypass_filtering) { if (io->bypass_filtering) {
dec->filter_type_ = 0; dec->filter_type_ = 0;
} }
// TODO(skal): filter type / strength / sharpness forcing
// Define the area where we can skip in-loop filtering, in case of cropping. // Define the area where we can skip in-loop filtering, in case of cropping.
// //
@ -569,8 +568,6 @@ VP8StatusCode VP8EnterCritical(VP8Decoder* const dec, VP8Io* const io) {
// Means: there's a dependency chain that goes all the way up to the // Means: there's a dependency chain that goes all the way up to the
// top-left corner of the picture (MB #0). We must filter all the previous // top-left corner of the picture (MB #0). We must filter all the previous
// macroblocks. // macroblocks.
// TODO(skal): add an 'approximate_decoding' option, that won't produce
// a 1:1 bit-exactness for complex filtering?
{ {
const int extra_pixels = kFilterExtraRows[dec->filter_type_]; const int extra_pixels = kFilterExtraRows[dec->filter_type_];
if (dec->filter_type_ == 2) { if (dec->filter_type_ == 2) {
@ -651,7 +648,7 @@ static int InitThreadContext(VP8Decoder* const dec) {
} }
worker->data1 = dec; worker->data1 = dec;
worker->data2 = (void*)&dec->thread_ctx_.io_; worker->data2 = (void*)&dec->thread_ctx_.io_;
worker->hook = (WebPWorkerHook)FinishRow; worker->hook = FinishRow;
dec->num_caches_ = dec->num_caches_ =
(dec->filter_type_ > 0) ? MT_CACHE_LINES : MT_CACHE_LINES - 1; (dec->filter_type_ > 0) ? MT_CACHE_LINES : MT_CACHE_LINES - 1;
} else { } else {
@ -671,15 +668,9 @@ int VP8GetThreadMethod(const WebPDecoderOptions* const options,
(void)height; (void)height;
assert(headers == NULL || !headers->is_lossless); assert(headers == NULL || !headers->is_lossless);
#if defined(WEBP_USE_THREAD) #if defined(WEBP_USE_THREAD)
if (width < MIN_WIDTH_FOR_THREADS) return 0; if (width >= MIN_WIDTH_FOR_THREADS) return 2;
// TODO(skal): tune the heuristic further
#if 0
if (height < 2 * width) return 2;
#endif #endif
return 2;
#else // !WEBP_USE_THREAD
return 0; return 0;
#endif
} }
#undef MT_CACHE_LINES #undef MT_CACHE_LINES

View File

@ -140,10 +140,9 @@ static void DoRemap(WebPIDecoder* const idec, ptrdiff_t offset) {
if (NeedCompressedAlpha(idec)) { if (NeedCompressedAlpha(idec)) {
ALPHDecoder* const alph_dec = dec->alph_dec_; ALPHDecoder* const alph_dec = dec->alph_dec_;
dec->alpha_data_ += offset; dec->alpha_data_ += offset;
if (alph_dec != NULL) { if (alph_dec != NULL && alph_dec->vp8l_dec_ != NULL) {
if (alph_dec->method_ == ALPHA_LOSSLESS_COMPRESSION) { if (alph_dec->method_ == ALPHA_LOSSLESS_COMPRESSION) {
VP8LDecoder* const alph_vp8l_dec = alph_dec->vp8l_dec_; VP8LDecoder* const alph_vp8l_dec = alph_dec->vp8l_dec_;
assert(alph_vp8l_dec != NULL);
assert(dec->alpha_data_size_ >= ALPHA_HEADER_LEN); assert(dec->alpha_data_size_ >= ALPHA_HEADER_LEN);
VP8LBitReaderSetBuffer(&alph_vp8l_dec->br_, VP8LBitReaderSetBuffer(&alph_vp8l_dec->br_,
dec->alpha_data_ + ALPHA_HEADER_LEN, dec->alpha_data_ + ALPHA_HEADER_LEN,
@ -474,6 +473,12 @@ static VP8StatusCode DecodeRemaining(WebPIDecoder* const idec) {
MemDataSize(&idec->mem_) > MAX_MB_SIZE) { MemDataSize(&idec->mem_) > MAX_MB_SIZE) {
return IDecError(idec, VP8_STATUS_BITSTREAM_ERROR); return IDecError(idec, VP8_STATUS_BITSTREAM_ERROR);
} }
// Synchronize the threads.
if (dec->mt_method_ > 0) {
if (!WebPGetWorkerInterface()->Sync(&dec->worker_)) {
return IDecError(idec, VP8_STATUS_BITSTREAM_ERROR);
}
}
RestoreContext(&context, dec, token_br); RestoreContext(&context, dec, token_br);
return VP8_STATUS_SUSPENDED; return VP8_STATUS_SUSPENDED;
} }

View File

@ -491,7 +491,7 @@ static int GetCoeffsAlt(VP8BitReader* const br,
return 16; return 16;
} }
WEBP_TSAN_IGNORE_FUNCTION static void InitGetCoeffs(void) { static WEBP_TSAN_IGNORE_FUNCTION void InitGetCoeffs(void) {
if (GetCoeffs == NULL) { if (GetCoeffs == NULL) {
if (VP8GetCPUInfo != NULL && VP8GetCPUInfo(kSlowSSSE3)) { if (VP8GetCPUInfo != NULL && VP8GetCPUInfo(kSlowSSSE3)) {
GetCoeffs = GetCoeffsAlt; GetCoeffs = GetCoeffsAlt;

View File

@ -182,4 +182,4 @@ WEBP_EXTERN int VP8LGetInfo(
} // extern "C" } // extern "C"
#endif #endif
#endif /* WEBP_DEC_VP8_DEC_H_ */ #endif // WEBP_DEC_VP8_DEC_H_

View File

@ -30,8 +30,8 @@ extern "C" {
// Various defines and enums // Various defines and enums
// version numbers // version numbers
#define DEC_MAJ_VERSION 0 #define DEC_MAJ_VERSION 1
#define DEC_MIN_VERSION 6 #define DEC_MIN_VERSION 0
#define DEC_REV_VERSION 1 #define DEC_REV_VERSION 1
// YUV-cache parameters. Cache is 32-bytes wide (= one cacheline). // YUV-cache parameters. Cache is 32-bytes wide (= one cacheline).
@ -316,4 +316,4 @@ const uint8_t* VP8DecompressAlphaRows(VP8Decoder* const dec,
} // extern "C" } // extern "C"
#endif #endif
#endif /* WEBP_DEC_VP8I_DEC_H_ */ #endif // WEBP_DEC_VP8I_DEC_H_

View File

@ -253,11 +253,11 @@ static int ReadHuffmanCodeLengths(
int symbol; int symbol;
int max_symbol; int max_symbol;
int prev_code_len = DEFAULT_CODE_LENGTH; int prev_code_len = DEFAULT_CODE_LENGTH;
HuffmanTables tables; HuffmanCode table[1 << LENGTHS_TABLE_BITS];
if (!VP8LHuffmanTablesAllocate(1 << LENGTHS_TABLE_BITS, &tables) || if (!VP8LBuildHuffmanTable(table, LENGTHS_TABLE_BITS,
!VP8LBuildHuffmanTable(&tables, LENGTHS_TABLE_BITS, code_length_code_lengths,
code_length_code_lengths, NUM_CODE_LENGTH_CODES)) { NUM_CODE_LENGTH_CODES)) {
goto End; goto End;
} }
@ -277,7 +277,7 @@ static int ReadHuffmanCodeLengths(
int code_len; int code_len;
if (max_symbol-- == 0) break; if (max_symbol-- == 0) break;
VP8LFillBitWindow(br); VP8LFillBitWindow(br);
p = &tables.curr_segment->start[VP8LPrefetchBits(br) & LENGTHS_TABLE_MASK]; p = &table[VP8LPrefetchBits(br) & LENGTHS_TABLE_MASK];
VP8LSetBitPos(br, br->bit_pos_ + p->bits); VP8LSetBitPos(br, br->bit_pos_ + p->bits);
code_len = p->value; code_len = p->value;
if (code_len < kCodeLengthLiterals) { if (code_len < kCodeLengthLiterals) {
@ -300,7 +300,6 @@ static int ReadHuffmanCodeLengths(
ok = 1; ok = 1;
End: End:
VP8LHuffmanTablesDeallocate(&tables);
if (!ok) dec->status_ = VP8_STATUS_BITSTREAM_ERROR; if (!ok) dec->status_ = VP8_STATUS_BITSTREAM_ERROR;
return ok; return ok;
} }
@ -308,8 +307,7 @@ static int ReadHuffmanCodeLengths(
// 'code_lengths' is pre-allocated temporary buffer, used for creating Huffman // 'code_lengths' is pre-allocated temporary buffer, used for creating Huffman
// tree. // tree.
static int ReadHuffmanCode(int alphabet_size, VP8LDecoder* const dec, static int ReadHuffmanCode(int alphabet_size, VP8LDecoder* const dec,
int* const code_lengths, int* const code_lengths, HuffmanCode* const table) {
HuffmanTables* const table) {
int ok = 0; int ok = 0;
int size = 0; int size = 0;
VP8LBitReader* const br = &dec->br_; VP8LBitReader* const br = &dec->br_;
@ -364,7 +362,12 @@ static int ReadHuffmanCodes(VP8LDecoder* const dec, int xsize, int ysize,
VP8LMetadata* const hdr = &dec->hdr_; VP8LMetadata* const hdr = &dec->hdr_;
uint32_t* huffman_image = NULL; uint32_t* huffman_image = NULL;
HTreeGroup* htree_groups = NULL; HTreeGroup* htree_groups = NULL;
HuffmanTables* huffman_tables = &hdr->huffman_tables_; // When reading htrees, some might be unused, as the format allows it.
// We will still read them but put them in this htree_group_bogus.
HTreeGroup htree_group_bogus;
HuffmanCode* huffman_tables = NULL;
HuffmanCode* huffman_tables_bogus = NULL;
HuffmanCode* next = NULL;
int num_htree_groups = 1; int num_htree_groups = 1;
int num_htree_groups_max = 1; int num_htree_groups_max = 1;
int max_alphabet_size = 0; int max_alphabet_size = 0;
@ -373,10 +376,6 @@ static int ReadHuffmanCodes(VP8LDecoder* const dec, int xsize, int ysize,
int* mapping = NULL; int* mapping = NULL;
int ok = 0; int ok = 0;
// Check the table has been 0 initialized (through InitMetadata).
assert(huffman_tables->root.start == NULL);
assert(huffman_tables->curr_segment == NULL);
if (allow_recursion && VP8LReadBits(br, 1)) { if (allow_recursion && VP8LReadBits(br, 1)) {
// use meta Huffman codes. // use meta Huffman codes.
const int huffman_precision = VP8LReadBits(br, 3) + 2; const int huffman_precision = VP8LReadBits(br, 3) + 2;
@ -419,6 +418,12 @@ static int ReadHuffmanCodes(VP8LDecoder* const dec, int xsize, int ysize,
if (*mapped_group == -1) *mapped_group = num_htree_groups++; if (*mapped_group == -1) *mapped_group = num_htree_groups++;
huffman_image[i] = *mapped_group; huffman_image[i] = *mapped_group;
} }
huffman_tables_bogus = (HuffmanCode*)WebPSafeMalloc(
table_size, sizeof(*huffman_tables_bogus));
if (huffman_tables_bogus == NULL) {
dec->status_ = VP8_STATUS_OUT_OF_MEMORY;
goto Error;
}
} else { } else {
num_htree_groups = num_htree_groups_max; num_htree_groups = num_htree_groups_max;
} }
@ -437,82 +442,74 @@ static int ReadHuffmanCodes(VP8LDecoder* const dec, int xsize, int ysize,
} }
} }
htree_groups = VP8LHtreeGroupsNew(num_htree_groups);
code_lengths = (int*)WebPSafeCalloc((uint64_t)max_alphabet_size, code_lengths = (int*)WebPSafeCalloc((uint64_t)max_alphabet_size,
sizeof(*code_lengths)); sizeof(*code_lengths));
huffman_tables = (HuffmanCode*)WebPSafeMalloc(num_htree_groups * table_size,
sizeof(*huffman_tables));
htree_groups = VP8LHtreeGroupsNew(num_htree_groups);
if (htree_groups == NULL || code_lengths == NULL || if (htree_groups == NULL || code_lengths == NULL || huffman_tables == NULL) {
!VP8LHuffmanTablesAllocate(num_htree_groups * table_size,
huffman_tables)) {
dec->status_ = VP8_STATUS_OUT_OF_MEMORY; dec->status_ = VP8_STATUS_OUT_OF_MEMORY;
goto Error; goto Error;
} }
next = huffman_tables;
for (i = 0; i < num_htree_groups_max; ++i) { for (i = 0; i < num_htree_groups_max; ++i) {
// If the index "i" is unused in the Huffman image, just make sure the // If the index "i" is unused in the Huffman image, read the coefficients
// coefficients are valid but do not store them. // but store them to a bogus htree_group.
if (mapping != NULL && mapping[i] == -1) { const int is_bogus = (mapping != NULL && mapping[i] == -1);
for (j = 0; j < HUFFMAN_CODES_PER_META_CODE; ++j) { HTreeGroup* const htree_group =
int alphabet_size = kAlphabetSize[j]; is_bogus ? &htree_group_bogus :
if (j == 0 && color_cache_bits > 0) { &htree_groups[(mapping == NULL) ? i : mapping[i]];
alphabet_size += (1 << color_cache_bits); HuffmanCode** const htrees = htree_group->htrees;
} HuffmanCode* huffman_tables_i = is_bogus ? huffman_tables_bogus : next;
// Passing in NULL so that nothing gets filled. int size;
if (!ReadHuffmanCode(alphabet_size, dec, code_lengths, NULL)) { int total_size = 0;
goto Error; int is_trivial_literal = 1;
} int max_bits = 0;
for (j = 0; j < HUFFMAN_CODES_PER_META_CODE; ++j) {
int alphabet_size = kAlphabetSize[j];
htrees[j] = huffman_tables_i;
if (j == 0 && color_cache_bits > 0) {
alphabet_size += 1 << color_cache_bits;
} }
} else { size =
HTreeGroup* const htree_group = ReadHuffmanCode(alphabet_size, dec, code_lengths, huffman_tables_i);
&htree_groups[(mapping == NULL) ? i : mapping[i]]; if (size == 0) {
HuffmanCode** const htrees = htree_group->htrees; goto Error;
int size; }
int total_size = 0; if (is_trivial_literal && kLiteralMap[j] == 1) {
int is_trivial_literal = 1; is_trivial_literal = (huffman_tables_i->bits == 0);
int max_bits = 0; }
for (j = 0; j < HUFFMAN_CODES_PER_META_CODE; ++j) { total_size += huffman_tables_i->bits;
int alphabet_size = kAlphabetSize[j]; huffman_tables_i += size;
if (j == 0 && color_cache_bits > 0) { if (j <= ALPHA) {
alphabet_size += (1 << color_cache_bits); int local_max_bits = code_lengths[0];
} int k;
size = for (k = 1; k < alphabet_size; ++k) {
ReadHuffmanCode(alphabet_size, dec, code_lengths, huffman_tables); if (code_lengths[k] > local_max_bits) {
htrees[j] = huffman_tables->curr_segment->curr_table; local_max_bits = code_lengths[k];
if (size == 0) {
goto Error;
}
if (is_trivial_literal && kLiteralMap[j] == 1) {
is_trivial_literal = (htrees[j]->bits == 0);
}
total_size += htrees[j]->bits;
huffman_tables->curr_segment->curr_table += size;
if (j <= ALPHA) {
int local_max_bits = code_lengths[0];
int k;
for (k = 1; k < alphabet_size; ++k) {
if (code_lengths[k] > local_max_bits) {
local_max_bits = code_lengths[k];
}
} }
max_bits += local_max_bits;
} }
max_bits += local_max_bits;
} }
htree_group->is_trivial_literal = is_trivial_literal;
htree_group->is_trivial_code = 0;
if (is_trivial_literal) {
const int red = htrees[RED][0].value;
const int blue = htrees[BLUE][0].value;
const int alpha = htrees[ALPHA][0].value;
htree_group->literal_arb = ((uint32_t)alpha << 24) | (red << 16) | blue;
if (total_size == 0 && htrees[GREEN][0].value < NUM_LITERAL_CODES) {
htree_group->is_trivial_code = 1;
htree_group->literal_arb |= htrees[GREEN][0].value << 8;
}
}
htree_group->use_packed_table =
!htree_group->is_trivial_code && (max_bits < HUFFMAN_PACKED_BITS);
if (htree_group->use_packed_table) BuildPackedTable(htree_group);
} }
if (!is_bogus) next = huffman_tables_i;
htree_group->is_trivial_literal = is_trivial_literal;
htree_group->is_trivial_code = 0;
if (is_trivial_literal) {
const int red = htrees[RED][0].value;
const int blue = htrees[BLUE][0].value;
const int alpha = htrees[ALPHA][0].value;
htree_group->literal_arb = ((uint32_t)alpha << 24) | (red << 16) | blue;
if (total_size == 0 && htrees[GREEN][0].value < NUM_LITERAL_CODES) {
htree_group->is_trivial_code = 1;
htree_group->literal_arb |= htrees[GREEN][0].value << 8;
}
}
htree_group->use_packed_table =
!htree_group->is_trivial_code && (max_bits < HUFFMAN_PACKED_BITS);
if (htree_group->use_packed_table) BuildPackedTable(htree_group);
} }
ok = 1; ok = 1;
@ -520,13 +517,15 @@ static int ReadHuffmanCodes(VP8LDecoder* const dec, int xsize, int ysize,
hdr->huffman_image_ = huffman_image; hdr->huffman_image_ = huffman_image;
hdr->num_htree_groups_ = num_htree_groups; hdr->num_htree_groups_ = num_htree_groups;
hdr->htree_groups_ = htree_groups; hdr->htree_groups_ = htree_groups;
hdr->huffman_tables_ = huffman_tables;
Error: Error:
WebPSafeFree(code_lengths); WebPSafeFree(code_lengths);
WebPSafeFree(huffman_tables_bogus);
WebPSafeFree(mapping); WebPSafeFree(mapping);
if (!ok) { if (!ok) {
WebPSafeFree(huffman_image); WebPSafeFree(huffman_image);
VP8LHuffmanTablesDeallocate(huffman_tables); WebPSafeFree(huffman_tables);
VP8LHtreeGroupsFree(htree_groups); VP8LHtreeGroupsFree(htree_groups);
} }
return ok; return ok;
@ -1237,20 +1236,9 @@ static int DecodeImageData(VP8LDecoder* const dec, uint32_t* const data,
} }
br->eos_ = VP8LIsEndOfStream(br); br->eos_ = VP8LIsEndOfStream(br);
// In incremental decoding: if (dec->incremental_ && br->eos_ && src < src_end) {
// br->eos_ && src < src_last: if 'br' reached the end of the buffer and
// 'src_last' has not been reached yet, there is not enough data. 'dec' has to
// be reset until there is more data.
// !br->eos_ && src < src_last: this cannot happen as either the buffer is
// fully read, either enough has been read to reach 'src_last'.
// src >= src_last: 'src_last' is reached, all is fine. 'src' can actually go
// beyond 'src_last' in case the image is cropped and an LZ77 goes further.
// The buffer might have been enough or there is some left. 'br->eos_' does
// not matter.
assert(!dec->incremental_ || (br->eos_ && src < src_last) || src >= src_last);
if (dec->incremental_ && br->eos_ && src < src_last) {
RestoreState(dec); RestoreState(dec);
} else if ((dec->incremental_ && src >= src_last) || !br->eos_) { } else if (!br->eos_) {
// Process the remaining rows corresponding to last row-block. // Process the remaining rows corresponding to last row-block.
if (process_func != NULL) { if (process_func != NULL) {
process_func(dec, row > last_row ? last_row : row); process_func(dec, row > last_row ? last_row : row);
@ -1369,7 +1357,7 @@ static void ClearMetadata(VP8LMetadata* const hdr) {
assert(hdr != NULL); assert(hdr != NULL);
WebPSafeFree(hdr->huffman_image_); WebPSafeFree(hdr->huffman_image_);
VP8LHuffmanTablesDeallocate(&hdr->huffman_tables_); WebPSafeFree(hdr->huffman_tables_);
VP8LHtreeGroupsFree(hdr->htree_groups_); VP8LHtreeGroupsFree(hdr->htree_groups_);
VP8LColorCacheClear(&hdr->color_cache_); VP8LColorCacheClear(&hdr->color_cache_);
VP8LColorCacheClear(&hdr->saved_color_cache_); VP8LColorCacheClear(&hdr->saved_color_cache_);
@ -1588,7 +1576,6 @@ int VP8LDecodeAlphaHeader(ALPHDecoder* const alph_dec,
if (dec == NULL) return 0; if (dec == NULL) return 0;
assert(alph_dec != NULL); assert(alph_dec != NULL);
alph_dec->vp8l_dec_ = dec;
dec->width_ = alph_dec->width_; dec->width_ = alph_dec->width_;
dec->height_ = alph_dec->height_; dec->height_ = alph_dec->height_;
@ -1620,11 +1607,12 @@ int VP8LDecodeAlphaHeader(ALPHDecoder* const alph_dec,
if (!ok) goto Err; if (!ok) goto Err;
// Only set here, once we are sure it is valid (to avoid thread races).
alph_dec->vp8l_dec_ = dec;
return 1; return 1;
Err: Err:
VP8LDelete(alph_dec->vp8l_dec_); VP8LDelete(dec);
alph_dec->vp8l_dec_ = NULL;
return 0; return 0;
} }
@ -1685,7 +1673,7 @@ int VP8LDecodeImage(VP8LDecoder* const dec) {
// Sanity checks. // Sanity checks.
if (dec == NULL) return 0; if (dec == NULL) return 0;
assert(dec->hdr_.huffman_tables_.root.start != NULL); assert(dec->hdr_.huffman_tables_ != NULL);
assert(dec->hdr_.htree_groups_ != NULL); assert(dec->hdr_.htree_groups_ != NULL);
assert(dec->hdr_.num_htree_groups_ > 0); assert(dec->hdr_.num_htree_groups_ > 0);
@ -1708,17 +1696,17 @@ int VP8LDecodeImage(VP8LDecoder* const dec) {
#if !defined(WEBP_REDUCE_SIZE) #if !defined(WEBP_REDUCE_SIZE)
if (io->use_scaling && !AllocateAndInitRescaler(dec, io)) goto Err; if (io->use_scaling && !AllocateAndInitRescaler(dec, io)) goto Err;
if (io->use_scaling || WebPIsPremultipliedMode(dec->output_->colorspace)) {
// need the alpha-multiply functions for premultiplied output or rescaling
WebPInitAlphaProcessing();
}
#else #else
if (io->use_scaling) { if (io->use_scaling) {
dec->status_ = VP8_STATUS_INVALID_PARAM; dec->status_ = VP8_STATUS_INVALID_PARAM;
goto Err; goto Err;
} }
#endif #endif
if (io->use_scaling || WebPIsPremultipliedMode(dec->output_->colorspace)) {
// need the alpha-multiply functions for premultiplied output or rescaling
WebPInitAlphaProcessing();
}
if (!WebPIsRGBMode(dec->output_->colorspace)) { if (!WebPIsRGBMode(dec->output_->colorspace)) {
WebPInitConvertARGBToYUV(); WebPInitConvertARGBToYUV();
if (dec->output_->u.YUVA.a != NULL) WebPInitAlphaProcessing(); if (dec->output_->u.YUVA.a != NULL) WebPInitAlphaProcessing();

View File

@ -51,7 +51,7 @@ typedef struct {
uint32_t *huffman_image_; uint32_t *huffman_image_;
int num_htree_groups_; int num_htree_groups_;
HTreeGroup *htree_groups_; HTreeGroup *htree_groups_;
HuffmanTables huffman_tables_; HuffmanCode *huffman_tables_;
} VP8LMetadata; } VP8LMetadata;
typedef struct VP8LDecoder VP8LDecoder; typedef struct VP8LDecoder VP8LDecoder;
@ -132,4 +132,4 @@ void VP8LDelete(VP8LDecoder* const dec);
} // extern "C" } // extern "C"
#endif #endif
#endif /* WEBP_DEC_VP8LI_DEC_H_ */ #endif // WEBP_DEC_VP8LI_DEC_H_

View File

@ -130,4 +130,4 @@ int WebPAvoidSlowMemory(const WebPDecBuffer* const output,
} // extern "C" } // extern "C"
#endif #endif
#endif /* WEBP_DEC_WEBPI_DEC_H_ */ #endif // WEBP_DEC_WEBPI_DEC_H_

View File

@ -5,11 +5,14 @@ libwebpdemux_la_SOURCES =
libwebpdemux_la_SOURCES += anim_decode.c demux.c libwebpdemux_la_SOURCES += anim_decode.c demux.c
libwebpdemuxinclude_HEADERS = libwebpdemuxinclude_HEADERS =
libwebpdemuxinclude_HEADERS += ../webp/decode.h
libwebpdemuxinclude_HEADERS += ../webp/demux.h libwebpdemuxinclude_HEADERS += ../webp/demux.h
libwebpdemuxinclude_HEADERS += ../webp/mux_types.h libwebpdemuxinclude_HEADERS += ../webp/mux_types.h
libwebpdemuxinclude_HEADERS += ../webp/types.h libwebpdemuxinclude_HEADERS += ../webp/types.h
noinst_HEADERS =
noinst_HEADERS += ../webp/format_constants.h
libwebpdemux_la_LIBADD = ../libwebp.la libwebpdemux_la_LIBADD = ../libwebp.la
libwebpdemux_la_LDFLAGS = -no-undefined -version-info 2:3:0 libwebpdemux_la_LDFLAGS = -no-undefined -version-info 2:5:0
libwebpdemuxincludedir = $(includedir)/webp libwebpdemuxincludedir = $(includedir)/webp
pkgconfig_DATA = libwebpdemux.pc pkgconfig_DATA = libwebpdemux.pc

View File

@ -23,9 +23,9 @@
#include "src/webp/demux.h" #include "src/webp/demux.h"
#include "src/webp/format_constants.h" #include "src/webp/format_constants.h"
#define DMUX_MAJ_VERSION 0 #define DMUX_MAJ_VERSION 1
#define DMUX_MIN_VERSION 3 #define DMUX_MIN_VERSION 0
#define DMUX_REV_VERSION 3 #define DMUX_REV_VERSION 1
typedef struct { typedef struct {
size_t start_; // start location of the data size_t start_; // start location of the data

View File

@ -6,8 +6,8 @@
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
VS_VERSION_INFO VERSIONINFO VS_VERSION_INFO VERSIONINFO
FILEVERSION 0,3,0,3 FILEVERSION 1,0,0,1
PRODUCTVERSION 0,3,0,3 PRODUCTVERSION 1,0,0,1
FILEFLAGSMASK 0x3fL FILEFLAGSMASK 0x3fL
#ifdef _DEBUG #ifdef _DEBUG
FILEFLAGS 0x1L FILEFLAGS 0x1L
@ -24,12 +24,12 @@ BEGIN
BEGIN BEGIN
VALUE "CompanyName", "Google, Inc." VALUE "CompanyName", "Google, Inc."
VALUE "FileDescription", "libwebpdemux DLL" VALUE "FileDescription", "libwebpdemux DLL"
VALUE "FileVersion", "0.3.3" VALUE "FileVersion", "1.0.1"
VALUE "InternalName", "libwebpdemux.dll" VALUE "InternalName", "libwebpdemux.dll"
VALUE "LegalCopyright", "Copyright (C) 2017" VALUE "LegalCopyright", "Copyright (C) 2018"
VALUE "OriginalFilename", "libwebpdemux.dll" VALUE "OriginalFilename", "libwebpdemux.dll"
VALUE "ProductName", "WebP Image Demuxer" VALUE "ProductName", "WebP Image Demuxer"
VALUE "ProductVersion", "0.3.3" VALUE "ProductVersion", "1.0.1"
END END
END END
BLOCK "VarFileInfo" BLOCK "VarFileInfo"

View File

@ -1,7 +1,6 @@
AM_CPPFLAGS += -I$(top_builddir) -I$(top_srcdir) AM_CPPFLAGS += -I$(top_builddir) -I$(top_srcdir)
noinst_LTLIBRARIES = noinst_LTLIBRARIES =
noinst_LTLIBRARIES += libwebpdsp.la noinst_LTLIBRARIES += libwebpdsp.la
noinst_LTLIBRARIES += libwebpdsp_avx2.la
noinst_LTLIBRARIES += libwebpdsp_sse2.la noinst_LTLIBRARIES += libwebpdsp_sse2.la
noinst_LTLIBRARIES += libwebpdspdecode_sse2.la noinst_LTLIBRARIES += libwebpdspdecode_sse2.la
noinst_LTLIBRARIES += libwebpdsp_sse41.la noinst_LTLIBRARIES += libwebpdsp_sse41.la
@ -10,6 +9,10 @@ noinst_LTLIBRARIES += libwebpdsp_neon.la
noinst_LTLIBRARIES += libwebpdspdecode_neon.la noinst_LTLIBRARIES += libwebpdspdecode_neon.la
noinst_LTLIBRARIES += libwebpdsp_msa.la noinst_LTLIBRARIES += libwebpdsp_msa.la
noinst_LTLIBRARIES += libwebpdspdecode_msa.la noinst_LTLIBRARIES += libwebpdspdecode_msa.la
noinst_LTLIBRARIES += libwebpdsp_mips32.la
noinst_LTLIBRARIES += libwebpdspdecode_mips32.la
noinst_LTLIBRARIES += libwebpdsp_mips_dsp_r2.la
noinst_LTLIBRARIES += libwebpdspdecode_mips_dsp_r2.la
if BUILD_LIBWEBPDECODER if BUILD_LIBWEBPDECODER
noinst_LTLIBRARIES += libwebpdspdecode.la noinst_LTLIBRARIES += libwebpdspdecode.la
@ -20,56 +23,36 @@ commondir = $(includedir)/webp
COMMON_SOURCES = COMMON_SOURCES =
COMMON_SOURCES += alpha_processing.c COMMON_SOURCES += alpha_processing.c
COMMON_SOURCES += alpha_processing_mips_dsp_r2.c
COMMON_SOURCES += common_sse2.h
COMMON_SOURCES += cpu.c COMMON_SOURCES += cpu.c
COMMON_SOURCES += dec.c COMMON_SOURCES += dec.c
COMMON_SOURCES += dec_clip_tables.c COMMON_SOURCES += dec_clip_tables.c
COMMON_SOURCES += dec_mips32.c
COMMON_SOURCES += dec_mips_dsp_r2.c
COMMON_SOURCES += dsp.h COMMON_SOURCES += dsp.h
COMMON_SOURCES += filters.c COMMON_SOURCES += filters.c
COMMON_SOURCES += filters_mips_dsp_r2.c
COMMON_SOURCES += lossless.c COMMON_SOURCES += lossless.c
COMMON_SOURCES += lossless.h COMMON_SOURCES += lossless.h
COMMON_SOURCES += lossless_common.h COMMON_SOURCES += lossless_common.h
COMMON_SOURCES += lossless_mips_dsp_r2.c
COMMON_SOURCES += mips_macro.h
COMMON_SOURCES += rescaler.c COMMON_SOURCES += rescaler.c
COMMON_SOURCES += rescaler_mips32.c
COMMON_SOURCES += rescaler_mips_dsp_r2.c
COMMON_SOURCES += upsampling.c COMMON_SOURCES += upsampling.c
COMMON_SOURCES += upsampling_mips_dsp_r2.c
COMMON_SOURCES += yuv.c COMMON_SOURCES += yuv.c
COMMON_SOURCES += yuv.h COMMON_SOURCES += yuv.h
COMMON_SOURCES += yuv_mips32.c
COMMON_SOURCES += yuv_mips_dsp_r2.c
ENC_SOURCES = ENC_SOURCES =
ENC_SOURCES += cost.c ENC_SOURCES += cost.c
ENC_SOURCES += cost_mips32.c
ENC_SOURCES += cost_mips_dsp_r2.c
ENC_SOURCES += enc.c ENC_SOURCES += enc.c
ENC_SOURCES += enc_mips32.c
ENC_SOURCES += enc_mips_dsp_r2.c
ENC_SOURCES += lossless_enc.c ENC_SOURCES += lossless_enc.c
ENC_SOURCES += lossless_enc_mips32.c
ENC_SOURCES += lossless_enc_mips_dsp_r2.c
ENC_SOURCES += ssim.c ENC_SOURCES += ssim.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_sse41_la_SOURCES = libwebpdspdecode_sse41_la_SOURCES =
libwebpdspdecode_sse41_la_SOURCES += alpha_processing_sse41.c libwebpdspdecode_sse41_la_SOURCES += alpha_processing_sse41.c
libwebpdspdecode_sse41_la_SOURCES += dec_sse41.c libwebpdspdecode_sse41_la_SOURCES += dec_sse41.c
libwebpdspdecode_sse41_la_SOURCES += upsampling_sse41.c
libwebpdspdecode_sse41_la_SOURCES += yuv_sse41.c
libwebpdspdecode_sse41_la_CPPFLAGS = $(libwebpdsp_la_CPPFLAGS) libwebpdspdecode_sse41_la_CPPFLAGS = $(libwebpdsp_la_CPPFLAGS)
libwebpdspdecode_sse41_la_CFLAGS = $(AM_CFLAGS) $(SSE41_FLAGS) libwebpdspdecode_sse41_la_CFLAGS = $(AM_CFLAGS) $(SSE41_FLAGS)
libwebpdspdecode_sse2_la_SOURCES = libwebpdspdecode_sse2_la_SOURCES =
libwebpdspdecode_sse2_la_SOURCES += alpha_processing_sse2.c libwebpdspdecode_sse2_la_SOURCES += alpha_processing_sse2.c
libwebpdspdecode_sse2_la_SOURCES += common_sse2.h
libwebpdspdecode_sse2_la_SOURCES += dec_sse2.c libwebpdspdecode_sse2_la_SOURCES += dec_sse2.c
libwebpdspdecode_sse2_la_SOURCES += filters_sse2.c libwebpdspdecode_sse2_la_SOURCES += filters_sse2.c
libwebpdspdecode_sse2_la_SOURCES += lossless_sse2.c libwebpdspdecode_sse2_la_SOURCES += lossless_sse2.c
@ -101,6 +84,26 @@ libwebpdspdecode_msa_la_SOURCES += upsampling_msa.c
libwebpdspdecode_msa_la_CPPFLAGS = $(libwebpdsp_msa_la_CPPFLAGS) libwebpdspdecode_msa_la_CPPFLAGS = $(libwebpdsp_msa_la_CPPFLAGS)
libwebpdspdecode_msa_la_CFLAGS = $(libwebpdsp_msa_la_CFLAGS) libwebpdspdecode_msa_la_CFLAGS = $(libwebpdsp_msa_la_CFLAGS)
libwebpdspdecode_mips32_la_SOURCES =
libwebpdspdecode_mips32_la_SOURCES += dec_mips32.c
libwebpdspdecode_mips32_la_SOURCES += mips_macro.h
libwebpdspdecode_mips32_la_SOURCES += rescaler_mips32.c
libwebpdspdecode_mips32_la_SOURCES += yuv_mips32.c
libwebpdspdecode_mips32_la_CPPFLAGS = $(libwebpdsp_mips32_la_CPPFLAGS)
libwebpdspdecode_mips32_la_CFLAGS = $(libwebpdsp_mips32_la_CFLAGS)
libwebpdspdecode_mips_dsp_r2_la_SOURCES =
libwebpdspdecode_mips_dsp_r2_la_SOURCES += alpha_processing_mips_dsp_r2.c
libwebpdspdecode_mips_dsp_r2_la_SOURCES += dec_mips_dsp_r2.c
libwebpdspdecode_mips_dsp_r2_la_SOURCES += filters_mips_dsp_r2.c
libwebpdspdecode_mips_dsp_r2_la_SOURCES += lossless_mips_dsp_r2.c
libwebpdspdecode_mips_dsp_r2_la_SOURCES += mips_macro.h
libwebpdspdecode_mips_dsp_r2_la_SOURCES += rescaler_mips_dsp_r2.c
libwebpdspdecode_mips_dsp_r2_la_SOURCES += upsampling_mips_dsp_r2.c
libwebpdspdecode_mips_dsp_r2_la_SOURCES += yuv_mips_dsp_r2.c
libwebpdspdecode_mips_dsp_r2_la_CPPFLAGS = $(libwebpdsp_mips_dsp_r2_la_CPPFLAGS)
libwebpdspdecode_mips_dsp_r2_la_CFLAGS = $(libwebpdsp_mips_dsp_r2_la_CFLAGS)
libwebpdsp_sse2_la_SOURCES = libwebpdsp_sse2_la_SOURCES =
libwebpdsp_sse2_la_SOURCES += cost_sse2.c libwebpdsp_sse2_la_SOURCES += cost_sse2.c
libwebpdsp_sse2_la_SOURCES += enc_sse2.c libwebpdsp_sse2_la_SOURCES += enc_sse2.c
@ -131,6 +134,22 @@ libwebpdsp_msa_la_CPPFLAGS = $(libwebpdsp_la_CPPFLAGS)
libwebpdsp_msa_la_CFLAGS = $(AM_CFLAGS) libwebpdsp_msa_la_CFLAGS = $(AM_CFLAGS)
libwebpdsp_msa_la_LIBADD = libwebpdspdecode_msa.la libwebpdsp_msa_la_LIBADD = libwebpdspdecode_msa.la
libwebpdsp_mips32_la_SOURCES =
libwebpdsp_mips32_la_SOURCES += cost_mips32.c
libwebpdsp_mips32_la_SOURCES += enc_mips32.c
libwebpdsp_mips32_la_SOURCES += lossless_enc_mips32.c
libwebpdsp_mips32_la_CPPFLAGS = $(libwebpdsp_la_CPPFLAGS)
libwebpdsp_mips32_la_CFLAGS = $(AM_CFLAGS)
libwebpdsp_mips32_la_LIBADD = libwebpdspdecode_mips32.la
libwebpdsp_mips_dsp_r2_la_SOURCES =
libwebpdsp_mips_dsp_r2_la_SOURCES += cost_mips_dsp_r2.c
libwebpdsp_mips_dsp_r2_la_SOURCES += enc_mips_dsp_r2.c
libwebpdsp_mips_dsp_r2_la_SOURCES += lossless_enc_mips_dsp_r2.c
libwebpdsp_mips_dsp_r2_la_CPPFLAGS = $(libwebpdsp_la_CPPFLAGS)
libwebpdsp_mips_dsp_r2_la_CFLAGS = $(AM_CFLAGS)
libwebpdsp_mips_dsp_r2_la_LIBADD = libwebpdspdecode_mips_dsp_r2.la
libwebpdsp_la_SOURCES = $(COMMON_SOURCES) $(ENC_SOURCES) libwebpdsp_la_SOURCES = $(COMMON_SOURCES) $(ENC_SOURCES)
noinst_HEADERS = noinst_HEADERS =
@ -139,14 +158,15 @@ noinst_HEADERS += ../webp/decode.h
libwebpdsp_la_CPPFLAGS = libwebpdsp_la_CPPFLAGS =
libwebpdsp_la_CPPFLAGS += $(AM_CPPFLAGS) libwebpdsp_la_CPPFLAGS += $(AM_CPPFLAGS)
libwebpdsp_la_CPPFLAGS += $(USE_EXPERIMENTAL_CODE) $(USE_SWAP_16BIT_CSP) libwebpdsp_la_CPPFLAGS += $(USE_SWAP_16BIT_CSP)
libwebpdsp_la_LDFLAGS = -lm libwebpdsp_la_LDFLAGS = -lm
libwebpdsp_la_LIBADD = libwebpdsp_la_LIBADD =
libwebpdsp_la_LIBADD += libwebpdsp_avx2.la
libwebpdsp_la_LIBADD += libwebpdsp_sse2.la libwebpdsp_la_LIBADD += libwebpdsp_sse2.la
libwebpdsp_la_LIBADD += libwebpdsp_sse41.la libwebpdsp_la_LIBADD += libwebpdsp_sse41.la
libwebpdsp_la_LIBADD += libwebpdsp_neon.la libwebpdsp_la_LIBADD += libwebpdsp_neon.la
libwebpdsp_la_LIBADD += libwebpdsp_msa.la libwebpdsp_la_LIBADD += libwebpdsp_msa.la
libwebpdsp_la_LIBADD += libwebpdsp_mips32.la
libwebpdsp_la_LIBADD += libwebpdsp_mips_dsp_r2.la
if BUILD_LIBWEBPDECODER if BUILD_LIBWEBPDECODER
libwebpdspdecode_la_SOURCES = $(COMMON_SOURCES) libwebpdspdecode_la_SOURCES = $(COMMON_SOURCES)
@ -158,4 +178,6 @@ if BUILD_LIBWEBPDECODER
libwebpdspdecode_la_LIBADD += libwebpdspdecode_sse41.la libwebpdspdecode_la_LIBADD += libwebpdspdecode_sse41.la
libwebpdspdecode_la_LIBADD += libwebpdspdecode_neon.la libwebpdspdecode_la_LIBADD += libwebpdspdecode_neon.la
libwebpdspdecode_la_LIBADD += libwebpdspdecode_msa.la libwebpdspdecode_la_LIBADD += libwebpdspdecode_msa.la
libwebpdspdecode_la_LIBADD += libwebpdspdecode_mips32.la
libwebpdspdecode_la_LIBADD += libwebpdspdecode_mips_dsp_r2.la
endif endif

View File

@ -409,12 +409,7 @@ extern void WebPInitAlphaProcessingSSE2(void);
extern void WebPInitAlphaProcessingSSE41(void); extern void WebPInitAlphaProcessingSSE41(void);
extern void WebPInitAlphaProcessingNEON(void); extern void WebPInitAlphaProcessingNEON(void);
static volatile VP8CPUInfo alpha_processing_last_cpuinfo_used = WEBP_DSP_INIT_FUNC(WebPInitAlphaProcessing) {
(VP8CPUInfo)&alpha_processing_last_cpuinfo_used;
WEBP_TSAN_IGNORE_FUNCTION void WebPInitAlphaProcessing(void) {
if (alpha_processing_last_cpuinfo_used == VP8GetCPUInfo) return;
WebPMultARGBRow = WebPMultARGBRow_C; WebPMultARGBRow = WebPMultARGBRow_C;
WebPMultRow = WebPMultRow_C; WebPMultRow = WebPMultRow_C;
WebPApplyAlphaMultiply4444 = ApplyAlphaMultiply_16b_C; WebPApplyAlphaMultiply4444 = ApplyAlphaMultiply_16b_C;
@ -474,6 +469,4 @@ WEBP_TSAN_IGNORE_FUNCTION void WebPInitAlphaProcessing(void) {
assert(WebPPackRGB != NULL); assert(WebPPackRGB != NULL);
assert(WebPHasAlpha8b != NULL); assert(WebPHasAlpha8b != NULL);
assert(WebPHasAlpha32b != NULL); assert(WebPHasAlpha32b != NULL);
alpha_processing_last_cpuinfo_used = VP8GetCPUInfo;
} }

View File

@ -83,7 +83,7 @@ static void ApplyAlphaMultiply_NEON(uint8_t* rgba, int alpha_first,
static int DispatchAlpha_NEON(const uint8_t* alpha, int alpha_stride, static int DispatchAlpha_NEON(const uint8_t* alpha, int alpha_stride,
int width, int height, int width, int height,
uint8_t* dst, int dst_stride) { uint8_t* dst, int dst_stride) {
uint32_t alpha_mask = 0xffu; uint32_t alpha_mask = 0xffffffffu;
uint8x8_t mask8 = vdup_n_u8(0xff); uint8x8_t mask8 = vdup_n_u8(0xff);
uint32_t tmp[2]; uint32_t tmp[2];
int i, j; int i, j;
@ -107,7 +107,6 @@ static int DispatchAlpha_NEON(const uint8_t* alpha, int alpha_stride,
dst += dst_stride; dst += dst_stride;
} }
vst1_u8((uint8_t*)tmp, mask8); vst1_u8((uint8_t*)tmp, mask8);
alpha_mask *= 0x01010101;
alpha_mask &= tmp[0]; alpha_mask &= tmp[0];
alpha_mask &= tmp[1]; alpha_mask &= tmp[1];
return (alpha_mask != 0xffffffffu); return (alpha_mask != 0xffffffffu);
@ -135,7 +134,7 @@ static void DispatchAlphaToGreen_NEON(const uint8_t* alpha, int alpha_stride,
static int ExtractAlpha_NEON(const uint8_t* argb, int argb_stride, static int ExtractAlpha_NEON(const uint8_t* argb, int argb_stride,
int width, int height, int width, int height,
uint8_t* alpha, int alpha_stride) { uint8_t* alpha, int alpha_stride) {
uint32_t alpha_mask = 0xffu; uint32_t alpha_mask = 0xffffffffu;
uint8x8_t mask8 = vdup_n_u8(0xff); uint8x8_t mask8 = vdup_n_u8(0xff);
uint32_t tmp[2]; uint32_t tmp[2];
int i, j; int i, j;
@ -157,7 +156,6 @@ static int ExtractAlpha_NEON(const uint8_t* argb, int argb_stride,
alpha += alpha_stride; alpha += alpha_stride;
} }
vst1_u8((uint8_t*)tmp, mask8); vst1_u8((uint8_t*)tmp, mask8);
alpha_mask *= 0x01010101;
alpha_mask &= tmp[0]; alpha_mask &= tmp[0];
alpha_mask &= tmp[1]; alpha_mask &= tmp[1];
return (alpha_mask == 0xffffffffu); return (alpha_mask == 0xffffffffu);

View File

@ -128,9 +128,9 @@ static WEBP_INLINE void VP8Transpose_2_4x4_16b(
// Pack the planar buffers // Pack the planar buffers
// rrrr... rrrr... gggg... gggg... bbbb... bbbb.... // rrrr... rrrr... gggg... gggg... bbbb... bbbb....
// triplet by triplet in the output buffer rgb as rgbrgbrgbrgb ... // triplet by triplet in the output buffer rgb as rgbrgbrgbrgb ...
static WEBP_INLINE void VP8PlanarTo24b(__m128i* const in0, __m128i* const in1, static WEBP_INLINE void VP8PlanarTo24b_SSE2(
__m128i* const in2, __m128i* const in3, __m128i* const in0, __m128i* const in1, __m128i* const in2,
__m128i* const in4, __m128i* const in5) { __m128i* const in3, __m128i* const in4, __m128i* const in5) {
// The input is 6 registers of sixteen 8b but for the sake of explanation, // The input is 6 registers of sixteen 8b but for the sake of explanation,
// let's take 6 registers of four 8b values. // let's take 6 registers of four 8b values.
// To pack, we will keep taking one every two 8b integer and move it // To pack, we will keep taking one every two 8b integer and move it
@ -159,10 +159,10 @@ static WEBP_INLINE void VP8PlanarTo24b(__m128i* const in0, __m128i* const in1,
// Convert four packed four-channel buffers like argbargbargbargb... into the // Convert four packed four-channel buffers like argbargbargbargb... into the
// split channels aaaaa ... rrrr ... gggg .... bbbbb ...... // split channels aaaaa ... rrrr ... gggg .... bbbbb ......
static WEBP_INLINE void VP8L32bToPlanar(__m128i* const in0, static WEBP_INLINE void VP8L32bToPlanar_SSE2(__m128i* const in0,
__m128i* const in1, __m128i* const in1,
__m128i* const in2, __m128i* const in2,
__m128i* const in3) { __m128i* const in3) {
// Column-wise transpose. // Column-wise transpose.
const __m128i A0 = _mm_unpacklo_epi8(*in0, *in1); const __m128i A0 = _mm_unpacklo_epi8(*in0, *in1);
const __m128i A1 = _mm_unpackhi_epi8(*in0, *in1); const __m128i A1 = _mm_unpackhi_epi8(*in0, *in1);

132
src/dsp/common_sse41.h Normal file
View File

@ -0,0 +1,132 @@
// Copyright 2016 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.
// -----------------------------------------------------------------------------
//
// SSE4 code common to several files.
//
// Author: Vincent Rabaud (vrabaud@google.com)
#ifndef WEBP_DSP_COMMON_SSE41_H_
#define WEBP_DSP_COMMON_SSE41_H_
#ifdef __cplusplus
extern "C" {
#endif
#if defined(WEBP_USE_SSE41)
#include <smmintrin.h>
//------------------------------------------------------------------------------
// Channel mixing.
// Shuffles the input buffer as A0 0 0 A1 0 0 A2 ...
#define WEBP_SSE41_SHUFF(OUT, IN0, IN1) \
OUT##0 = _mm_shuffle_epi8(*IN0, shuff0); \
OUT##1 = _mm_shuffle_epi8(*IN0, shuff1); \
OUT##2 = _mm_shuffle_epi8(*IN0, shuff2); \
OUT##3 = _mm_shuffle_epi8(*IN1, shuff0); \
OUT##4 = _mm_shuffle_epi8(*IN1, shuff1); \
OUT##5 = _mm_shuffle_epi8(*IN1, shuff2);
// Pack the planar buffers
// rrrr... rrrr... gggg... gggg... bbbb... bbbb....
// triplet by triplet in the output buffer rgb as rgbrgbrgbrgb ...
static WEBP_INLINE void VP8PlanarTo24b_SSE41(
__m128i* const in0, __m128i* const in1, __m128i* const in2,
__m128i* const in3, __m128i* const in4, __m128i* const in5) {
__m128i R0, R1, R2, R3, R4, R5;
__m128i G0, G1, G2, G3, G4, G5;
__m128i B0, B1, B2, B3, B4, B5;
// Process R.
{
const __m128i shuff0 = _mm_set_epi8(
5, -1, -1, 4, -1, -1, 3, -1, -1, 2, -1, -1, 1, -1, -1, 0);
const __m128i shuff1 = _mm_set_epi8(
-1, 10, -1, -1, 9, -1, -1, 8, -1, -1, 7, -1, -1, 6, -1, -1);
const __m128i shuff2 = _mm_set_epi8(
-1, -1, 15, -1, -1, 14, -1, -1, 13, -1, -1, 12, -1, -1, 11, -1);
WEBP_SSE41_SHUFF(R, in0, in1)
}
// Process G.
{
// Same as before, just shifted to the left by one and including the right
// padding.
const __m128i shuff0 = _mm_set_epi8(
-1, -1, 4, -1, -1, 3, -1, -1, 2, -1, -1, 1, -1, -1, 0, -1);
const __m128i shuff1 = _mm_set_epi8(
10, -1, -1, 9, -1, -1, 8, -1, -1, 7, -1, -1, 6, -1, -1, 5);
const __m128i shuff2 = _mm_set_epi8(
-1, 15, -1, -1, 14, -1, -1, 13, -1, -1, 12, -1, -1, 11, -1, -1);
WEBP_SSE41_SHUFF(G, in2, in3)
}
// Process B.
{
const __m128i shuff0 = _mm_set_epi8(
-1, 4, -1, -1, 3, -1, -1, 2, -1, -1, 1, -1, -1, 0, -1, -1);
const __m128i shuff1 = _mm_set_epi8(
-1, -1, 9, -1, -1, 8, -1, -1, 7, -1, -1, 6, -1, -1, 5, -1);
const __m128i shuff2 = _mm_set_epi8(
15, -1, -1, 14, -1, -1, 13, -1, -1, 12, -1, -1, 11, -1, -1, 10);
WEBP_SSE41_SHUFF(B, in4, in5)
}
// OR the different channels.
{
const __m128i RG0 = _mm_or_si128(R0, G0);
const __m128i RG1 = _mm_or_si128(R1, G1);
const __m128i RG2 = _mm_or_si128(R2, G2);
const __m128i RG3 = _mm_or_si128(R3, G3);
const __m128i RG4 = _mm_or_si128(R4, G4);
const __m128i RG5 = _mm_or_si128(R5, G5);
*in0 = _mm_or_si128(RG0, B0);
*in1 = _mm_or_si128(RG1, B1);
*in2 = _mm_or_si128(RG2, B2);
*in3 = _mm_or_si128(RG3, B3);
*in4 = _mm_or_si128(RG4, B4);
*in5 = _mm_or_si128(RG5, B5);
}
}
#undef WEBP_SSE41_SHUFF
// Convert four packed four-channel buffers like argbargbargbargb... into the
// split channels aaaaa ... rrrr ... gggg .... bbbbb ......
static WEBP_INLINE void VP8L32bToPlanar_SSE41(__m128i* const in0,
__m128i* const in1,
__m128i* const in2,
__m128i* const in3) {
// aaaarrrrggggbbbb
const __m128i shuff0 =
_mm_set_epi8(15, 11, 7, 3, 14, 10, 6, 2, 13, 9, 5, 1, 12, 8, 4, 0);
const __m128i A0 = _mm_shuffle_epi8(*in0, shuff0);
const __m128i A1 = _mm_shuffle_epi8(*in1, shuff0);
const __m128i A2 = _mm_shuffle_epi8(*in2, shuff0);
const __m128i A3 = _mm_shuffle_epi8(*in3, shuff0);
// A0A1R0R1
// G0G1B0B1
// A2A3R2R3
// G0G1B0B1
const __m128i B0 = _mm_unpacklo_epi32(A0, A1);
const __m128i B1 = _mm_unpackhi_epi32(A0, A1);
const __m128i B2 = _mm_unpacklo_epi32(A2, A3);
const __m128i B3 = _mm_unpackhi_epi32(A2, A3);
*in3 = _mm_unpacklo_epi64(B0, B2);
*in2 = _mm_unpackhi_epi64(B0, B2);
*in1 = _mm_unpacklo_epi64(B1, B3);
*in0 = _mm_unpackhi_epi64(B1, B3);
}
#endif // WEBP_USE_SSE41
#ifdef __cplusplus
} // extern "C"
#endif
#endif // WEBP_DSP_COMMON_SSE41_H_

View File

@ -378,12 +378,7 @@ extern void VP8EncDspCostInitMIPS32(void);
extern void VP8EncDspCostInitMIPSdspR2(void); extern void VP8EncDspCostInitMIPSdspR2(void);
extern void VP8EncDspCostInitSSE2(void); extern void VP8EncDspCostInitSSE2(void);
static volatile VP8CPUInfo cost_last_cpuinfo_used = WEBP_DSP_INIT_FUNC(VP8EncDspCostInit) {
(VP8CPUInfo)&cost_last_cpuinfo_used;
WEBP_TSAN_IGNORE_FUNCTION void VP8EncDspCostInit(void) {
if (cost_last_cpuinfo_used == VP8GetCPUInfo) return;
VP8GetResidualCost = GetResidualCost_C; VP8GetResidualCost = GetResidualCost_C;
VP8SetResidualCoeffs = SetResidualCoeffs_C; VP8SetResidualCoeffs = SetResidualCoeffs_C;
@ -405,8 +400,6 @@ WEBP_TSAN_IGNORE_FUNCTION void VP8EncDspCostInit(void) {
} }
#endif #endif
} }
cost_last_cpuinfo_used = VP8GetCPUInfo;
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------

View File

@ -741,12 +741,7 @@ extern void VP8DspInitMIPS32(void);
extern void VP8DspInitMIPSdspR2(void); extern void VP8DspInitMIPSdspR2(void);
extern void VP8DspInitMSA(void); extern void VP8DspInitMSA(void);
static volatile VP8CPUInfo dec_last_cpuinfo_used = WEBP_DSP_INIT_FUNC(VP8DspInit) {
(VP8CPUInfo)&dec_last_cpuinfo_used;
WEBP_TSAN_IGNORE_FUNCTION void VP8DspInit(void) {
if (dec_last_cpuinfo_used == VP8GetCPUInfo) return;
VP8InitClipTables(); VP8InitClipTables();
#if !WEBP_NEON_OMIT_C_CODE #if !WEBP_NEON_OMIT_C_CODE
@ -889,6 +884,4 @@ WEBP_TSAN_IGNORE_FUNCTION void VP8DspInit(void) {
assert(VP8PredChroma8[5] != NULL); assert(VP8PredChroma8[5] != NULL);
assert(VP8PredChroma8[6] != NULL); assert(VP8PredChroma8[6] != NULL);
assert(VP8DitherCombine8x8 != NULL); assert(VP8DitherCombine8x8 != NULL);
dec_last_cpuinfo_used = VP8GetCPUInfo;
} }

View File

@ -76,10 +76,6 @@ extern "C" {
#define WEBP_USE_SSE41 #define WEBP_USE_SSE41
#endif #endif
#if defined(__AVX2__) || defined(WEBP_HAVE_AVX2)
#define WEBP_USE_AVX2
#endif
// The intrinsics currently cause compiler errors with arm-nacl-gcc and the // The intrinsics currently cause compiler errors with arm-nacl-gcc and the
// inline assembly would need to be modified for use with Native Client. // inline assembly would need to be modified for use with Native Client.
#if (defined(__ARM_NEON__) || \ #if (defined(__ARM_NEON__) || \
@ -141,6 +137,42 @@ extern "C" {
#endif #endif
#endif #endif
#if defined(WEBP_USE_THREAD) && !defined(_WIN32)
#include <pthread.h> // NOLINT
#define WEBP_DSP_INIT(func) do { \
static volatile VP8CPUInfo func ## _last_cpuinfo_used = \
(VP8CPUInfo)&func ## _last_cpuinfo_used; \
static pthread_mutex_t func ## _lock = PTHREAD_MUTEX_INITIALIZER; \
if (pthread_mutex_lock(&func ## _lock)) break; \
if (func ## _last_cpuinfo_used != VP8GetCPUInfo) func(); \
func ## _last_cpuinfo_used = VP8GetCPUInfo; \
(void)pthread_mutex_unlock(&func ## _lock); \
} while (0)
#else // !(defined(WEBP_USE_THREAD) && !defined(_WIN32))
#define WEBP_DSP_INIT(func) do { \
static volatile VP8CPUInfo func ## _last_cpuinfo_used = \
(VP8CPUInfo)&func ## _last_cpuinfo_used; \
if (func ## _last_cpuinfo_used == VP8GetCPUInfo) break; \
func(); \
func ## _last_cpuinfo_used = VP8GetCPUInfo; \
} while (0)
#endif // defined(WEBP_USE_THREAD) && !defined(_WIN32)
// Defines an Init + helper function that control multiple initialization of
// function pointers / tables.
/* Usage:
WEBP_DSP_INIT_FUNC(InitFunc) {
...function body
}
*/
#define WEBP_DSP_INIT_FUNC(name) \
static WEBP_TSAN_IGNORE_FUNCTION void name ## _body(void); \
WEBP_TSAN_IGNORE_FUNCTION void name(void) { \
WEBP_DSP_INIT(name ## _body); \
} \
static WEBP_TSAN_IGNORE_FUNCTION void name ## _body(void)
#define WEBP_UBSAN_IGNORE_UNDEF #define WEBP_UBSAN_IGNORE_UNDEF
#define WEBP_UBSAN_IGNORE_UNSIGNED_OVERFLOW #define WEBP_UBSAN_IGNORE_UNSIGNED_OVERFLOW
#if defined(__clang__) && defined(__has_attribute) #if defined(__clang__) && defined(__has_attribute)
@ -196,7 +228,7 @@ WEBP_EXTERN VP8CPUInfo VP8GetCPUInfo;
// avoiding a compiler warning. // avoiding a compiler warning.
#define WEBP_DSP_INIT_STUB(func) \ #define WEBP_DSP_INIT_STUB(func) \
extern void func(void); \ extern void func(void); \
WEBP_TSAN_IGNORE_FUNCTION void func(void) {} void func(void) {}
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// Encoding // Encoding
@ -643,4 +675,4 @@ void VP8FiltersInit(void);
} // extern "C" } // extern "C"
#endif #endif
#endif /* WEBP_DSP_DSP_H_ */ #endif // WEBP_DSP_DSP_H_

View File

@ -734,18 +734,12 @@ VP8BlockCopy VP8Copy16x8;
extern void VP8EncDspInitSSE2(void); extern void VP8EncDspInitSSE2(void);
extern void VP8EncDspInitSSE41(void); extern void VP8EncDspInitSSE41(void);
extern void VP8EncDspInitAVX2(void);
extern void VP8EncDspInitNEON(void); extern void VP8EncDspInitNEON(void);
extern void VP8EncDspInitMIPS32(void); extern void VP8EncDspInitMIPS32(void);
extern void VP8EncDspInitMIPSdspR2(void); extern void VP8EncDspInitMIPSdspR2(void);
extern void VP8EncDspInitMSA(void); extern void VP8EncDspInitMSA(void);
static volatile VP8CPUInfo enc_last_cpuinfo_used = WEBP_DSP_INIT_FUNC(VP8EncDspInit) {
(VP8CPUInfo)&enc_last_cpuinfo_used;
WEBP_TSAN_IGNORE_FUNCTION void VP8EncDspInit(void) {
if (enc_last_cpuinfo_used == VP8GetCPUInfo) return;
VP8DspInit(); // common inverse transforms VP8DspInit(); // common inverse transforms
InitTables(); InitTables();
@ -789,11 +783,6 @@ WEBP_TSAN_IGNORE_FUNCTION void VP8EncDspInit(void) {
#endif #endif
} }
#endif #endif
#if defined(WEBP_USE_AVX2)
if (VP8GetCPUInfo(kAVX2)) {
VP8EncDspInitAVX2();
}
#endif
#if defined(WEBP_USE_MIPS32) #if defined(WEBP_USE_MIPS32)
if (VP8GetCPUInfo(kMIPS32)) { if (VP8GetCPUInfo(kMIPS32)) {
VP8EncDspInitMIPS32(); VP8EncDspInitMIPS32();
@ -838,6 +827,4 @@ WEBP_TSAN_IGNORE_FUNCTION void VP8EncDspInit(void) {
assert(VP8EncQuantizeBlockWHT != NULL); assert(VP8EncQuantizeBlockWHT != NULL);
assert(VP8Copy4x4 != NULL); assert(VP8Copy4x4 != NULL);
assert(VP8Copy16x8 != NULL); assert(VP8Copy16x8 != NULL);
enc_last_cpuinfo_used = VP8GetCPUInfo;
} }

View File

@ -1,21 +0,0 @@
// 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 "src/dsp/dsp.h"
#if defined(WEBP_USE_AVX2)
#endif // WEBP_USE_AVX2
//------------------------------------------------------------------------------
// Entry point
WEBP_DSP_INIT_STUB(VP8EncDspInitAVX2)

View File

@ -238,12 +238,7 @@ extern void VP8FiltersInitMSA(void);
extern void VP8FiltersInitNEON(void); extern void VP8FiltersInitNEON(void);
extern void VP8FiltersInitSSE2(void); extern void VP8FiltersInitSSE2(void);
static volatile VP8CPUInfo filters_last_cpuinfo_used = WEBP_DSP_INIT_FUNC(VP8FiltersInit) {
(VP8CPUInfo)&filters_last_cpuinfo_used;
WEBP_TSAN_IGNORE_FUNCTION void VP8FiltersInit(void) {
if (filters_last_cpuinfo_used == VP8GetCPUInfo) return;
WebPUnfilters[WEBP_FILTER_NONE] = NULL; WebPUnfilters[WEBP_FILTER_NONE] = NULL;
#if !WEBP_NEON_OMIT_C_CODE #if !WEBP_NEON_OMIT_C_CODE
WebPUnfilters[WEBP_FILTER_HORIZONTAL] = HorizontalUnfilter_C; WebPUnfilters[WEBP_FILTER_HORIZONTAL] = HorizontalUnfilter_C;
@ -289,6 +284,4 @@ WEBP_TSAN_IGNORE_FUNCTION void VP8FiltersInit(void) {
assert(WebPFilters[WEBP_FILTER_HORIZONTAL] != NULL); assert(WebPFilters[WEBP_FILTER_HORIZONTAL] != NULL);
assert(WebPFilters[WEBP_FILTER_VERTICAL] != NULL); assert(WebPFilters[WEBP_FILTER_VERTICAL] != NULL);
assert(WebPFilters[WEBP_FILTER_GRADIENT] != NULL); assert(WebPFilters[WEBP_FILTER_GRADIENT] != NULL);
filters_last_cpuinfo_used = VP8GetCPUInfo;
} }

View File

@ -23,8 +23,6 @@
#include "src/dsp/lossless.h" #include "src/dsp/lossless.h"
#include "src/dsp/lossless_common.h" #include "src/dsp/lossless_common.h"
#define MAX_DIFF_COST (1e30f)
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// Image transforms. // Image transforms.
@ -577,9 +575,6 @@ extern void VP8LDspInitNEON(void);
extern void VP8LDspInitMIPSdspR2(void); extern void VP8LDspInitMIPSdspR2(void);
extern void VP8LDspInitMSA(void); extern void VP8LDspInitMSA(void);
static volatile VP8CPUInfo lossless_last_cpuinfo_used =
(VP8CPUInfo)&lossless_last_cpuinfo_used;
#define COPY_PREDICTOR_ARRAY(IN, OUT) do { \ #define COPY_PREDICTOR_ARRAY(IN, OUT) do { \
(OUT)[0] = IN##0_C; \ (OUT)[0] = IN##0_C; \
(OUT)[1] = IN##1_C; \ (OUT)[1] = IN##1_C; \
@ -599,9 +594,7 @@ static volatile VP8CPUInfo lossless_last_cpuinfo_used =
(OUT)[15] = IN##0_C; \ (OUT)[15] = IN##0_C; \
} while (0); } while (0);
WEBP_TSAN_IGNORE_FUNCTION void VP8LDspInit(void) { WEBP_DSP_INIT_FUNC(VP8LDspInit) {
if (lossless_last_cpuinfo_used == VP8GetCPUInfo) return;
COPY_PREDICTOR_ARRAY(Predictor, VP8LPredictors) COPY_PREDICTOR_ARRAY(Predictor, VP8LPredictors)
COPY_PREDICTOR_ARRAY(Predictor, VP8LPredictors_C) COPY_PREDICTOR_ARRAY(Predictor, VP8LPredictors_C)
COPY_PREDICTOR_ARRAY(PredictorAdd, VP8LPredictorsAdd) COPY_PREDICTOR_ARRAY(PredictorAdd, VP8LPredictorsAdd)
@ -658,8 +651,6 @@ WEBP_TSAN_IGNORE_FUNCTION void VP8LDspInit(void) {
assert(VP8LConvertBGRAToRGB565 != NULL); assert(VP8LConvertBGRAToRGB565 != NULL);
assert(VP8LMapColor32b != NULL); assert(VP8LMapColor32b != NULL);
assert(VP8LMapColor8b != NULL); assert(VP8LMapColor8b != NULL);
lossless_last_cpuinfo_used = VP8GetCPUInfo;
} }
#undef COPY_PREDICTOR_ARRAY #undef COPY_PREDICTOR_ARRAY

View File

@ -25,10 +25,6 @@
extern "C" { extern "C" {
#endif #endif
#ifdef WEBP_EXPERIMENTAL_FEATURES
#include "src/enc/delta_palettization_enc.h"
#endif // WEBP_EXPERIMENTAL_FEATURES
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// Decoding // Decoding
@ -167,7 +163,7 @@ extern VP8LCostCombinedFunc VP8LExtraCostCombined;
extern VP8LCombinedShannonEntropyFunc VP8LCombinedShannonEntropy; extern VP8LCombinedShannonEntropyFunc VP8LCombinedShannonEntropy;
typedef struct { // small struct to hold counters typedef struct { // small struct to hold counters
int counts[2]; // index: 0=zero steak, 1=non-zero streak int counts[2]; // index: 0=zero streak, 1=non-zero streak
int streaks[2][2]; // [zero/non-zero][streak<3 / streak>=3] int streaks[2][2]; // [zero/non-zero][streak<3 / streak>=3]
} VP8LStreaks; } VP8LStreaks;
@ -198,10 +194,14 @@ extern VP8LGetEntropyUnrefinedFunc VP8LGetEntropyUnrefined;
void VP8LBitsEntropyUnrefined(const uint32_t* const array, int n, void VP8LBitsEntropyUnrefined(const uint32_t* const array, int n,
VP8LBitEntropy* const entropy); VP8LBitEntropy* const entropy);
typedef void (*VP8LHistogramAddFunc)(const VP8LHistogram* const a, typedef void (*VP8LAddVectorFunc)(const uint32_t* a, const uint32_t* b,
const VP8LHistogram* const b, uint32_t* out, int size);
VP8LHistogram* const out); extern VP8LAddVectorFunc VP8LAddVector;
extern VP8LHistogramAddFunc VP8LHistogramAdd; typedef void (*VP8LAddVectorEqFunc)(const uint32_t* a, uint32_t* out, int size);
extern VP8LAddVectorEqFunc VP8LAddVectorEq;
void VP8LHistogramAdd(const VP8LHistogram* const a,
const VP8LHistogram* const b,
VP8LHistogram* const out);
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
// PrefixEncode() // PrefixEncode()

View File

@ -632,38 +632,67 @@ static double ExtraCostCombined_C(const uint32_t* X, const uint32_t* Y,
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
static void HistogramAdd_C(const VP8LHistogram* const a, static void AddVector_C(const uint32_t* a, const uint32_t* b, uint32_t* out,
const VP8LHistogram* const b, int size) {
VP8LHistogram* const out) { int i;
for (i = 0; i < size; ++i) out[i] = a[i] + b[i];
}
static void AddVectorEq_C(const uint32_t* a, uint32_t* out, int size) {
int i;
for (i = 0; i < size; ++i) out[i] += a[i];
}
#define ADD(X, ARG, LEN) do { \
if (a->is_used_[X]) { \
if (b->is_used_[X]) { \
VP8LAddVector(a->ARG, b->ARG, out->ARG, (LEN)); \
} else { \
memcpy(&out->ARG[0], &a->ARG[0], (LEN) * sizeof(out->ARG[0])); \
} \
} else if (b->is_used_[X]) { \
memcpy(&out->ARG[0], &b->ARG[0], (LEN) * sizeof(out->ARG[0])); \
} else { \
memset(&out->ARG[0], 0, (LEN) * sizeof(out->ARG[0])); \
} \
} while (0)
#define ADD_EQ(X, ARG, LEN) do { \
if (a->is_used_[X]) { \
if (out->is_used_[X]) { \
VP8LAddVectorEq(a->ARG, out->ARG, (LEN)); \
} else { \
memcpy(&out->ARG[0], &a->ARG[0], (LEN) * sizeof(out->ARG[0])); \
} \
} \
} while (0)
void VP8LHistogramAdd(const VP8LHistogram* const a,
const VP8LHistogram* const b, VP8LHistogram* const out) {
int i; int i;
const int literal_size = VP8LHistogramNumCodes(a->palette_code_bits_); const int literal_size = VP8LHistogramNumCodes(a->palette_code_bits_);
assert(a->palette_code_bits_ == b->palette_code_bits_); assert(a->palette_code_bits_ == b->palette_code_bits_);
if (b != out) { if (b != out) {
for (i = 0; i < literal_size; ++i) { ADD(0, literal_, literal_size);
out->literal_[i] = a->literal_[i] + b->literal_[i]; ADD(1, red_, NUM_LITERAL_CODES);
} ADD(2, blue_, NUM_LITERAL_CODES);
for (i = 0; i < NUM_DISTANCE_CODES; ++i) { ADD(3, alpha_, NUM_LITERAL_CODES);
out->distance_[i] = a->distance_[i] + b->distance_[i]; ADD(4, distance_, NUM_DISTANCE_CODES);
} for (i = 0; i < 5; ++i) {
for (i = 0; i < NUM_LITERAL_CODES; ++i) { out->is_used_[i] = (a->is_used_[i] | b->is_used_[i]);
out->red_[i] = a->red_[i] + b->red_[i];
out->blue_[i] = a->blue_[i] + b->blue_[i];
out->alpha_[i] = a->alpha_[i] + b->alpha_[i];
} }
} else { } else {
for (i = 0; i < literal_size; ++i) { ADD_EQ(0, literal_, literal_size);
out->literal_[i] += a->literal_[i]; ADD_EQ(1, red_, NUM_LITERAL_CODES);
} ADD_EQ(2, blue_, NUM_LITERAL_CODES);
for (i = 0; i < NUM_DISTANCE_CODES; ++i) { ADD_EQ(3, alpha_, NUM_LITERAL_CODES);
out->distance_[i] += a->distance_[i]; ADD_EQ(4, distance_, NUM_DISTANCE_CODES);
} for (i = 0; i < 5; ++i) out->is_used_[i] |= a->is_used_[i];
for (i = 0; i < NUM_LITERAL_CODES; ++i) {
out->red_[i] += a->red_[i];
out->blue_[i] += a->blue_[i];
out->alpha_[i] += a->alpha_[i];
}
} }
} }
#undef ADD
#undef ADD_EQ
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// Image transforms. // Image transforms.
@ -848,7 +877,8 @@ VP8LCombinedShannonEntropyFunc VP8LCombinedShannonEntropy;
VP8LGetEntropyUnrefinedFunc VP8LGetEntropyUnrefined; VP8LGetEntropyUnrefinedFunc VP8LGetEntropyUnrefined;
VP8LGetCombinedEntropyUnrefinedFunc VP8LGetCombinedEntropyUnrefined; VP8LGetCombinedEntropyUnrefinedFunc VP8LGetCombinedEntropyUnrefined;
VP8LHistogramAddFunc VP8LHistogramAdd; VP8LAddVectorFunc VP8LAddVector;
VP8LAddVectorEqFunc VP8LAddVectorEq;
VP8LVectorMismatchFunc VP8LVectorMismatch; VP8LVectorMismatchFunc VP8LVectorMismatch;
VP8LBundleColorMapFunc VP8LBundleColorMap; VP8LBundleColorMapFunc VP8LBundleColorMap;
@ -863,12 +893,7 @@ extern void VP8LEncDspInitMIPS32(void);
extern void VP8LEncDspInitMIPSdspR2(void); extern void VP8LEncDspInitMIPSdspR2(void);
extern void VP8LEncDspInitMSA(void); extern void VP8LEncDspInitMSA(void);
static volatile VP8CPUInfo lossless_enc_last_cpuinfo_used = WEBP_DSP_INIT_FUNC(VP8LEncDspInit) {
(VP8CPUInfo)&lossless_enc_last_cpuinfo_used;
WEBP_TSAN_IGNORE_FUNCTION void VP8LEncDspInit(void) {
if (lossless_enc_last_cpuinfo_used == VP8GetCPUInfo) return;
VP8LDspInit(); VP8LDspInit();
#if !WEBP_NEON_OMIT_C_CODE #if !WEBP_NEON_OMIT_C_CODE
@ -890,7 +915,8 @@ WEBP_TSAN_IGNORE_FUNCTION void VP8LEncDspInit(void) {
VP8LGetEntropyUnrefined = GetEntropyUnrefined_C; VP8LGetEntropyUnrefined = GetEntropyUnrefined_C;
VP8LGetCombinedEntropyUnrefined = GetCombinedEntropyUnrefined_C; VP8LGetCombinedEntropyUnrefined = GetCombinedEntropyUnrefined_C;
VP8LHistogramAdd = HistogramAdd_C; VP8LAddVector = AddVector_C;
VP8LAddVectorEq = AddVectorEq_C;
VP8LVectorMismatch = VectorMismatch_C; VP8LVectorMismatch = VectorMismatch_C;
VP8LBundleColorMap = VP8LBundleColorMap_C; VP8LBundleColorMap = VP8LBundleColorMap_C;
@ -976,7 +1002,8 @@ WEBP_TSAN_IGNORE_FUNCTION void VP8LEncDspInit(void) {
assert(VP8LCombinedShannonEntropy != NULL); assert(VP8LCombinedShannonEntropy != NULL);
assert(VP8LGetEntropyUnrefined != NULL); assert(VP8LGetEntropyUnrefined != NULL);
assert(VP8LGetCombinedEntropyUnrefined != NULL); assert(VP8LGetCombinedEntropyUnrefined != NULL);
assert(VP8LHistogramAdd != NULL); assert(VP8LAddVector != NULL);
assert(VP8LAddVectorEq != NULL);
assert(VP8LVectorMismatch != NULL); assert(VP8LVectorMismatch != NULL);
assert(VP8LBundleColorMap != NULL); assert(VP8LBundleColorMap != NULL);
assert(VP8LPredictorsSub[0] != NULL); assert(VP8LPredictorsSub[0] != NULL);
@ -1011,8 +1038,6 @@ WEBP_TSAN_IGNORE_FUNCTION void VP8LEncDspInit(void) {
assert(VP8LPredictorsSub_C[13] != NULL); assert(VP8LPredictorsSub_C[13] != NULL);
assert(VP8LPredictorsSub_C[14] != NULL); assert(VP8LPredictorsSub_C[14] != NULL);
assert(VP8LPredictorsSub_C[15] != NULL); assert(VP8LPredictorsSub_C[15] != NULL);
lossless_enc_last_cpuinfo_used = VP8GetCPUInfo;
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------

View File

@ -344,65 +344,29 @@ static void GetCombinedEntropyUnrefined_MIPS32(const uint32_t X[],
ASM_END_COMMON_0 \ ASM_END_COMMON_0 \
ASM_END_COMMON_1 ASM_END_COMMON_1
#define ADD_VECTOR(A, B, OUT, SIZE, EXTRA_SIZE) do { \ static void AddVector_MIPS32(const uint32_t* pa, const uint32_t* pb,
const uint32_t* pa = (const uint32_t*)(A); \ uint32_t* pout, int size) {
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_MIPS32(const VP8LHistogram* const a,
const VP8LHistogram* const b,
VP8LHistogram* const out) {
uint32_t temp0, temp1, temp2, temp3, temp4, temp5, temp6, temp7; uint32_t temp0, temp1, temp2, temp3, temp4, temp5, temp6, temp7;
const int extra_cache_size = VP8LHistogramNumCodes(a->palette_code_bits_) const uint32_t end = ((size) / 4) * 4;
- (NUM_LITERAL_CODES + NUM_LENGTH_CODES); const uint32_t* const LoopEnd = pa + end;
assert(a->palette_code_bits_ == b->palette_code_bits_); int i;
ASM_START
if (b != out) { ADD_TO_OUT(0, 4, 8, 12, 1, pa, pb, pout)
ADD_VECTOR(a->literal_, b->literal_, out->literal_, ASM_END_0
NUM_LITERAL_CODES + NUM_LENGTH_CODES, extra_cache_size); for (i = end; i < size; ++i) pout[i] = pa[i] + pb[i];
ADD_VECTOR(a->distance_, b->distance_, out->distance_, }
NUM_DISTANCE_CODES, 0);
ADD_VECTOR(a->red_, b->red_, out->red_, NUM_LITERAL_CODES, 0); static void AddVectorEq_MIPS32(const uint32_t* pa, uint32_t* pout, int size) {
ADD_VECTOR(a->blue_, b->blue_, out->blue_, NUM_LITERAL_CODES, 0); uint32_t temp0, temp1, temp2, temp3, temp4, temp5, temp6, temp7;
ADD_VECTOR(a->alpha_, b->alpha_, out->alpha_, NUM_LITERAL_CODES, 0); const uint32_t end = ((size) / 4) * 4;
} else { const uint32_t* const LoopEnd = pa + end;
ADD_VECTOR_EQ(a->literal_, out->literal_, int i;
NUM_LITERAL_CODES + NUM_LENGTH_CODES, extra_cache_size); ASM_START
ADD_VECTOR_EQ(a->distance_, out->distance_, NUM_DISTANCE_CODES, 0); ADD_TO_OUT(0, 4, 8, 12, 0, pa, pout, pout)
ADD_VECTOR_EQ(a->red_, out->red_, NUM_LITERAL_CODES, 0); ASM_END_1
ADD_VECTOR_EQ(a->blue_, out->blue_, NUM_LITERAL_CODES, 0); for (i = end; i < size; ++i) pout[i] += pa[i];
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_1
#undef ASM_END_0 #undef ASM_END_0
#undef ASM_END_COMMON_1 #undef ASM_END_COMMON_1
@ -422,7 +386,8 @@ WEBP_TSAN_IGNORE_FUNCTION void VP8LEncDspInitMIPS32(void) {
VP8LExtraCostCombined = ExtraCostCombined_MIPS32; VP8LExtraCostCombined = ExtraCostCombined_MIPS32;
VP8LGetEntropyUnrefined = GetEntropyUnrefined_MIPS32; VP8LGetEntropyUnrefined = GetEntropyUnrefined_MIPS32;
VP8LGetCombinedEntropyUnrefined = GetCombinedEntropyUnrefined_MIPS32; VP8LGetCombinedEntropyUnrefined = GetCombinedEntropyUnrefined_MIPS32;
VP8LHistogramAdd = HistogramAdd_MIPS32; VP8LAddVector = AddVector_MIPS32;
VP8LAddVectorEq = AddVectorEq_MIPS32;
} }
#else // !WEBP_USE_MIPS32 #else // !WEBP_USE_MIPS32

View File

@ -46,16 +46,14 @@ static void SubtractGreenFromBlueAndRed_SSE2(uint32_t* argb_data,
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// Color Transform // Color Transform
#define MK_CST_16(HI, LO) \
_mm_set1_epi32((int)(((uint32_t)(HI) << 16) | ((LO) & 0xffff)))
static void TransformColor_SSE2(const VP8LMultipliers* const m, static void TransformColor_SSE2(const VP8LMultipliers* const m,
uint32_t* argb_data, int num_pixels) { uint32_t* argb_data, int num_pixels) {
const __m128i mults_rb = _mm_set_epi16( const __m128i mults_rb = MK_CST_16(CST_5b(m->green_to_red_),
CST_5b(m->green_to_red_), CST_5b(m->green_to_blue_), CST_5b(m->green_to_blue_));
CST_5b(m->green_to_red_), CST_5b(m->green_to_blue_), const __m128i mults_b2 = MK_CST_16(CST_5b(m->red_to_blue_), 0);
CST_5b(m->green_to_red_), CST_5b(m->green_to_blue_),
CST_5b(m->green_to_red_), CST_5b(m->green_to_blue_));
const __m128i mults_b2 = _mm_set_epi16(
CST_5b(m->red_to_blue_), 0, CST_5b(m->red_to_blue_), 0,
CST_5b(m->red_to_blue_), 0, CST_5b(m->red_to_blue_), 0);
const __m128i mask_ag = _mm_set1_epi32(0xff00ff00); // alpha-green masks const __m128i mask_ag = _mm_set1_epi32(0xff00ff00); // alpha-green masks
const __m128i mask_rb = _mm_set1_epi32(0x00ff00ff); // red-blue masks const __m128i mask_rb = _mm_set1_epi32(0x00ff00ff); // red-blue masks
int i; int i;
@ -85,12 +83,8 @@ static void CollectColorBlueTransforms_SSE2(const uint32_t* argb, int stride,
int tile_width, int tile_height, int tile_width, int tile_height,
int green_to_blue, int red_to_blue, int green_to_blue, int red_to_blue,
int histo[]) { int histo[]) {
const __m128i mults_r = _mm_set_epi16( const __m128i mults_r = MK_CST_16(CST_5b(red_to_blue), 0);
CST_5b(red_to_blue), 0, CST_5b(red_to_blue), 0, const __m128i mults_g = MK_CST_16(0, CST_5b(green_to_blue));
CST_5b(red_to_blue), 0, CST_5b(red_to_blue), 0);
const __m128i mults_g = _mm_set_epi16(
0, CST_5b(green_to_blue), 0, CST_5b(green_to_blue),
0, CST_5b(green_to_blue), 0, CST_5b(green_to_blue));
const __m128i mask_g = _mm_set1_epi32(0x00ff00); // green mask const __m128i mask_g = _mm_set1_epi32(0x00ff00); // green mask
const __m128i mask_b = _mm_set1_epi32(0x0000ff); // blue mask const __m128i mask_b = _mm_set1_epi32(0x0000ff); // blue mask
int y; int y;
@ -135,9 +129,7 @@ static void CollectColorBlueTransforms_SSE2(const uint32_t* argb, int stride,
static void CollectColorRedTransforms_SSE2(const uint32_t* argb, int stride, static void CollectColorRedTransforms_SSE2(const uint32_t* argb, int stride,
int tile_width, int tile_height, int tile_width, int tile_height,
int green_to_red, int histo[]) { int green_to_red, int histo[]) {
const __m128i mults_g = _mm_set_epi16( const __m128i mults_g = MK_CST_16(0, CST_5b(green_to_red));
0, CST_5b(green_to_red), 0, CST_5b(green_to_red),
0, CST_5b(green_to_red), 0, CST_5b(green_to_red));
const __m128i mask_g = _mm_set1_epi32(0x00ff00); // green mask const __m128i mask_g = _mm_set1_epi32(0x00ff00); // green mask
const __m128i mask = _mm_set1_epi32(0xff); const __m128i mask = _mm_set1_epi32(0xff);
@ -174,15 +166,17 @@ static void CollectColorRedTransforms_SSE2(const uint32_t* argb, int stride,
} }
} }
#undef SPAN #undef SPAN
#undef MK_CST_16
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// 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).
#define LINE_SIZE 16 // 8 or 16 #define LINE_SIZE 16 // 8 or 16
static void AddVector_SSE2(const uint32_t* a, const uint32_t* b, uint32_t* out, static void AddVector_SSE2(const uint32_t* a, const uint32_t* b, uint32_t* out,
int size) { int size) {
int i; int i;
assert(size % LINE_SIZE == 0); for (i = 0; i + LINE_SIZE <= size; i += LINE_SIZE) {
for (i = 0; i < size; i += LINE_SIZE) {
const __m128i a0 = _mm_loadu_si128((const __m128i*)&a[i + 0]); const __m128i a0 = _mm_loadu_si128((const __m128i*)&a[i + 0]);
const __m128i a1 = _mm_loadu_si128((const __m128i*)&a[i + 4]); const __m128i a1 = _mm_loadu_si128((const __m128i*)&a[i + 4]);
#if (LINE_SIZE == 16) #if (LINE_SIZE == 16)
@ -202,12 +196,14 @@ static void AddVector_SSE2(const uint32_t* a, const uint32_t* b, uint32_t* out,
_mm_storeu_si128((__m128i*)&out[i + 12], _mm_add_epi32(a3, b3)); _mm_storeu_si128((__m128i*)&out[i + 12], _mm_add_epi32(a3, b3));
#endif #endif
} }
for (; i < size; ++i) {
out[i] = a[i] + b[i];
}
} }
static void AddVectorEq_SSE2(const uint32_t* a, uint32_t* out, int size) { static void AddVectorEq_SSE2(const uint32_t* a, uint32_t* out, int size) {
int i; int i;
assert(size % LINE_SIZE == 0); for (i = 0; i + LINE_SIZE <= size; i += LINE_SIZE) {
for (i = 0; i < size; i += LINE_SIZE) {
const __m128i a0 = _mm_loadu_si128((const __m128i*)&a[i + 0]); const __m128i a0 = _mm_loadu_si128((const __m128i*)&a[i + 0]);
const __m128i a1 = _mm_loadu_si128((const __m128i*)&a[i + 4]); const __m128i a1 = _mm_loadu_si128((const __m128i*)&a[i + 4]);
#if (LINE_SIZE == 16) #if (LINE_SIZE == 16)
@ -227,36 +223,12 @@ static void AddVectorEq_SSE2(const uint32_t* a, uint32_t* out, int size) {
_mm_storeu_si128((__m128i*)&out[i + 12], _mm_add_epi32(a3, b3)); _mm_storeu_si128((__m128i*)&out[i + 12], _mm_add_epi32(a3, b3));
#endif #endif
} }
for (; i < size; ++i) {
out[i] += a[i];
}
} }
#undef LINE_SIZE #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_SSE2(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_SSE2(a->literal_, b->literal_, out->literal_, NUM_LITERAL_CODES);
AddVector_SSE2(a->red_, b->red_, out->red_, NUM_LITERAL_CODES);
AddVector_SSE2(a->blue_, b->blue_, out->blue_, NUM_LITERAL_CODES);
AddVector_SSE2(a->alpha_, b->alpha_, out->alpha_, NUM_LITERAL_CODES);
} else {
AddVectorEq_SSE2(a->literal_, out->literal_, NUM_LITERAL_CODES);
AddVectorEq_SSE2(a->red_, out->red_, NUM_LITERAL_CODES);
AddVectorEq_SSE2(a->blue_, out->blue_, NUM_LITERAL_CODES);
AddVectorEq_SSE2(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];
}
}
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// Entropy // Entropy
@ -682,7 +654,8 @@ WEBP_TSAN_IGNORE_FUNCTION void VP8LEncDspInitSSE2(void) {
VP8LTransformColor = TransformColor_SSE2; VP8LTransformColor = TransformColor_SSE2;
VP8LCollectColorBlueTransforms = CollectColorBlueTransforms_SSE2; VP8LCollectColorBlueTransforms = CollectColorBlueTransforms_SSE2;
VP8LCollectColorRedTransforms = CollectColorRedTransforms_SSE2; VP8LCollectColorRedTransforms = CollectColorRedTransforms_SSE2;
VP8LHistogramAdd = HistogramAdd_SSE2; VP8LAddVector = AddVector_SSE2;
VP8LAddVectorEq = AddVectorEq_SSE2;
VP8LCombinedShannonEntropy = CombinedShannonEntropy_SSE2; VP8LCombinedShannonEntropy = CombinedShannonEntropy_SSE2;
VP8LVectorMismatch = VectorMismatch_SSE2; VP8LVectorMismatch = VectorMismatch_SSE2;
VP8LBundleColorMap = BundleColorMap_SSE2; VP8LBundleColorMap = BundleColorMap_SSE2;

View File

@ -18,6 +18,9 @@
#include <smmintrin.h> #include <smmintrin.h>
#include "src/dsp/lossless.h" #include "src/dsp/lossless.h"
// For sign-extended multiplying constants, pre-shifted by 5:
#define CST_5b(X) (((int16_t)((uint16_t)(X) << 8)) >> 5)
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// Subtract-Green Transform // Subtract-Green Transform
@ -38,6 +41,95 @@ static void SubtractGreenFromBlueAndRed_SSE41(uint32_t* argb_data,
} }
} }
//------------------------------------------------------------------------------
// Color Transform
#define SPAN 8
static void CollectColorBlueTransforms_SSE41(const uint32_t* argb, int stride,
int tile_width, int tile_height,
int green_to_blue, int red_to_blue,
int histo[]) {
const __m128i mults_r = _mm_set1_epi16(CST_5b(red_to_blue));
const __m128i mults_g = _mm_set1_epi16(CST_5b(green_to_blue));
const __m128i mask_g = _mm_set1_epi16(0xff00); // green mask
const __m128i mask_gb = _mm_set1_epi32(0xffff); // green/blue mask
const __m128i mask_b = _mm_set1_epi16(0x00ff); // blue mask
const __m128i shuffler_lo = _mm_setr_epi8(-1, 2, -1, 6, -1, 10, -1, 14, -1,
-1, -1, -1, -1, -1, -1, -1);
const __m128i shuffler_hi = _mm_setr_epi8(-1, -1, -1, -1, -1, -1, -1, -1, -1,
2, -1, 6, -1, 10, -1, 14);
int y;
for (y = 0; y < tile_height; ++y) {
const uint32_t* const src = argb + y * stride;
int i, x;
for (x = 0; x + SPAN <= tile_width; x += SPAN) {
uint16_t values[SPAN];
const __m128i in0 = _mm_loadu_si128((__m128i*)&src[x + 0]);
const __m128i in1 = _mm_loadu_si128((__m128i*)&src[x + SPAN / 2]);
const __m128i r0 = _mm_shuffle_epi8(in0, shuffler_lo);
const __m128i r1 = _mm_shuffle_epi8(in1, shuffler_hi);
const __m128i r = _mm_or_si128(r0, r1); // r 0
const __m128i gb0 = _mm_and_si128(in0, mask_gb);
const __m128i gb1 = _mm_and_si128(in1, mask_gb);
const __m128i gb = _mm_packus_epi32(gb0, gb1); // g b
const __m128i g = _mm_and_si128(gb, mask_g); // g 0
const __m128i A = _mm_mulhi_epi16(r, mults_r); // x dbr
const __m128i B = _mm_mulhi_epi16(g, mults_g); // x dbg
const __m128i C = _mm_sub_epi8(gb, B); // x b'
const __m128i D = _mm_sub_epi8(C, A); // x b''
const __m128i E = _mm_and_si128(D, mask_b); // 0 b''
_mm_storeu_si128((__m128i*)values, E);
for (i = 0; i < SPAN; ++i) ++histo[values[i]];
}
}
{
const int left_over = tile_width & (SPAN - 1);
if (left_over > 0) {
VP8LCollectColorBlueTransforms_C(argb + tile_width - left_over, stride,
left_over, tile_height,
green_to_blue, red_to_blue, histo);
}
}
}
static void CollectColorRedTransforms_SSE41(const uint32_t* argb, int stride,
int tile_width, int tile_height,
int green_to_red, int histo[]) {
const __m128i mults_g = _mm_set1_epi16(CST_5b(green_to_red));
const __m128i mask_g = _mm_set1_epi32(0x00ff00); // green mask
const __m128i mask = _mm_set1_epi16(0xff);
int y;
for (y = 0; y < tile_height; ++y) {
const uint32_t* const src = argb + y * stride;
int i, x;
for (x = 0; x + SPAN <= tile_width; x += SPAN) {
uint16_t values[SPAN];
const __m128i in0 = _mm_loadu_si128((__m128i*)&src[x + 0]);
const __m128i in1 = _mm_loadu_si128((__m128i*)&src[x + SPAN / 2]);
const __m128i g0 = _mm_and_si128(in0, mask_g); // 0 0 | g 0
const __m128i g1 = _mm_and_si128(in1, mask_g);
const __m128i g = _mm_packus_epi32(g0, g1); // g 0
const __m128i A0 = _mm_srli_epi32(in0, 16); // 0 0 | x r
const __m128i A1 = _mm_srli_epi32(in1, 16);
const __m128i A = _mm_packus_epi32(A0, A1); // x r
const __m128i B = _mm_mulhi_epi16(g, mults_g); // x dr
const __m128i C = _mm_sub_epi8(A, B); // x r'
const __m128i D = _mm_and_si128(C, mask); // 0 r'
_mm_storeu_si128((__m128i*)values, D);
for (i = 0; i < SPAN; ++i) ++histo[values[i]];
}
}
{
const int left_over = tile_width & (SPAN - 1);
if (left_over > 0) {
VP8LCollectColorRedTransforms_C(argb + tile_width - left_over, stride,
left_over, tile_height, green_to_red,
histo);
}
}
}
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// Entry point // Entry point
@ -45,6 +137,8 @@ extern void VP8LEncDspInitSSE41(void);
WEBP_TSAN_IGNORE_FUNCTION void VP8LEncDspInitSSE41(void) { WEBP_TSAN_IGNORE_FUNCTION void VP8LEncDspInitSSE41(void) {
VP8LSubtractGreenFromBlueAndRed = SubtractGreenFromBlueAndRed_SSE41; VP8LSubtractGreenFromBlueAndRed = SubtractGreenFromBlueAndRed_SSE41;
VP8LCollectColorBlueTransforms = CollectColorBlueTransforms_SSE41;
VP8LCollectColorRedTransforms = CollectColorRedTransforms_SSE41;
} }
#else // !WEBP_USE_SSE41 #else // !WEBP_USE_SSE41

View File

@ -453,14 +453,11 @@ static void TransformColorInverse_SSE2(const VP8LMultipliers* const m,
int num_pixels, uint32_t* dst) { int num_pixels, uint32_t* dst) {
// sign-extended multiplying constants, pre-shifted by 5. // sign-extended multiplying constants, pre-shifted by 5.
#define CST(X) (((int16_t)(m->X << 8)) >> 5) // sign-extend #define CST(X) (((int16_t)(m->X << 8)) >> 5) // sign-extend
const __m128i mults_rb = _mm_set_epi16( #define MK_CST_16(HI, LO) \
CST(green_to_red_), CST(green_to_blue_), _mm_set1_epi32((int)(((uint32_t)(HI) << 16) | ((LO) & 0xffff)))
CST(green_to_red_), CST(green_to_blue_), const __m128i mults_rb = MK_CST_16(CST(green_to_red_), CST(green_to_blue_));
CST(green_to_red_), CST(green_to_blue_), const __m128i mults_b2 = MK_CST_16(CST(red_to_blue_), 0);
CST(green_to_red_), CST(green_to_blue_)); #undef MK_CST_16
const __m128i mults_b2 = _mm_set_epi16(
CST(red_to_blue_), 0, CST(red_to_blue_), 0,
CST(red_to_blue_), 0, CST(red_to_blue_), 0);
#undef CST #undef CST
const __m128i mask_ag = _mm_set1_epi32(0xff00ff00); // alpha-green masks const __m128i mask_ag = _mm_set1_epi32(0xff00ff00); // alpha-green masks
int i; int i;
@ -503,11 +500,11 @@ static void ConvertBGRAToRGB_SSE2(const uint32_t* src, int num_pixels,
__m128i in5 = _mm_loadu_si128(in + 5); __m128i in5 = _mm_loadu_si128(in + 5);
__m128i in6 = _mm_loadu_si128(in + 6); __m128i in6 = _mm_loadu_si128(in + 6);
__m128i in7 = _mm_loadu_si128(in + 7); __m128i in7 = _mm_loadu_si128(in + 7);
VP8L32bToPlanar(&in0, &in1, &in2, &in3); VP8L32bToPlanar_SSE2(&in0, &in1, &in2, &in3);
VP8L32bToPlanar(&in4, &in5, &in6, &in7); VP8L32bToPlanar_SSE2(&in4, &in5, &in6, &in7);
// At this points, in1/in5 contains red only, in2/in6 green only ... // At this points, in1/in5 contains red only, in2/in6 green only ...
// Pack the colors in 24b RGB. // Pack the colors in 24b RGB.
VP8PlanarTo24b(&in1, &in5, &in2, &in6, &in3, &in7); VP8PlanarTo24b_SSE2(&in1, &in5, &in2, &in6, &in3, &in7);
_mm_storeu_si128(out + 0, in1); _mm_storeu_si128(out + 0, in1);
_mm_storeu_si128(out + 1, in5); _mm_storeu_si128(out + 1, in5);
_mm_storeu_si128(out + 2, in2); _mm_storeu_si128(out + 2, in2);

View File

@ -1389,4 +1389,4 @@ static WEBP_INLINE uint32_t func_hadd_uh_u32(v8u16 in) {
} while (0) } while (0)
#define AVER_UB2_UB(...) AVER_UB2(v16u8, __VA_ARGS__) #define AVER_UB2_UB(...) AVER_UB2(v16u8, __VA_ARGS__)
#endif /* WEBP_DSP_MSA_MACRO_H_ */ #endif // WEBP_DSP_MSA_MACRO_H_

View File

@ -21,6 +21,7 @@
#define ROUNDER (WEBP_RESCALER_ONE >> 1) #define ROUNDER (WEBP_RESCALER_ONE >> 1)
#define MULT_FIX(x, y) (((uint64_t)(x) * (y) + ROUNDER) >> WEBP_RESCALER_RFIX) #define MULT_FIX(x, y) (((uint64_t)(x) * (y) + ROUNDER) >> WEBP_RESCALER_RFIX)
#define MULT_FIX_FLOOR(x, y) (((uint64_t)(x) * (y)) >> WEBP_RESCALER_RFIX)
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// Row import // Row import
@ -138,7 +139,7 @@ void WebPRescalerExportRowShrink_C(WebPRescaler* const wrk) {
if (yscale) { if (yscale) {
for (x_out = 0; x_out < x_out_max; ++x_out) { for (x_out = 0; x_out < x_out_max; ++x_out) {
const uint32_t frac = (uint32_t)MULT_FIX(frow[x_out], yscale); const uint32_t frac = (uint32_t)MULT_FIX(frow[x_out], yscale);
const int v = (int)MULT_FIX(irow[x_out] - frac, wrk->fxy_scale); const int v = (int)MULT_FIX_FLOOR(irow[x_out] - frac, wrk->fxy_scale);
assert(v >= 0 && v <= 255); assert(v >= 0 && v <= 255);
dst[x_out] = v; dst[x_out] = v;
irow[x_out] = frac; // new fractional start irow[x_out] = frac; // new fractional start
@ -153,6 +154,7 @@ void WebPRescalerExportRowShrink_C(WebPRescaler* const wrk) {
} }
} }
#undef MULT_FIX_FLOOR
#undef MULT_FIX #undef MULT_FIX
#undef ROUNDER #undef ROUNDER
@ -204,11 +206,7 @@ extern void WebPRescalerDspInitMIPSdspR2(void);
extern void WebPRescalerDspInitMSA(void); extern void WebPRescalerDspInitMSA(void);
extern void WebPRescalerDspInitNEON(void); extern void WebPRescalerDspInitNEON(void);
static volatile VP8CPUInfo rescaler_last_cpuinfo_used = WEBP_DSP_INIT_FUNC(WebPRescalerDspInit) {
(VP8CPUInfo)&rescaler_last_cpuinfo_used;
WEBP_TSAN_IGNORE_FUNCTION void WebPRescalerDspInit(void) {
if (rescaler_last_cpuinfo_used == VP8GetCPUInfo) return;
#if !defined(WEBP_REDUCE_SIZE) #if !defined(WEBP_REDUCE_SIZE)
#if !WEBP_NEON_OMIT_C_CODE #if !WEBP_NEON_OMIT_C_CODE
WebPRescalerExportRowExpand = WebPRescalerExportRowExpand_C; WebPRescalerExportRowExpand = WebPRescalerExportRowExpand_C;
@ -253,5 +251,4 @@ WEBP_TSAN_IGNORE_FUNCTION void WebPRescalerDspInit(void) {
assert(WebPRescalerImportRowExpand != NULL); assert(WebPRescalerImportRowExpand != NULL);
assert(WebPRescalerImportRowShrink != NULL); assert(WebPRescalerImportRowShrink != NULL);
#endif // WEBP_REDUCE_SIZE #endif // WEBP_REDUCE_SIZE
rescaler_last_cpuinfo_used = VP8GetCPUInfo;
} }

View File

@ -209,6 +209,7 @@ static void ExportRowExpand_MIPS32(WebPRescaler* const wrk) {
} }
} }
#if 0 // disabled for now. TODO(skal): make match the C-code
static void ExportRowShrink_MIPS32(WebPRescaler* const wrk) { static void ExportRowShrink_MIPS32(WebPRescaler* const wrk) {
const int x_out_max = wrk->dst_width * wrk->num_channels; const int x_out_max = wrk->dst_width * wrk->num_channels;
uint8_t* dst = wrk->dst; uint8_t* dst = wrk->dst;
@ -273,6 +274,7 @@ static void ExportRowShrink_MIPS32(WebPRescaler* const wrk) {
); );
} }
} }
#endif // 0
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// Entry point // Entry point
@ -283,7 +285,7 @@ WEBP_TSAN_IGNORE_FUNCTION void WebPRescalerDspInitMIPS32(void) {
WebPRescalerImportRowExpand = ImportRowExpand_MIPS32; WebPRescalerImportRowExpand = ImportRowExpand_MIPS32;
WebPRescalerImportRowShrink = ImportRowShrink_MIPS32; WebPRescalerImportRowShrink = ImportRowShrink_MIPS32;
WebPRescalerExportRowExpand = ExportRowExpand_MIPS32; WebPRescalerExportRowExpand = ExportRowExpand_MIPS32;
WebPRescalerExportRowShrink = ExportRowShrink_MIPS32; // WebPRescalerExportRowShrink = ExportRowShrink_MIPS32;
} }
#else // !WEBP_USE_MIPS32 #else // !WEBP_USE_MIPS32

View File

@ -20,10 +20,12 @@
#define ROUNDER (WEBP_RESCALER_ONE >> 1) #define ROUNDER (WEBP_RESCALER_ONE >> 1)
#define MULT_FIX(x, y) (((uint64_t)(x) * (y) + ROUNDER) >> WEBP_RESCALER_RFIX) #define MULT_FIX(x, y) (((uint64_t)(x) * (y) + ROUNDER) >> WEBP_RESCALER_RFIX)
#define MULT_FIX_FLOOR(x, y) (((uint64_t)(x) * (y)) >> WEBP_RESCALER_RFIX)
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// Row export // Row export
#if 0 // disabled for now. TODO(skal): make match the C-code
static void ExportRowShrink_MIPSdspR2(WebPRescaler* const wrk) { static void ExportRowShrink_MIPSdspR2(WebPRescaler* const wrk) {
int i; int i;
const int x_out_max = wrk->dst_width * wrk->num_channels; const int x_out_max = wrk->dst_width * wrk->num_channels;
@ -106,7 +108,7 @@ static void ExportRowShrink_MIPSdspR2(WebPRescaler* const wrk) {
} }
for (i = 0; i < (x_out_max & 0x3); ++i) { for (i = 0; i < (x_out_max & 0x3); ++i) {
const uint32_t frac = (uint32_t)MULT_FIX(*frow++, yscale); const uint32_t frac = (uint32_t)MULT_FIX(*frow++, yscale);
const int v = (int)MULT_FIX(*irow - frac, wrk->fxy_scale); const int v = (int)MULT_FIX_FLOOR(*irow - frac, wrk->fxy_scale);
assert(v >= 0 && v <= 255); assert(v >= 0 && v <= 255);
*dst++ = v; *dst++ = v;
*irow++ = frac; // new fractional start *irow++ = frac; // new fractional start
@ -154,13 +156,14 @@ static void ExportRowShrink_MIPSdspR2(WebPRescaler* const wrk) {
); );
} }
for (i = 0; i < (x_out_max & 0x3); ++i) { for (i = 0; i < (x_out_max & 0x3); ++i) {
const int v = (int)MULT_FIX(*irow, wrk->fxy_scale); const int v = (int)MULT_FIX_FLOOR(*irow, wrk->fxy_scale);
assert(v >= 0 && v <= 255); assert(v >= 0 && v <= 255);
*dst++ = v; *dst++ = v;
*irow++ = 0; *irow++ = 0;
} }
} }
} }
#endif // 0
static void ExportRowExpand_MIPSdspR2(WebPRescaler* const wrk) { static void ExportRowExpand_MIPSdspR2(WebPRescaler* const wrk) {
int i; int i;
@ -294,6 +297,7 @@ static void ExportRowExpand_MIPSdspR2(WebPRescaler* const wrk) {
} }
} }
#undef MULT_FIX_FLOOR
#undef MULT_FIX #undef MULT_FIX
#undef ROUNDER #undef ROUNDER
@ -304,7 +308,7 @@ extern void WebPRescalerDspInitMIPSdspR2(void);
WEBP_TSAN_IGNORE_FUNCTION void WebPRescalerDspInitMIPSdspR2(void) { WEBP_TSAN_IGNORE_FUNCTION void WebPRescalerDspInitMIPSdspR2(void) {
WebPRescalerExportRowExpand = ExportRowExpand_MIPSdspR2; WebPRescalerExportRowExpand = ExportRowExpand_MIPSdspR2;
WebPRescalerExportRowShrink = ExportRowShrink_MIPSdspR2; // WebPRescalerExportRowShrink = ExportRowShrink_MIPSdspR2;
} }
#else // !WEBP_USE_MIPS_DSP_R2 #else // !WEBP_USE_MIPS_DSP_R2

View File

@ -22,6 +22,7 @@
#define ROUNDER (WEBP_RESCALER_ONE >> 1) #define ROUNDER (WEBP_RESCALER_ONE >> 1)
#define MULT_FIX(x, y) (((uint64_t)(x) * (y) + ROUNDER) >> WEBP_RESCALER_RFIX) #define MULT_FIX(x, y) (((uint64_t)(x) * (y) + ROUNDER) >> WEBP_RESCALER_RFIX)
#define MULT_FIX_FLOOR(x, y) (((uint64_t)(x) * (y)) >> WEBP_RESCALER_RFIX)
#define CALC_MULT_FIX_16(in0, in1, in2, in3, scale, shift, dst) do { \ #define CALC_MULT_FIX_16(in0, in1, in2, in3, scale, shift, dst) do { \
v4u32 tmp0, tmp1, tmp2, tmp3; \ v4u32 tmp0, tmp1, tmp2, tmp3; \
@ -262,6 +263,7 @@ static void RescalerExportRowExpand_MIPSdspR2(WebPRescaler* const wrk) {
} }
} }
#if 0 // disabled for now. TODO(skal): make match the C-code
static WEBP_INLINE void ExportRowShrink_0(const uint32_t* frow, uint32_t* irow, static WEBP_INLINE void ExportRowShrink_0(const uint32_t* frow, uint32_t* irow,
uint8_t* dst, int length, uint8_t* dst, int length,
const uint32_t yscale, const uint32_t yscale,
@ -341,7 +343,7 @@ static WEBP_INLINE void ExportRowShrink_0(const uint32_t* frow, uint32_t* irow,
} }
for (x_out = 0; x_out < length; ++x_out) { for (x_out = 0; x_out < length; ++x_out) {
const uint32_t frac = (uint32_t)MULT_FIX(frow[x_out], yscale); const uint32_t frac = (uint32_t)MULT_FIX(frow[x_out], yscale);
const int v = (int)MULT_FIX(irow[x_out] - frac, wrk->fxy_scale); const int v = (int)MULT_FIX_FLOOR(irow[x_out] - frac, wrk->fxy_scale);
assert(v >= 0 && v <= 255); assert(v >= 0 && v <= 255);
dst[x_out] = v; dst[x_out] = v;
irow[x_out] = frac; irow[x_out] = frac;
@ -426,6 +428,7 @@ static void RescalerExportRowShrink_MIPSdspR2(WebPRescaler* const wrk) {
ExportRowShrink_1(irow, dst, x_out_max, wrk); ExportRowShrink_1(irow, dst, x_out_max, wrk);
} }
} }
#endif // 0
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// Entry point // Entry point
@ -434,7 +437,7 @@ extern void WebPRescalerDspInitMSA(void);
WEBP_TSAN_IGNORE_FUNCTION void WebPRescalerDspInitMSA(void) { WEBP_TSAN_IGNORE_FUNCTION void WebPRescalerDspInitMSA(void) {
WebPRescalerExportRowExpand = RescalerExportRowExpand_MIPSdspR2; WebPRescalerExportRowExpand = RescalerExportRowExpand_MIPSdspR2;
WebPRescalerExportRowShrink = RescalerExportRowShrink_MIPSdspR2; // WebPRescalerExportRowShrink = RescalerExportRowShrink_MIPSdspR2;
} }
#else // !WEBP_USE_MSA #else // !WEBP_USE_MSA

View File

@ -22,6 +22,7 @@
#define ROUNDER (WEBP_RESCALER_ONE >> 1) #define ROUNDER (WEBP_RESCALER_ONE >> 1)
#define MULT_FIX_C(x, y) (((uint64_t)(x) * (y) + ROUNDER) >> WEBP_RESCALER_RFIX) #define MULT_FIX_C(x, y) (((uint64_t)(x) * (y) + ROUNDER) >> WEBP_RESCALER_RFIX)
#define MULT_FIX_FLOOR_C(x, y) (((uint64_t)(x) * (y)) >> WEBP_RESCALER_RFIX)
#define LOAD_32x4(SRC, DST) const uint32x4_t DST = vld1q_u32((SRC)) #define LOAD_32x4(SRC, DST) const uint32x4_t DST = vld1q_u32((SRC))
#define LOAD_32x8(SRC, DST0, DST1) \ #define LOAD_32x8(SRC, DST0, DST1) \
@ -35,8 +36,11 @@
#if (WEBP_RESCALER_RFIX == 32) #if (WEBP_RESCALER_RFIX == 32)
#define MAKE_HALF_CST(C) vdupq_n_s32((int32_t)((C) >> 1)) #define MAKE_HALF_CST(C) vdupq_n_s32((int32_t)((C) >> 1))
#define MULT_FIX(A, B) /* note: B is actualy scale>>1. See MAKE_HALF_CST */ \ // note: B is actualy scale>>1. See MAKE_HALF_CST
#define MULT_FIX(A, B) \
vreinterpretq_u32_s32(vqrdmulhq_s32(vreinterpretq_s32_u32((A)), (B))) vreinterpretq_u32_s32(vqrdmulhq_s32(vreinterpretq_s32_u32((A)), (B)))
#define MULT_FIX_FLOOR(A, B) \
vreinterpretq_u32_s32(vqdmulhq_s32(vreinterpretq_s32_u32((A)), (B)))
#else #else
#error "MULT_FIX/WEBP_RESCALER_RFIX need some more work" #error "MULT_FIX/WEBP_RESCALER_RFIX need some more work"
#endif #endif
@ -135,8 +139,8 @@ static void RescalerExportRowShrink_NEON(WebPRescaler* const wrk) {
const uint32x4_t A1 = MULT_FIX(in1, yscale_half); const uint32x4_t A1 = MULT_FIX(in1, yscale_half);
const uint32x4_t B0 = vqsubq_u32(in2, A0); const uint32x4_t B0 = vqsubq_u32(in2, A0);
const uint32x4_t B1 = vqsubq_u32(in3, A1); const uint32x4_t B1 = vqsubq_u32(in3, A1);
const uint32x4_t C0 = MULT_FIX(B0, fxy_scale_half); const uint32x4_t C0 = MULT_FIX_FLOOR(B0, fxy_scale_half);
const uint32x4_t C1 = MULT_FIX(B1, fxy_scale_half); const uint32x4_t C1 = MULT_FIX_FLOOR(B1, fxy_scale_half);
const uint16x4_t D0 = vmovn_u32(C0); const uint16x4_t D0 = vmovn_u32(C0);
const uint16x4_t D1 = vmovn_u32(C1); const uint16x4_t D1 = vmovn_u32(C1);
const uint8x8_t E = vmovn_u16(vcombine_u16(D0, D1)); const uint8x8_t E = vmovn_u16(vcombine_u16(D0, D1));
@ -145,7 +149,7 @@ static void RescalerExportRowShrink_NEON(WebPRescaler* const wrk) {
} }
for (; x_out < x_out_max; ++x_out) { for (; x_out < x_out_max; ++x_out) {
const uint32_t frac = (uint32_t)MULT_FIX_C(frow[x_out], yscale); const uint32_t frac = (uint32_t)MULT_FIX_C(frow[x_out], yscale);
const int v = (int)MULT_FIX_C(irow[x_out] - frac, wrk->fxy_scale); const int v = (int)MULT_FIX_FLOOR_C(irow[x_out] - frac, fxy_scale);
assert(v >= 0 && v <= 255); assert(v >= 0 && v <= 255);
dst[x_out] = v; dst[x_out] = v;
irow[x_out] = frac; // new fractional start irow[x_out] = frac; // new fractional start
@ -170,6 +174,12 @@ static void RescalerExportRowShrink_NEON(WebPRescaler* const wrk) {
} }
} }
#undef MULT_FIX_FLOOR_C
#undef MULT_FIX_C
#undef MULT_FIX_FLOOR
#undef MULT_FIX
#undef ROUNDER
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
extern void WebPRescalerDspInitNEON(void); extern void WebPRescalerDspInitNEON(void);

View File

@ -25,6 +25,7 @@
#define ROUNDER (WEBP_RESCALER_ONE >> 1) #define ROUNDER (WEBP_RESCALER_ONE >> 1)
#define MULT_FIX(x, y) (((uint64_t)(x) * (y) + ROUNDER) >> WEBP_RESCALER_RFIX) #define MULT_FIX(x, y) (((uint64_t)(x) * (y) + ROUNDER) >> WEBP_RESCALER_RFIX)
#define MULT_FIX_FLOOR(x, y) (((uint64_t)(x) * (y)) >> WEBP_RESCALER_RFIX)
// input: 8 bytes ABCDEFGH -> output: A0E0B0F0C0G0D0H0 // input: 8 bytes ABCDEFGH -> output: A0E0B0F0C0G0D0H0
static void LoadTwoPixels_SSE2(const uint8_t* const src, __m128i* out) { static void LoadTwoPixels_SSE2(const uint8_t* const src, __m128i* out) {
@ -36,7 +37,7 @@ static void LoadTwoPixels_SSE2(const uint8_t* const src, __m128i* out) {
} }
// input: 8 bytes ABCDEFGH -> output: A0B0C0D0E0F0G0H0 // input: 8 bytes ABCDEFGH -> output: A0B0C0D0E0F0G0H0
static void LoadHeightPixels_SSE2(const uint8_t* const src, __m128i* out) { static void LoadEightPixels_SSE2(const uint8_t* const src, __m128i* out) {
const __m128i zero = _mm_setzero_si128(); const __m128i zero = _mm_setzero_si128();
const __m128i A = _mm_loadl_epi64((const __m128i*)(src)); // ABCDEFGH const __m128i A = _mm_loadl_epi64((const __m128i*)(src)); // ABCDEFGH
*out = _mm_unpacklo_epi8(A, zero); *out = _mm_unpacklo_epi8(A, zero);
@ -50,13 +51,15 @@ static void RescalerImportRowExpand_SSE2(WebPRescaler* const wrk,
int accum = x_add; int accum = x_add;
__m128i cur_pixels; __m128i cur_pixels;
// SSE2 implementation only works with 16b signed arithmetic at max.
if (wrk->src_width < 8 || accum >= (1 << 15)) {
WebPRescalerImportRowExpand_C(wrk, src);
return;
}
assert(!WebPRescalerInputDone(wrk)); assert(!WebPRescalerInputDone(wrk));
assert(wrk->x_expand); assert(wrk->x_expand);
if (wrk->num_channels == 4) { if (wrk->num_channels == 4) {
if (wrk->src_width < 2) {
WebPRescalerImportRowExpand_C(wrk, src);
return;
}
LoadTwoPixels_SSE2(src, &cur_pixels); LoadTwoPixels_SSE2(src, &cur_pixels);
src += 4; src += 4;
while (1) { while (1) {
@ -75,11 +78,7 @@ static void RescalerImportRowExpand_SSE2(WebPRescaler* const wrk,
} else { } else {
int left; int left;
const uint8_t* const src_limit = src + wrk->src_width - 8; const uint8_t* const src_limit = src + wrk->src_width - 8;
if (wrk->src_width < 8) { LoadEightPixels_SSE2(src, &cur_pixels);
WebPRescalerImportRowExpand_C(wrk, src);
return;
}
LoadHeightPixels_SSE2(src, &cur_pixels);
src += 7; src += 7;
left = 7; left = 7;
while (1) { while (1) {
@ -94,7 +93,7 @@ static void RescalerImportRowExpand_SSE2(WebPRescaler* const wrk,
if (--left) { if (--left) {
cur_pixels = _mm_srli_si128(cur_pixels, 2); cur_pixels = _mm_srli_si128(cur_pixels, 2);
} else if (src <= src_limit) { } else if (src <= src_limit) {
LoadHeightPixels_SSE2(src, &cur_pixels); LoadEightPixels_SSE2(src, &cur_pixels);
src += 7; src += 7;
left = 7; left = 7;
} else { // tail } else { // tail
@ -226,6 +225,35 @@ static WEBP_INLINE void ProcessRow_SSE2(const __m128i* const A0,
_mm_storel_epi64((__m128i*)dst, G); _mm_storel_epi64((__m128i*)dst, G);
} }
static WEBP_INLINE void ProcessRow_Floor_SSE2(const __m128i* const A0,
const __m128i* const A1,
const __m128i* const A2,
const __m128i* const A3,
const __m128i* const mult,
uint8_t* const dst) {
const __m128i mask = _mm_set_epi32(0xffffffffu, 0, 0xffffffffu, 0);
const __m128i B0 = _mm_mul_epu32(*A0, *mult);
const __m128i B1 = _mm_mul_epu32(*A1, *mult);
const __m128i B2 = _mm_mul_epu32(*A2, *mult);
const __m128i B3 = _mm_mul_epu32(*A3, *mult);
const __m128i D0 = _mm_srli_epi64(B0, WEBP_RESCALER_RFIX);
const __m128i D1 = _mm_srli_epi64(B1, WEBP_RESCALER_RFIX);
#if (WEBP_RESCALER_RFIX < 32)
const __m128i D2 =
_mm_and_si128(_mm_slli_epi64(B2, 32 - WEBP_RESCALER_RFIX), mask);
const __m128i D3 =
_mm_and_si128(_mm_slli_epi64(B3, 32 - WEBP_RESCALER_RFIX), mask);
#else
const __m128i D2 = _mm_and_si128(B2, mask);
const __m128i D3 = _mm_and_si128(B3, mask);
#endif
const __m128i E0 = _mm_or_si128(D0, D2);
const __m128i E1 = _mm_or_si128(D1, D3);
const __m128i F = _mm_packs_epi32(E0, E1);
const __m128i G = _mm_packus_epi16(F, F);
_mm_storel_epi64((__m128i*)dst, G);
}
static void RescalerExportRowExpand_SSE2(WebPRescaler* const wrk) { static void RescalerExportRowExpand_SSE2(WebPRescaler* const wrk) {
int x_out; int x_out;
uint8_t* const dst = wrk->dst; uint8_t* const dst = wrk->dst;
@ -324,12 +352,12 @@ static void RescalerExportRowShrink_SSE2(WebPRescaler* const wrk) {
const __m128i G1 = _mm_or_si128(D1, F3); const __m128i G1 = _mm_or_si128(D1, F3);
_mm_storeu_si128((__m128i*)(irow + x_out + 0), G0); _mm_storeu_si128((__m128i*)(irow + x_out + 0), G0);
_mm_storeu_si128((__m128i*)(irow + x_out + 4), G1); _mm_storeu_si128((__m128i*)(irow + x_out + 4), G1);
ProcessRow_SSE2(&E0, &E1, &E2, &E3, &mult_xy, dst + x_out); ProcessRow_Floor_SSE2(&E0, &E1, &E2, &E3, &mult_xy, dst + x_out);
} }
} }
for (; x_out < x_out_max; ++x_out) { for (; x_out < x_out_max; ++x_out) {
const uint32_t frac = (int)MULT_FIX(frow[x_out], yscale); const uint32_t frac = (int)MULT_FIX(frow[x_out], yscale);
const int v = (int)MULT_FIX(irow[x_out] - frac, wrk->fxy_scale); const int v = (int)MULT_FIX_FLOOR(irow[x_out] - frac, wrk->fxy_scale);
assert(v >= 0 && v <= 255); assert(v >= 0 && v <= 255);
dst[x_out] = v; dst[x_out] = v;
irow[x_out] = frac; // new fractional start irow[x_out] = frac; // new fractional start
@ -354,6 +382,7 @@ static void RescalerExportRowShrink_SSE2(WebPRescaler* const wrk) {
} }
} }
#undef MULT_FIX_FLOOR
#undef MULT_FIX #undef MULT_FIX
#undef ROUNDER #undef ROUNDER

View File

@ -139,12 +139,7 @@ VP8AccumulateSSEFunc VP8AccumulateSSE;
extern void VP8SSIMDspInitSSE2(void); extern void VP8SSIMDspInitSSE2(void);
static volatile VP8CPUInfo ssim_last_cpuinfo_used = WEBP_DSP_INIT_FUNC(VP8SSIMDspInit) {
(VP8CPUInfo)&ssim_last_cpuinfo_used;
WEBP_TSAN_IGNORE_FUNCTION void VP8SSIMDspInit(void) {
if (ssim_last_cpuinfo_used == VP8GetCPUInfo) return;
#if !defined(WEBP_REDUCE_SIZE) #if !defined(WEBP_REDUCE_SIZE)
VP8SSIMGetClipped = SSIMGetClipped_C; VP8SSIMGetClipped = SSIMGetClipped_C;
VP8SSIMGet = SSIMGet_C; VP8SSIMGet = SSIMGet_C;
@ -161,6 +156,4 @@ WEBP_TSAN_IGNORE_FUNCTION void VP8SSIMDspInit(void) {
} }
#endif #endif
} }
ssim_last_cpuinfo_used = VP8GetCPUInfo;
} }

View File

@ -217,13 +217,9 @@ WebPYUV444Converter WebPYUV444Converters[MODE_LAST];
extern void WebPInitYUV444ConvertersMIPSdspR2(void); extern void WebPInitYUV444ConvertersMIPSdspR2(void);
extern void WebPInitYUV444ConvertersSSE2(void); extern void WebPInitYUV444ConvertersSSE2(void);
extern void WebPInitYUV444ConvertersSSE41(void);
static volatile VP8CPUInfo upsampling_last_cpuinfo_used1 = WEBP_DSP_INIT_FUNC(WebPInitYUV444Converters) {
(VP8CPUInfo)&upsampling_last_cpuinfo_used1;
WEBP_TSAN_IGNORE_FUNCTION void WebPInitYUV444Converters(void) {
if (upsampling_last_cpuinfo_used1 == VP8GetCPUInfo) return;
WebPYUV444Converters[MODE_RGBA] = WebPYuv444ToRgba_C; WebPYUV444Converters[MODE_RGBA] = WebPYuv444ToRgba_C;
WebPYUV444Converters[MODE_BGRA] = WebPYuv444ToBgra_C; WebPYUV444Converters[MODE_BGRA] = WebPYuv444ToBgra_C;
WebPYUV444Converters[MODE_RGB] = WebPYuv444ToRgb_C; WebPYUV444Converters[MODE_RGB] = WebPYuv444ToRgb_C;
@ -242,29 +238,29 @@ WEBP_TSAN_IGNORE_FUNCTION void WebPInitYUV444Converters(void) {
WebPInitYUV444ConvertersSSE2(); WebPInitYUV444ConvertersSSE2();
} }
#endif #endif
#if defined(WEBP_USE_SSE41)
if (VP8GetCPUInfo(kSSE4_1)) {
WebPInitYUV444ConvertersSSE41();
}
#endif
#if defined(WEBP_USE_MIPS_DSP_R2) #if defined(WEBP_USE_MIPS_DSP_R2)
if (VP8GetCPUInfo(kMIPSdspR2)) { if (VP8GetCPUInfo(kMIPSdspR2)) {
WebPInitYUV444ConvertersMIPSdspR2(); WebPInitYUV444ConvertersMIPSdspR2();
} }
#endif #endif
} }
upsampling_last_cpuinfo_used1 = VP8GetCPUInfo;
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// Main calls // Main calls
extern void WebPInitUpsamplersSSE2(void); extern void WebPInitUpsamplersSSE2(void);
extern void WebPInitUpsamplersSSE41(void);
extern void WebPInitUpsamplersNEON(void); extern void WebPInitUpsamplersNEON(void);
extern void WebPInitUpsamplersMIPSdspR2(void); extern void WebPInitUpsamplersMIPSdspR2(void);
extern void WebPInitUpsamplersMSA(void); extern void WebPInitUpsamplersMSA(void);
static volatile VP8CPUInfo upsampling_last_cpuinfo_used2 = WEBP_DSP_INIT_FUNC(WebPInitUpsamplers) {
(VP8CPUInfo)&upsampling_last_cpuinfo_used2;
WEBP_TSAN_IGNORE_FUNCTION void WebPInitUpsamplers(void) {
if (upsampling_last_cpuinfo_used2 == VP8GetCPUInfo) return;
#ifdef FANCY_UPSAMPLING #ifdef FANCY_UPSAMPLING
#if !WEBP_NEON_OMIT_C_CODE #if !WEBP_NEON_OMIT_C_CODE
WebPUpsamplers[MODE_RGBA] = UpsampleRgbaLinePair_C; WebPUpsamplers[MODE_RGBA] = UpsampleRgbaLinePair_C;
@ -287,6 +283,11 @@ WEBP_TSAN_IGNORE_FUNCTION void WebPInitUpsamplers(void) {
WebPInitUpsamplersSSE2(); WebPInitUpsamplersSSE2();
} }
#endif #endif
#if defined(WEBP_USE_SSE41)
if (VP8GetCPUInfo(kSSE4_1)) {
WebPInitUpsamplersSSE41();
}
#endif
#if defined(WEBP_USE_MIPS_DSP_R2) #if defined(WEBP_USE_MIPS_DSP_R2)
if (VP8GetCPUInfo(kMIPSdspR2)) { if (VP8GetCPUInfo(kMIPSdspR2)) {
WebPInitUpsamplersMIPSdspR2(); WebPInitUpsamplersMIPSdspR2();
@ -310,6 +311,7 @@ WEBP_TSAN_IGNORE_FUNCTION void WebPInitUpsamplers(void) {
assert(WebPUpsamplers[MODE_BGRA] != NULL); assert(WebPUpsamplers[MODE_BGRA] != NULL);
assert(WebPUpsamplers[MODE_rgbA] != NULL); assert(WebPUpsamplers[MODE_rgbA] != NULL);
assert(WebPUpsamplers[MODE_bgrA] != NULL); assert(WebPUpsamplers[MODE_bgrA] != NULL);
#if !defined(WEBP_REDUCE_CSP) || !WEBP_NEON_OMIT_C_CODE
assert(WebPUpsamplers[MODE_RGB] != NULL); assert(WebPUpsamplers[MODE_RGB] != NULL);
assert(WebPUpsamplers[MODE_BGR] != NULL); assert(WebPUpsamplers[MODE_BGR] != NULL);
assert(WebPUpsamplers[MODE_ARGB] != NULL); assert(WebPUpsamplers[MODE_ARGB] != NULL);
@ -317,9 +319,9 @@ WEBP_TSAN_IGNORE_FUNCTION void WebPInitUpsamplers(void) {
assert(WebPUpsamplers[MODE_RGB_565] != NULL); assert(WebPUpsamplers[MODE_RGB_565] != NULL);
assert(WebPUpsamplers[MODE_Argb] != NULL); assert(WebPUpsamplers[MODE_Argb] != NULL);
assert(WebPUpsamplers[MODE_rgbA_4444] != NULL); assert(WebPUpsamplers[MODE_rgbA_4444] != NULL);
#endif
#endif // FANCY_UPSAMPLING #endif // FANCY_UPSAMPLING
upsampling_last_cpuinfo_used2 = VP8GetCPUInfo;
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------

View File

@ -264,6 +264,7 @@ static void YuvToBgr(int y, int u, int v, uint8_t* const bgr) {
bgr[2] = Clip8(r1 >> 6); bgr[2] = Clip8(r1 >> 6);
} }
#if !defined(WEBP_REDUCE_CSP)
static void YuvToRgb565(int y, int u, int v, uint8_t* const rgb) { static void YuvToRgb565(int y, int u, int v, uint8_t* const rgb) {
const int y1 = MultHi(y, 19077); const int y1 = MultHi(y, 19077);
const int r1 = y1 + MultHi(v, 26149) - 14234; const int r1 = y1 + MultHi(v, 26149) - 14234;
@ -306,6 +307,7 @@ static void YuvToArgb(uint8_t y, uint8_t u, uint8_t v, uint8_t* const argb) {
argb[0] = 0xff; argb[0] = 0xff;
YuvToRgb(y, u, v, argb + 1); YuvToRgb(y, u, v, argb + 1);
} }
#endif // WEBP_REDUCE_CSP
static void YuvToBgra(uint8_t y, uint8_t u, uint8_t v, uint8_t* const bgra) { static void YuvToBgra(uint8_t y, uint8_t u, uint8_t v, uint8_t* const bgra) {
YuvToBgr(y, u, v, bgra); YuvToBgr(y, u, v, bgra);
@ -317,6 +319,7 @@ static void YuvToRgba(uint8_t y, uint8_t u, uint8_t v, uint8_t* const rgba) {
rgba[3] = 0xff; rgba[3] = 0xff;
} }
#if !defined(WEBP_REDUCE_CSP)
static void YuvToRgbLine(const uint8_t* y, const uint8_t* u, static void YuvToRgbLine(const uint8_t* y, const uint8_t* u,
const uint8_t* v, uint8_t* dst, int length) { const uint8_t* v, uint8_t* dst, int length) {
v16u8 R, G, B; v16u8 R, G, B;
@ -370,6 +373,7 @@ static void YuvToBgrLine(const uint8_t* y, const uint8_t* u,
memcpy(dst, temp, length * 3 * sizeof(*dst)); memcpy(dst, temp, length * 3 * sizeof(*dst));
} }
} }
#endif // WEBP_REDUCE_CSP
static void YuvToRgbaLine(const uint8_t* y, const uint8_t* u, static void YuvToRgbaLine(const uint8_t* y, const uint8_t* u,
const uint8_t* v, uint8_t* dst, int length) { const uint8_t* v, uint8_t* dst, int length) {
@ -427,6 +431,7 @@ static void YuvToBgraLine(const uint8_t* y, const uint8_t* u,
} }
} }
#if !defined(WEBP_REDUCE_CSP)
static void YuvToArgbLine(const uint8_t* y, const uint8_t* u, static void YuvToArgbLine(const uint8_t* y, const uint8_t* u,
const uint8_t* v, uint8_t* dst, int length) { const uint8_t* v, uint8_t* dst, int length) {
v16u8 R, G, B; v16u8 R, G, B;
@ -526,6 +531,7 @@ static void YuvToRgb565Line(const uint8_t* y, const uint8_t* u,
memcpy(dst, temp, length * 2 * sizeof(*dst)); memcpy(dst, temp, length * 2 * sizeof(*dst));
} }
} }
#endif // WEBP_REDUCE_CSP
#define UPSAMPLE_32PIXELS(a, b, c, d) do { \ #define UPSAMPLE_32PIXELS(a, b, c, d) do { \
v16u8 s = __msa_aver_u_b(a, d); \ v16u8 s = __msa_aver_u_b(a, d); \

View File

@ -104,21 +104,6 @@ static void Upsample32Pixels_SSE2(const uint8_t r1[], const uint8_t r2[],
Upsample32Pixels_SSE2(r1, r2, out); \ Upsample32Pixels_SSE2(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, \ #define CONVERT2RGB_32(FUNC, XSTEP, top_y, bottom_y, \
top_dst, bottom_dst, cur_x) do { \ top_dst, bottom_dst, cur_x) do { \
FUNC##32_SSE2((top_y) + (cur_x), r_u, r_v, (top_dst) + (cur_x) * (XSTEP)); \ FUNC##32_SSE2((top_y) + (cur_x), r_u, r_v, (top_dst) + (cur_x) * (XSTEP)); \
@ -135,7 +120,7 @@ static void FUNC_NAME(const uint8_t* top_y, const uint8_t* bottom_y, \
uint8_t* top_dst, uint8_t* bottom_dst, int len) { \ uint8_t* top_dst, uint8_t* bottom_dst, int len) { \
int uv_pos, pos; \ int uv_pos, pos; \
/* 16byte-aligned array to cache reconstructed u and v */ \ /* 16byte-aligned array to cache reconstructed u and v */ \
uint8_t uv_buf[4 * 32 + 15]; \ uint8_t uv_buf[14 * 32 + 15] = { 0 }; \
uint8_t* const r_u = (uint8_t*)((uintptr_t)(uv_buf + 15) & ~15); \ uint8_t* const r_u = (uint8_t*)((uintptr_t)(uv_buf + 15) & ~15); \
uint8_t* const r_v = r_u + 32; \ uint8_t* const r_v = r_u + 32; \
\ \
@ -160,11 +145,22 @@ static void FUNC_NAME(const uint8_t* top_y, const uint8_t* bottom_y, \
} \ } \
if (len > 1) { \ if (len > 1) { \
const int left_over = ((len + 1) >> 1) - (pos >> 1); \ const int left_over = ((len + 1) >> 1) - (pos >> 1); \
uint8_t* const tmp_top_dst = r_u + 4 * 32; \
uint8_t* const tmp_bottom_dst = tmp_top_dst + 4 * 32; \
uint8_t* const tmp_top = tmp_bottom_dst + 4 * 32; \
uint8_t* const tmp_bottom = (bottom_y == NULL) ? NULL : tmp_top + 32; \
assert(left_over > 0); \ assert(left_over > 0); \
UPSAMPLE_LAST_BLOCK(top_u + uv_pos, cur_u + uv_pos, left_over, r_u); \ 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); \ 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, \ memcpy(tmp_top, top_y + pos, len - pos); \
pos, len - pos); \ if (bottom_y != NULL) memcpy(tmp_bottom, bottom_y + pos, len - pos); \
CONVERT2RGB_32(FUNC, XSTEP, tmp_top, tmp_bottom, tmp_top_dst, \
tmp_bottom_dst, 0); \
memcpy(top_dst + pos * (XSTEP), tmp_top_dst, (len - pos) * (XSTEP)); \
if (bottom_y != NULL) { \
memcpy(bottom_dst + pos * (XSTEP), tmp_bottom_dst, \
(len - pos) * (XSTEP)); \
} \
} \ } \
} }

239
src/dsp/upsampling_sse41.c Normal file
View File

@ -0,0 +1,239 @@
// 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.
// -----------------------------------------------------------------------------
//
// SSE41 version of YUV to RGB upsampling functions.
//
// Author: somnath@google.com (Somnath Banerjee)
#include "src/dsp/dsp.h"
#if defined(WEBP_USE_SSE41)
#include <assert.h>
#include <smmintrin.h>
#include <string.h>
#include "src/dsp/yuv.h"
#ifdef FANCY_UPSAMPLING
#if !defined(WEBP_REDUCE_CSP)
// 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((const __m128i*)&(r1)[0]); \
const __m128i b = _mm_loadu_si128((const __m128i*)&(r1)[1]); \
const __m128i c = _mm_loadu_si128((const __m128i*)&(r2)[0]); \
const __m128i d = _mm_loadu_si128((const __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_SSE41(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_SSE41(r1, r2, out); \
}
#define CONVERT2RGB_32(FUNC, XSTEP, top_y, bottom_y, \
top_dst, bottom_dst, cur_x) do { \
FUNC##32_SSE41((top_y) + (cur_x), r_u, r_v, (top_dst) + (cur_x) * (XSTEP)); \
if ((bottom_y) != NULL) { \
FUNC##32_SSE41((bottom_y) + (cur_x), r_u + 64, r_v + 64, \
(bottom_dst) + (cur_x) * (XSTEP)); \
} \
} while (0)
#define SSE4_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[14 * 32 + 15] = { 0 }; \
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); \
uint8_t* const tmp_top_dst = r_u + 4 * 32; \
uint8_t* const tmp_bottom_dst = tmp_top_dst + 4 * 32; \
uint8_t* const tmp_top = tmp_bottom_dst + 4 * 32; \
uint8_t* const tmp_bottom = (bottom_y == NULL) ? NULL : tmp_top + 32; \
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); \
memcpy(tmp_top, top_y + pos, len - pos); \
if (bottom_y != NULL) memcpy(tmp_bottom, bottom_y + pos, len - pos); \
CONVERT2RGB_32(FUNC, XSTEP, tmp_top, tmp_bottom, tmp_top_dst, \
tmp_bottom_dst, 0); \
memcpy(top_dst + pos * (XSTEP), tmp_top_dst, (len - pos) * (XSTEP)); \
if (bottom_y != NULL) { \
memcpy(bottom_dst + pos * (XSTEP), tmp_bottom_dst, \
(len - pos) * (XSTEP)); \
} \
} \
}
// SSE4 variants of the fancy upsampler.
SSE4_UPSAMPLE_FUNC(UpsampleRgbLinePair_SSE41, VP8YuvToRgb, 3)
SSE4_UPSAMPLE_FUNC(UpsampleBgrLinePair_SSE41, VP8YuvToBgr, 3)
#undef GET_M
#undef PACK_AND_STORE
#undef UPSAMPLE_32PIXELS
#undef UPSAMPLE_LAST_BLOCK
#undef CONVERT2RGB
#undef CONVERT2RGB_32
#undef SSE4_UPSAMPLE_FUNC
#endif // WEBP_REDUCE_CSP
//------------------------------------------------------------------------------
// Entry point
extern WebPUpsampleLinePairFunc WebPUpsamplers[/* MODE_LAST */];
extern void WebPInitUpsamplersSSE41(void);
WEBP_TSAN_IGNORE_FUNCTION void WebPInitUpsamplersSSE41(void) {
#if !defined(WEBP_REDUCE_CSP)
WebPUpsamplers[MODE_RGB] = UpsampleRgbLinePair_SSE41;
WebPUpsamplers[MODE_BGR] = UpsampleBgrLinePair_SSE41;
#endif // WEBP_REDUCE_CSP
}
#endif // FANCY_UPSAMPLING
//------------------------------------------------------------------------------
extern WebPYUV444Converter WebPYUV444Converters[/* MODE_LAST */];
extern void WebPInitYUV444ConvertersSSE41(void);
#define YUV444_FUNC(FUNC_NAME, CALL, CALL_C, XSTEP) \
extern void CALL_C(const uint8_t* y, const uint8_t* u, const uint8_t* v, \
uint8_t* dst, int len); \
static void FUNC_NAME(const uint8_t* y, const uint8_t* u, const uint8_t* v, \
uint8_t* dst, int len) { \
int i; \
const int max_len = len & ~31; \
for (i = 0; i < max_len; i += 32) { \
CALL(y + i, u + i, v + i, dst + i * (XSTEP)); \
} \
if (i < len) { /* C-fallback */ \
CALL_C(y + i, u + i, v + i, dst + i * (XSTEP), len - i); \
} \
}
#if !defined(WEBP_REDUCE_CSP)
YUV444_FUNC(Yuv444ToRgb_SSE41, VP8YuvToRgb32_SSE41, WebPYuv444ToRgb_C, 3);
YUV444_FUNC(Yuv444ToBgr_SSE41, VP8YuvToBgr32_SSE41, WebPYuv444ToBgr_C, 3);
#endif // WEBP_REDUCE_CSP
WEBP_TSAN_IGNORE_FUNCTION void WebPInitYUV444ConvertersSSE41(void) {
#if !defined(WEBP_REDUCE_CSP)
WebPYUV444Converters[MODE_RGB] = Yuv444ToRgb_SSE41;
WebPYUV444Converters[MODE_BGR] = Yuv444ToBgr_SSE41;
#endif // WEBP_REDUCE_CSP
}
#else
WEBP_DSP_INIT_STUB(WebPInitYUV444ConvertersSSE41)
#endif // WEBP_USE_SSE41
#if !(defined(FANCY_UPSAMPLING) && defined(WEBP_USE_SSE41))
WEBP_DSP_INIT_STUB(WebPInitUpsamplersSSE41)
#endif

View File

@ -71,15 +71,11 @@ void WebPSamplerProcessPlane(const uint8_t* y, int y_stride,
WebPSamplerRowFunc WebPSamplers[MODE_LAST]; WebPSamplerRowFunc WebPSamplers[MODE_LAST];
extern void WebPInitSamplersSSE2(void); extern void WebPInitSamplersSSE2(void);
extern void WebPInitSamplersSSE41(void);
extern void WebPInitSamplersMIPS32(void); extern void WebPInitSamplersMIPS32(void);
extern void WebPInitSamplersMIPSdspR2(void); extern void WebPInitSamplersMIPSdspR2(void);
static volatile VP8CPUInfo yuv_last_cpuinfo_used = WEBP_DSP_INIT_FUNC(WebPInitSamplers) {
(VP8CPUInfo)&yuv_last_cpuinfo_used;
WEBP_TSAN_IGNORE_FUNCTION void WebPInitSamplers(void) {
if (yuv_last_cpuinfo_used == VP8GetCPUInfo) return;
WebPSamplers[MODE_RGB] = YuvToRgbRow; WebPSamplers[MODE_RGB] = YuvToRgbRow;
WebPSamplers[MODE_RGBA] = YuvToRgbaRow; WebPSamplers[MODE_RGBA] = YuvToRgbaRow;
WebPSamplers[MODE_BGR] = YuvToBgrRow; WebPSamplers[MODE_BGR] = YuvToBgrRow;
@ -99,6 +95,11 @@ WEBP_TSAN_IGNORE_FUNCTION void WebPInitSamplers(void) {
WebPInitSamplersSSE2(); WebPInitSamplersSSE2();
} }
#endif // WEBP_USE_SSE2 #endif // WEBP_USE_SSE2
#if defined(WEBP_USE_SSE41)
if (VP8GetCPUInfo(kSSE4_1)) {
WebPInitSamplersSSE41();
}
#endif // WEBP_USE_SSE41
#if defined(WEBP_USE_MIPS32) #if defined(WEBP_USE_MIPS32)
if (VP8GetCPUInfo(kMIPS32)) { if (VP8GetCPUInfo(kMIPS32)) {
WebPInitSamplersMIPS32(); WebPInitSamplersMIPS32();
@ -110,7 +111,6 @@ WEBP_TSAN_IGNORE_FUNCTION void WebPInitSamplers(void) {
} }
#endif // WEBP_USE_MIPS_DSP_R2 #endif // WEBP_USE_MIPS_DSP_R2
} }
yuv_last_cpuinfo_used = VP8GetCPUInfo;
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@ -254,17 +254,13 @@ void (*WebPSharpYUVUpdateRGB)(const int16_t* ref, const int16_t* src,
void (*WebPSharpYUVFilterRow)(const int16_t* A, const int16_t* B, int len, void (*WebPSharpYUVFilterRow)(const int16_t* A, const int16_t* B, int len,
const uint16_t* best_y, uint16_t* out); const uint16_t* best_y, uint16_t* out);
static volatile VP8CPUInfo rgba_to_yuv_last_cpuinfo_used =
(VP8CPUInfo)&rgba_to_yuv_last_cpuinfo_used;
extern void WebPInitConvertARGBToYUVSSE2(void); extern void WebPInitConvertARGBToYUVSSE2(void);
extern void WebPInitConvertARGBToYUVSSE41(void);
extern void WebPInitConvertARGBToYUVNEON(void); extern void WebPInitConvertARGBToYUVNEON(void);
extern void WebPInitSharpYUVSSE2(void); extern void WebPInitSharpYUVSSE2(void);
extern void WebPInitSharpYUVNEON(void); extern void WebPInitSharpYUVNEON(void);
WEBP_TSAN_IGNORE_FUNCTION void WebPInitConvertARGBToYUV(void) { WEBP_DSP_INIT_FUNC(WebPInitConvertARGBToYUV) {
if (rgba_to_yuv_last_cpuinfo_used == VP8GetCPUInfo) return;
WebPConvertARGBToY = ConvertARGBToY_C; WebPConvertARGBToY = ConvertARGBToY_C;
WebPConvertARGBToUV = WebPConvertARGBToUV_C; WebPConvertARGBToUV = WebPConvertARGBToUV_C;
@ -286,6 +282,11 @@ WEBP_TSAN_IGNORE_FUNCTION void WebPInitConvertARGBToYUV(void) {
WebPInitSharpYUVSSE2(); WebPInitSharpYUVSSE2();
} }
#endif // WEBP_USE_SSE2 #endif // WEBP_USE_SSE2
#if defined(WEBP_USE_SSE41)
if (VP8GetCPUInfo(kSSE4_1)) {
WebPInitConvertARGBToYUVSSE41();
}
#endif // WEBP_USE_SSE41
} }
#if defined(WEBP_USE_NEON) #if defined(WEBP_USE_NEON)
@ -304,6 +305,4 @@ WEBP_TSAN_IGNORE_FUNCTION void WebPInitConvertARGBToYUV(void) {
assert(WebPSharpYUVUpdateY != NULL); assert(WebPSharpYUVUpdateY != NULL);
assert(WebPSharpYUVUpdateRGB != NULL); assert(WebPSharpYUVUpdateRGB != NULL);
assert(WebPSharpYUVFilterRow != NULL); assert(WebPSharpYUVFilterRow != NULL);
rgba_to_yuv_last_cpuinfo_used = VP8GetCPUInfo;
} }

View File

@ -166,6 +166,19 @@ void VP8YuvToRgb56532_SSE2(const uint8_t* y, const uint8_t* u, const uint8_t* v,
#endif // WEBP_USE_SSE2 #endif // WEBP_USE_SSE2
//-----------------------------------------------------------------------------
// SSE41 extra functions (mostly for upsampling_sse41.c)
#if defined(WEBP_USE_SSE41)
// Process 32 pixels and store the result (16b, 24b or 32b per pixel) in *dst.
void VP8YuvToRgb32_SSE41(const uint8_t* y, const uint8_t* u, const uint8_t* v,
uint8_t* dst);
void VP8YuvToBgr32_SSE41(const uint8_t* y, const uint8_t* u, const uint8_t* v,
uint8_t* dst);
#endif // WEBP_USE_SSE41
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// RGB -> YUV conversion // RGB -> YUV conversion
@ -194,4 +207,4 @@ static WEBP_INLINE int VP8RGBToV(int r, int g, int b, int rounding) {
} // extern "C" } // extern "C"
#endif #endif
#endif /* WEBP_DSP_YUV_H_ */ #endif // WEBP_DSP_YUV_H_

View File

@ -180,7 +180,7 @@ static WEBP_INLINE void PlanarTo24b_SSE2(__m128i* const in0, __m128i* const in1,
// Repeat the same permutations twice more: // Repeat the same permutations twice more:
// r0r4g0g4 | b0b4r1r5 | g1g5b1b5 | r2r6g2g6 | b2b6r3r7 | g3g7b3b7 // r0r4g0g4 | b0b4r1r5 | g1g5b1b5 | r2r6g2g6 | b2b6r3r7 | g3g7b3b7
// r0g0b0r1 | g1b1r2g2 | b2r3g3b3 | r4g4b4r5 | g5b5r6g6 | b6r7g7b7 // r0g0b0r1 | g1b1r2g2 | b2r3g3b3 | r4g4b4r5 | g5b5r6g6 | b6r7g7b7
VP8PlanarTo24b(in0, in1, in2, in3, in4, in5); VP8PlanarTo24b_SSE2(in0, in1, in2, in3, in4, in5);
_mm_storeu_si128((__m128i*)(rgb + 0), *in0); _mm_storeu_si128((__m128i*)(rgb + 0), *in0);
_mm_storeu_si128((__m128i*)(rgb + 16), *in1); _mm_storeu_si128((__m128i*)(rgb + 16), *in1);
@ -492,7 +492,7 @@ static WEBP_INLINE void RGB32PackedToPlanar_SSE2(const uint32_t* const argb,
__m128i a1 = LOAD_16(argb + 4); __m128i a1 = LOAD_16(argb + 4);
__m128i a2 = LOAD_16(argb + 8); __m128i a2 = LOAD_16(argb + 8);
__m128i a3 = LOAD_16(argb + 12); __m128i a3 = LOAD_16(argb + 12);
VP8L32bToPlanar(&a0, &a1, &a2, &a3); VP8L32bToPlanar_SSE2(&a0, &a1, &a2, &a3);
rgb[0] = _mm_unpacklo_epi8(a1, zero); rgb[0] = _mm_unpacklo_epi8(a1, zero);
rgb[1] = _mm_unpackhi_epi8(a1, zero); rgb[1] = _mm_unpackhi_epi8(a1, zero);
rgb[2] = _mm_unpacklo_epi8(a2, zero); rgb[2] = _mm_unpacklo_epi8(a2, zero);

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