Compare commits

...

391 Commits

Author SHA1 Message Date
Vincent Rabaud
5225592f6b Refactor VP8LHistogram to hide initializations from the user.
This will make it easier to update some future statistics

Change-Id: I3a3ec64d3c9c53ebcf491007e3a4d916e122c87f
2025-04-11 16:16:37 +02:00
Vincent Rabaud
00338240c1 Remove some computations in histogram clustering
- move the bin_id to the Histogram
- do not consider empty histograms

The speed-ups are negligible as linear algorithms in uint16_t are
removed, while the whole code is still O(N^2) in histograms.

Change-Id: Ie9c4831f0f3c64af9d9710a1dc2d817ba165389e
2025-04-11 08:55:24 +02:00
Vincent Rabaud
44f91b0ddd Speed DispatchAlpha_SSE2 up
On some dataset, this was taking 2.5%. 2% when switching to
_mm_maskmoveu_si128. 1.7% when using _mm_loadu_si128

Confirmed by IACA: going from throughput of 4.26 to 3.5 and then
to 6.26 for twice the input.

Change-Id: I409f901aaad9d39bf55a1aac28cc25f126876b01
2025-04-10 11:53:19 +02:00
Vincent Rabaud
ee8e8c620f Fix member naming for VP8LHistogram
clang-tidy keeps complaining and that typedef will evolve in the
future

Change-Id: I734f2ae7dc0f4deac0dd391ae9f4b38c45507651
2025-04-10 09:54:57 +02:00
Vincent Rabaud
a1ad3f1e37 Merge "Remove now unused ExtraCostCombined" into main 2025-04-01 00:28:47 -07:00
Vincent Rabaud
321561b41f Remove now unused ExtraCostCombined
Change-Id: Ic9d1ccf5b10fed67f836aa19fa0f84238acbf4c1
2025-03-29 23:34:20 +01:00
James Zern
e0ae21d231 WebPMemoryWriterClear: use WebPMemoryWriterInit
Removes some common code between the two functions.

Change-Id: If9f42e580e34dad63f3806750d9d7571941026b5
2025-03-28 12:37:24 -07:00
Vincent Rabaud
a4183d94c7 Remove the computation of ExtraCost when comparing histograms
Entropy clustering merges symbol histograms to reduce the overall
entropy. The cost of 2 added histograms is compared to the 2 costs
of the individual histograms and if it is smaller, a merge is done.

Except for some symbols (distance and length), the computed cost is
 the real final cost based on the histogram, and some constant cost
(independent from the probabilities of the symbols and hence the
merge) because the symbol is encode as Golomb.

This constant cost is useless and can be removed.

Change-Id: I6271e8c0e4111cdeff544cbdb7dec3c67be5309c
2025-03-28 15:00:41 +01:00
Vincent Rabaud
f2b3f52733 Get AVX2 into WebP lossless
Change-Id: Ifad3102c9f899a46401985515cd98f3f7a21887f
2025-03-28 11:44:03 +01:00
Vincent Rabaud
7c70ff7a3b Clean dsp/lossless includes
Change-Id: I47a405a9c402095b440404fe57ac08b5293ea71b
2025-03-25 12:38:00 +01:00
Vincent Rabaud
9dd5ae819b Use the full register in PredictorSub13_SSE2
No more than 15 registers are used at a time

Change-Id: I40f77d9df8500e5e0d52ff6b206d765e8be62ae1
2025-03-25 11:07:15 +01:00
James Zern
613be8fc61 Makefile.vc: add /MP to CFLAGS
This speeds up the batch rules by compiling source files in parallel.

Change-Id: If5076e9c245d82df957b05711a74e2569f4ba086
2025-03-17 16:33:51 -07:00
James Zern
1d86819f49 Merge changes I1437390a,I10a20de5,I1ac777d1 into main
* changes:
  pngdec.c: add support for 'eXIf' tag
  pngdec.c: support ImageMagick app1 exif text data
  pngdec.c: add missing #ifdef for png_get_iCCP
2025-03-06 14:00:07 -08:00
James Zern
743a5f092d enc_neon: enable vld1q_u8_x4 for clang & msvc
This restores the use of the function after
980b708e enc_neon: fix build w/aarch64 gcc < 9.4.0

The intrinsic was added to llvm for aarch64 in:
5e4ce1ae9dad Implement the newly added AArch64 ACLE functions for
             ld1/st1 with 2/3/4 vectors. The functions are like:
             vst1_s8_x2 ...
llvmorg-3.4.0-rc1~101
https://github.com/llvm/llvm-project/commit/5e4ce1ae9dad

Visual Studio 2019 and 2022 also support the function (2017 is still
disabled for this path due to it relying on arm64_neon.h).

Change-Id: I6ff10e22deb3968a48738a4458d2d3d55410b5ec
2025-03-05 16:56:20 -08:00
James Zern
565da14882 pngdec.c: add support for 'eXIf' tag
Test file created with exiftool 12.76:

```
exiftool test_app1_exif.png -exif:all \
  -exif:DocumentName=test_multi_exif.png -o test_multi_exif.png
```

Bug: webp:398066379
Change-Id: I1437390a70f5708421683eb69c588624bb376baa
2025-03-05 13:54:09 -08:00
James Zern
319860e919 pngdec.c: support ImageMagick app1 exif text data
Test file created with ImageMagick 6.9.13-12:

```
convert test_exif.png test_app1_exif.png
```

Bug: webp:398066379
Change-Id: I10a20de5699fabb0906045994d7d1f4b9e951973
2025-03-05 13:54:07 -08:00
James Zern
815fc1e110 pngdec.c: add missing #ifdef for png_get_iCCP
png_get_iCCP is an optional part of the API. Protect its usage with
PNG_iCCP_SUPPORTED.

Change-Id: I1ac777d1c2a200bb3e1303b3d095cc0d67633bd4
2025-03-05 13:54:04 -08:00
James Zern
980b708e2c enc_neon: fix build w/aarch64 gcc < 9.4.0
vld1q_u8_x4 was added for aarch64 in the gcc 9.4.0 release:
https://gcc.gnu.org/git/?p=gcc.git;a=blob;f=gcc/ChangeLog;h=7558c0a369ea8c74a2b9369049a2d1cc187dc050;hb=13c83c4cc679ad5383ed57f359e53e8d518b7842#l2100

fixes:
src/dsp/enc_neon.c: In function 'Intra4Preds_NEON':
src/dsp/enc_neon.c:974:37: warning: implicit declaration of function
  'vld1q_u8_x4'; did you mean 'vld1q_u8_x2'?
  [-Wimplicit-function-declaration]

Bug: webp:398288323
Change-Id: Ic6e408065a375c945cc8691bd16a9f5d5642cfa2
2025-02-27 19:07:50 -08:00
James Zern
73b728cbb9 cmake: bump minimum version to 3.16
This matches the current support matrix (from 2024-12-17) [1] and quiets
a warning from recent (3.31.5) versions of cmake:

CMake Deprecation Warning at CMakeLists.txt:12 (cmake_minimum_required):
  Compatibility with CMake < 3.10 will be removed from a future version
  of CMake.

Explicit setting of CMP0072 is also removed; it was added in 3.11.

[1]: https://github.com/google/oss-policies-info/blob/main/foundational-cxx-support-matrix.md

Bug: webp:397130631
Change-Id: Ic844dadf983a82674990edbddbfc54329df12eb7
Fixed: webp:397130631
2025-02-20 12:32:08 -08:00
Vincent Rabaud
6a22b6709c Add a function to validate a WebPDecoderConfig
This echoes WebPValidateConfig for encoding.

Change-Id: Ib404d55c7af4d0755644879ec491e3998e6b5e8d
2025-01-30 10:10:08 +01:00
Vincent Rabaud
7ed2b10ef0 Use consistently signed stride types.
The stride can be negative when asked for a flipped image.

Change-Id: I049e8027c769186274a6a3049949f3fcaae7d2e9
2025-01-30 00:12:28 +01:00
Vincent Rabaud
654bfb040c Avoid nullptr arithmetic in VP8BitReaderSetBuffer
When start is nullptr, the IO is not used afterwards
anyway, so there is not risk.

Change-Id: I0a828aec85c6e228e95dfed4a40d348275a7c577
2025-01-30 00:12:15 +01:00
Vincent Rabaud
f8f2410710 Fix potential "divide by zero" in examples found by coverity
Change-Id: Ic41f9cb2ac24450986cd061db718953276eee080
2025-01-16 18:02:41 +01:00
James Zern
2af6c034ac libwebp-1.5.0
- 12/19/2024 version 1.5.0
   This is a binary compatible release.
   API changes:
     - `cross_color_transform_bits` added to WebPAuxStats
   * minor lossless encoder speed and compression improvements
   * lossless encoding does not use floats anymore
   * additional Arm optimizations for lossy & lossless + general code generation
     improvements
   * improvements to WASM performance (#643)
   * improvements and corrections in webp-container-spec.txt and
     webp-lossless-bitstream-spec.txt (#646, #355607636)
   * further security related hardening and increased fuzzing coverage w/fuzztest
     (oss-fuzz: #382816119, #70112, #70102, #69873, #69825, #69508, #69208)
   * miscellaneous warning, bug & build fixes (#499, #562, #381372617,
     #381109771, #42340561, #375011696, #372109644, chromium: #334120888)
   Tool updates:
     * gif2webp: add -sharp_yuv & -near_lossless
     * img2webp: add -exact & -noexact
     * exit codes normalized; running an example program with no
       arguments will output its help and exit with an error (#42340557,
       #381372617)
 -----BEGIN PGP SIGNATURE-----
 
 iQIzBAABCgAdFiEEaw5rcJdt4wPt8vYB+cPWvbgjK10FAmdk0soACgkQ+cPWvbgj
 K11UhhAAl5LtmIDz5uQE5ZlAADpIAuAC5nIikQUVY9up4RqAaw734atTh5JRzbpL
 QoQvAUPQ6YBdiH2GSF47THGHHQZfsV+f3yb0MICI3l6NOBJhHHFmG2Dt3IVVmO1l
 LZGM1CxaSZP7gpvSa/eNwvXEWxLezith7I3fyY0oIEf+JKdWan7uyeUPvc+iFrpo
 xTSpcAdWbHKGaC6zvH5gPJPlW64D2MZ31To+26s44uSgwpB6JrICXpxwn51cOClc
 1YzGJZ/aTQBphwY0W2yYFa5rBs6VxhCGHJAY5dSTmkeMUiQpIz0kugkKmyfVBmfN
 2tLC1suE0WgXzHUVwlZdorM5EIjXK0Orht/Fn5EphjmUXPr+2S+ENwiOnI2HPrEB
 Fn3Cy64uOHsuW58JVm+yUeNtPqB8uXunzQrteO7nd5aKXNxgth83QJwzv0T80tMI
 NltAfse+QPrbwA/GS250hh+8WfFzOr8i9W/3V0OYZXqLD/ooJA2hxy3gAU6Zr2qa
 GowRvbCZs18w1ormXoDEC3tBnBBPi8ktRfYd2wGHRl0VUFo1Ntyj+tr8NOuylpxO
 hE3WFn/Ao6Xs3WRSx1LppbPvWnH+j2UAm0QCeAcUN2A766XpKyupGDAg09fZUZe6
 korrahZni3I0uOpqyZX0W2FmCQYIIRHTwcCNLD/yTqlqhyiQtDg=
 =HZLr
 -----END PGP SIGNATURE-----

Merge tag 'v1.5.0'

libwebp-1.5.0

- 12/19/2024 version 1.5.0
  This is a binary compatible release.
  API changes:
    - `cross_color_transform_bits` added to WebPAuxStats
  * minor lossless encoder speed and compression improvements
  * lossless encoding does not use floats anymore
  * additional Arm optimizations for lossy & lossless + general code generation
    improvements
  * improvements to WASM performance (#643)
  * improvements and corrections in webp-container-spec.txt and
    webp-lossless-bitstream-spec.txt (#646, #355607636)
  * further security related hardening and increased fuzzing coverage w/fuzztest
    (oss-fuzz: #382816119, #70112, #70102, #69873, #69825, #69508, #69208)
  * miscellaneous warning, bug & build fixes (#499, #562, #381372617,
    #381109771, #42340561, #375011696, #372109644, chromium: #334120888)
  Tool updates:
    * gif2webp: add -sharp_yuv & -near_lossless
    * img2webp: add -exact & -noexact
    * exit codes normalized; running an example program with no
      arguments will output its help and exit with an error (#42340557,
      #381372617)

Bug: b:336795049,webp:380121350

* tag 'v1.5.0':
  update ChangeLog
  update NEWS
  tests/fuzzer/*: add missing <string_view> include
  fuzz_utils.cc: fix build error w/WEBP_REDUCE_SIZE
  mux_demux_api_fuzzer.cc: fix -Wshadow warning
  update ChangeLog
  update NEWS
  bump version to 1.5.0
  update AUTHORS

Change-Id: I076b197fac29230bc61bc5f06e950d83d058a737
2024-12-19 18:19:10 -08:00
James Zern
a4d7a71533 update ChangeLog
Bug: b:336795049,webp:380121350
Change-Id: I011bf6c44f89e475f58c6e96f5b68c6ed75a1e22
2024-12-19 17:17:50 -08:00
James Zern
c3d85ce4cf update NEWS
Bug: b:336795049,webp:380121350
Change-Id: Icb6f2f046647591a318f12853f265b2115060488
2024-12-19 12:32:05 -08:00
devtools-clrobot@google.com
ad14e811cf tests/fuzzer/*: add missing <string_view> include
Bug: webp:380121350
Change-Id: Ie0910165600317ed8c94305f0a793282e02e1c99
2024-12-19 12:31:52 -08:00
James Zern
74cd026edb fuzz_utils.cc: fix build error w/WEBP_REDUCE_SIZE
Correct (void) variable names.

Bug: webp:380121350
Change-Id: I3ce8a4d34f60f9ec0a467fcb5958b0b7a2edabc9
2024-12-17 09:58:20 -08:00
James Zern
a027aa93de mux_demux_api_fuzzer.cc: fix -Wshadow warning
`bool mux` -> `use_mux_api` to avoid conflicting with WebPMux variable.

Bug: webp:380121350
Change-Id: Ie3f8176efc296fae804c36ee0b27bf8e3034c6e8
2024-12-17 09:57:47 -08:00
James Zern
25e17c686f update ChangeLog
Bug: b:336795049,webp:380121350
Change-Id: I0ae2d1d3a812b6bc9c4cd889eae03308e344190b
2024-12-13 12:25:59 -08:00
James Zern
aa2684fccc update NEWS
Bug: b:336795049,webp:380121350
Change-Id: Ieb2c7961f6eef39813399855027d007e88ca7891
2024-12-13 09:27:03 -08:00
James Zern
369238461b bump version to 1.5.0
libwebp{,decoder} - 1.5.0
libwebp libtool - 8.10.1
libwebpdecoder libtool - 4.10.1

mux - 1.5.0
libtool - 4.1.1

demux - 1.5.0
libtool - 2.16.0

sharpyuv - 0.4.1
libtool - 1.1.1

Bug: b:336795049,webp:380121350
Change-Id: I53bdac2b0bd5ce30addf10e16776a16a07910e45
2024-12-12 17:43:51 -08:00
James Zern
ceea8ff6b3 update AUTHORS
Bug: b:336795049,webp:380121350
Change-Id: I45a2aff8d9f04d996e3391d111d18d0872f45b41
2024-12-12 17:43:41 -08:00
James Zern
e4f7a9f0c7 img2webp: add a warning for unused options
This may help prevent confusion when placing frame options after the
target frame.

Note for compatibility this isn't fatal, but the behavior may change in
the future.

Bug: webp:381372617
Change-Id: I9f3b51e60ff650ccc6fd29b8f5f607c3771a8a55
2024-12-10 17:32:54 -08:00
Vincent Rabaud
1b4c967fbb Merge "Properly check the data size against the end of the RIFF chunk" into main 2024-12-10 08:10:16 +00:00
Vincent Rabaud
9e5ecfaf00 Properly check the data size against the end of the RIFF chunk
Bug: oss-fuzz:382816119

Change-Id: I629870246d8f1bd7c6cb0d66e89018600cecee3a
2024-12-10 09:09:08 +01:00
James Zern
da0d9c7d4e examples: exit w/failure w/no args
cwebp, gif2webp, img2webp, vwebp and webpinfo are modified in this
change to align with the other examples. When given no arguments, the
examples print their help output and exit with failure.

Bug: webp:42340557, webp:381372617
Change-Id: Ifed4eb79e98233f7aa780c42e489636d0cf4a035
2024-12-06 14:53:06 -08:00
James Zern
fcff86c71b {gif,img}2webp: sync -m help w/cwebp
These were both missing the mention of the default value (4).

Bug: webm:381109771
Change-Id: Ibb0d822310af443c5ff5219fc0334008de0a0c60
2024-11-26 13:08:29 -08:00
James Zern
b76c4a8416 man/img2webp.1: sync -m text w/cwebp.1 & gif2webp.1
Bug: webp:381109771
Change-Id: I3df400305255ba74a913601cf7aa04f392814370
2024-11-26 13:03:20 -08:00
James Zern
306335198d muxread: fix reading of buffers > riff size
After:
  2c70ad76 muxread,CreateInternal: fix riff size checks (cl/200674839)

`SizeWithPadding()` adds `CHUNK_HEADER_SIZE` (plus additional 1 byte
padding if needed). A later check included `CHUNK_HEADER_SIZE` before
capping the value of the size passed to `WebPMuxCreateInternal()`,
missing cases with a small amount of extra data after the RIFF chunk
(like a newline when the file is opened and saved in a text editor) and
setting size to an incorrect value, so larger sizes would also fail.

Another check of `riff_size < CHUNK_HEADER_SIZE` after the call to
`SizeWithPadding()` is removed because 1) it could not fail given
`SizeWithPadding()` adds `CHUNK_HEADER_SIZE` to the value; and 2) it is
redundant as `size < RIFF_HEADER_SIZE + CHUNK_HEADER_SIZE` is checked
earlier in the function.

Bug: webp:42340561
Change-Id: I58dc4f071b27c2841001b4012aabdb1869f64f97
2024-11-22 12:40:34 -08:00
James Zern
4c85d860ea yuv.h: update RGB<->YUV coefficients in comment
The values for the R/G/B floating point formulas resembled
https://fourcc.org/fccyvrgb.php and Video Demystified, but the fixed
point values are more closely aligned to rounded values from
https://en.wikipedia.org/wiki/YCbCr and BT.601.

The R/G/B formulas with the values prior to this change are added to
sharpyuv_csp.c as they align with the fixed values. The origin of those
coefficients is unclear. For consistency between library versions we'll
leave them as is.

Bug: webp:375011696
Change-Id: Id3f2a57530eee700cc52a899b32b25b5c015e89b
2024-11-21 16:21:45 -08:00
James Zern
0ab789e067 Merge changes I6dfedfd5,I2376e2dc into main
* changes:
  rework AddVectorEq_SSE2
  rework AddVector_SSE2
2024-11-15 02:58:10 +00:00
James Zern
0323645066 {ios,xcframework}build.sh: fix compilation w/Xcode 16
Don't use `-fembed-bitcode`, fixes:
ld: warning: -bitcode_bundle is no longer supported and will be ignored
ld: -mllvm and -bitcode_bundle (Xcode setting ENABLE_BITCODE=YES) cannot
    be used together

Change-Id: I4ead0fc71da39bb5ec92c1f5ba467b95ad8b7461
2024-11-14 20:26:57 +00:00
James Zern
61e2cfdadd rework AddVectorEq_SSE2
Take advantage of the known sizes used by VP8LHistogramAdd() and
remove loop for the remainder. The loop was being auto-vectorized making
the code larger and slower than the vectorized C code.

For larger sizes the new code is ~3-4.5% faster than the old code with
about the same improvement against the vectorized C code. For the
minimal size (40), the new code is ~30% faster than the C and old SSE2
code.

The LINE_SIZE==8 option is removed with this change. It had been set
to 16 for its entire life and clang-16 was unrolling the LINE_SIZE==8
case by 2 in any case; they both profile similarly.

Change-Id: I6dfedfd57474f44d15e2ce510a48e5252221077a
2024-11-14 12:21:39 -08:00
James Zern
7bda3deb89 rework AddVector_SSE2
Take advantage of the known sizes used by VP8LHistogramAdd() and remove
loop for the remainder. The loop was being auto-vectorized making the
code larger and slower than the vectorized C code.

For larger sizes the new code is ~4-7% faster than the old code with
about the same improvement against the vectorized C code. For the
minimal size (40), the new code is ~30% faster than the C and old SSE2
code.

The LINE_SIZE==8 option is removed with this change. It had been set to
16 for its entire life and clang-16 was unrolling the LINE_SIZE==8 case
by 2 in any case; they both profile similarly.

Change-Id: I2376e2dca3bffa38477b4a432f4c533419e3be0e
2024-11-14 12:21:33 -08:00
Maryla
2ddaaf0aa5 Fix variable names in SharpYuvComputeConversionMatrix
Change-Id: Ia07e71aae42396100a4f50dc104e828239522d77
2024-11-07 09:37:40 +01:00
James Zern
a3ba6f19e9 Makefile.vc: fix gif2webp link error
Add missing dependency on libsharpyuv.

needed after:
f999d94f gif2webp: add -sharp_yuv/-near_lossless

Change-Id: I8bdd5c0fd4622f9c8ec6ffdf4ac11399f86350da
2024-11-06 10:14:05 -08:00
James Zern
f999d94f4a gif2webp: add -sharp_yuv/-near_lossless
This change is the same as the one that introduced the options to
img2webp:
0825faa4 img2webp: add -sharp_yuv/-near_lossless

Change-Id: Id380d159299c38dd6440f833d487e00c0976afec
2024-11-04 12:29:24 -08:00
James Zern
dfdcb7f95c Merge "lossless.h: fix function declaration mismatches" into main 2024-10-09 22:30:49 +00:00
James Zern
78ed683978 fix overread in Intra4Preds_NEON
Extend VP8EncIterator::i4_boundary_ by 3 bytes to avoid Intra4Preds_NEON
reading deeper into the struct (likely padding) when top is positioned
at offset 29. This data is memset with MSan to prevent a warning due to
its incorrect modeling of tbl instructions.

Prior to:
  169dfbf9 disable Intra4Preds_NEON
there was a mismatch in the preprocessor checks for enabling the
function in NEON and removing the C version; NEON used `BPS == 32` while
the C code was removed unconditionally when building for aarch64. This
patch also normalizes those checks to look for `BPS == 32` and `BPS !=
32` as appropriate.

Bug: b:366668849,webp:372109644
Change-Id: Ic9e6ad4b2d844cb446decd63aec0b2676a89c8d0
2024-10-08 16:55:12 -07:00
James Zern
d516a68e54 lossless.h: fix function declaration mismatches
These appear as warnings under VS15 (16 and 17 are silent) and were
missed in:
a32b436b dsp/lossless*: use WEBP_RESTRICT qualifier

Change-Id: Ia7cffafc166f2da93b51714363558798cda71b67
2024-10-08 13:41:16 -07:00
Maryla Ustarroz-Calonge
874069042e Merge "Improve documentation of SharpYuvConversionMatrix." into main 2024-10-04 11:59:25 +00:00
James Zern
fdb229ea3a Merge changes I07a7e36a,Ib29980f7,I2316122d,I2356e314,I32b53dd3, ... into main
* changes:
  dsp/yuv*: use WEBP_RESTRICT qualifier
  dsp/upsampling*: use WEBP_RESTRICT qualifier
  dsp/rescaler*: use WEBP_RESTRICT qualifier
  dsp/lossless*: use WEBP_RESTRICT qualifier
  dsp/filters*: use WEBP_RESTRICT qualifier
  dsp/enc*: use WEBP_RESTRICT qualifier
  dsp/dec*: use WEBP_RESTRICT qualifier
  dsp/cost*: use WEBP_RESTRICT qualifier
2024-10-03 17:01:02 +00:00
Maryla
0c3cd9cc2c Improve documentation of SharpYuvConversionMatrix.
Change-Id: I39898bf53db759b68c86c9005c11ded20de4eb3e
2024-10-03 10:35:58 +02:00
James Zern
169dfbf931 disable Intra4Preds_NEON
The load of the `top` parameter may over read causing MSan errors:

==7373==WARNING: MemorySanitizer: use-of-uninitialized-value
  #0 0xfff891d52ad4 in Intra4Preds_NEON src/dsp/enc_neon.c:1003:12
  #1 0xfff892d87618 in MakeIntra4Preds src/enc/quant_enc.c:484:3

Bug: b:366668849
Change-Id: I29cf3b2f402ee79ea93c1ee2a4fdd95083aeed68
2024-10-02 15:42:19 -07:00
James Zern
2dd5eb9862 dsp/yuv*: use WEBP_RESTRICT qualifier
Better vectorization in the C code, fewer instructions / comparisons in
NEON, and fewer reloads in SSE2/SSE4 w/ndk r27/gcc-13/clang-16.

This only affects non-vector pointers; any vector pointers are left as a
follow up.

Change-Id: I07a7e36a2dce8632c71c0fbbeef94dc51453eaf7
2024-10-02 14:55:15 -07:00
James Zern
23bbafbeb8 dsp/upsampling*: use WEBP_RESTRICT qualifier
Better vectorization in the C code, fewer instructions in NEON, and some
code reordering / better register usage in SSE2/SSE4 w/ndk
r27/gcc-13/clang-16.

This only affects non-vector pointers; any vector pointers are left as a
follow up.

Change-Id: Ib29980f778ad3dbb952178ad8dee39b8673c4ff8
2024-10-02 14:55:15 -07:00
James Zern
35915b389e dsp/rescaler*: use WEBP_RESTRICT qualifier
Some improvement in the C code. No changes in NEON or SSE2 w/ndk
r27/gcc-13/clang-16.

This only affects non-vector pointers; any vector pointers are left as a
follow up.

Change-Id: I2316122db893f48f0afda90a147c83cac7f07526
2024-10-02 14:55:14 -07:00
James Zern
a32b436bd5 dsp/lossless*: use WEBP_RESTRICT qualifier
lossless_enc: better vectorization, most benefits seen in AddVector/Eq
              w/ndk r27/gcc-13/clang-16
lossless: minor reordering and some improvement to PredictorAdd5_SSE2
          w/gcc-13

This only affects non-vector pointers; any vector pointers are left as a
follow up.

Change-Id: I2356e314f391ee2f2c71f00bc6ee10097d3881e7
2024-10-02 14:55:14 -07:00
James Zern
04d4b4f387 dsp/filters*: use WEBP_RESTRICT qualifier
Better stack/register usage in SSE2/NEON code and improved vectorization
of the C code with ndk r27/gcc-13/clang-16.

This only affects non-vector pointers; any vector pointers are left as a
follow up.

Change-Id: I32b53dd38bfc7e2231d875409e7dfda7c513cfb6
2024-10-02 14:55:14 -07:00
James Zern
b1cb37e659 dsp/enc*: use WEBP_RESTRICT qualifier
This allows for better vectorization of the C code, inlining of
TrueMotion_SSE2, better load usage in aarch64 and other minor
reordering with ndk r27/gcc-13/clang-16.

This only affects non-vector pointers; any vector pointers are left as a
follow up.

Change-Id: I07e9944d5c0aa5a079b22883ac5a2d649695e4a0
2024-10-02 14:55:14 -07:00
James Zern
201894ef24 dsp/dec*: use WEBP_RESTRICT qualifier
A minor improvement for arm targets with ndk r27/gcc-13 in H/VFilter8 (a
couple fewer moves w/aarch64) and much better vectorization of
DitherCombine8x8_C in most targets.

This only affects non-vector pointers; any vector pointers are left as a
follow up.

Change-Id: I03e73e6d6404261bb8408a9ae76a4b6ef142f8f0
2024-10-02 14:55:14 -07:00
James Zern
02eac8a741 dsp/cost*: use WEBP_RESTRICT qualifier
on SetResidualCoeffs_*. This results in some minor code reordering when
targeting arvm7 with ndk r27 and other recent versions of clang. No
changes in the x86 compilations with clang-16 / gcc-13.

This only affects non-vector pointers; any vector pointers are left as a
follow up.

Change-Id: I7c3554ece848fafbc5ac9c4944f1dc85129f6fd8
2024-10-02 14:55:14 -07:00
James Zern
84b118c9c3 Merge "webp-container-spec: normalize notes & unknown chunk link" into main 2024-09-30 18:16:05 +00:00
James Zern
052cf42f1a webp-container-spec: normalize notes & unknown chunk link
- use plural 'Notes' in the description of 'Background Color' to match
  the formatting of the notes describing 'Disposal method';
- fix one unknown chunks link to contain both words to match others

+ add a couple of missing commas

These changes are based on editor changes in AUTH48:
https://datatracker.ietf.org/doc/draft-zern-webp/

Change-Id: Ibbed0459d42944099e295f492dc21bde4e107658
2024-09-27 11:07:10 -07:00
Vincent Rabaud
220ee52967 Search for best predictor transform bits
This is useful in cruncher mode.

Change-Id: I8586bdbf464daf85db381ab77a18bf63dd48f323
2024-09-24 10:44:22 +02:00
Vincent Rabaud
7861947813 Try to reduce the sampling for the entropy image
This offers minor compression improvements.

Change-Id: I4b3b1bb11ee83273c0e4c9f47e53b21cf7cd5f76
2024-09-24 10:28:43 +02:00
James Zern
14f09ab75b webp-container-spec: reorder chunk size - N text
Use 'Chunk Size bytes - N' to avoid singular/plural confusion in the
case of 'Chunk Size - 1 bytes' case.

These changes are based on editor comments in AUTH48:
https://datatracker.ietf.org/doc/draft-zern-webp/

Change-Id: I898113033fd53d744fe9289f971887b8cfe278b9
2024-09-19 11:54:42 -07:00
Vincent Rabaud
a78c5356ba Remove a useless malloc for entropy image
histogram_symbols is converted to uint32_t and <<8 into
histogram_argb.
Using a uint32_t buffer from the start prevents copying and
converting the data.

Change-Id: I245003a6a0f048c31519afa25a600d4479e762e3
2024-09-18 22:38:11 +02:00
Vincent Rabaud
bc49176355 Merge "Refactor predictor finding" into main 2024-09-18 08:38:57 +00:00
James Zern
34f9223829 man/{cwebp,img2webp}.1: rm 'if needed' from -sharp_yuv
The wording might have implied that the library would optionally use
sharpyuv, though this option forces its use. The riskiness score
computed by SharpYuvEstimate420Risk() (extras/extras.c) is not used by
the library.

Change-Id: I56ea3262d7985215570809a4a629a2a7760e936a
2024-09-17 11:03:04 -07:00
Vincent Rabaud
367ca938f1 Refactor predictor finding
This is useful for a forward change that will improve compression.
It splits the residual computation and the best predictor
selection.

The only downside is that more memory is allocated: we had 2
histograms before, we now have 14, but this is necessary for the
later change. Still, this is nothing compared to what is done
later in the pipeline in HistogramSetTotalSize where the number of
histograms created is the number of pixels in the subsampled image.

Change-Id: If03501a26f00462dd1809daa6e9314abd180945d
2024-09-17 09:49:43 +02:00
James Zern
a582b53b74 webp-lossless-bitstream-spec: clarify some text
These changes are based on editor comments in AUTH48:
https://datatracker.ietf.org/doc/draft-zern-webp/

Change-Id: I21f18bce43fde0e396b2cbc935d0ff90448f96c4
2024-09-10 18:04:24 -07:00
James Zern
0fd25d8406 Merge "anim_encode.c: fix function ref in comment" into main 2024-09-10 18:53:23 +00:00
James Zern
f888291359 anim_encode.c: fix function ref in comment
WebPCleanupTransparentAreaLossless() was renamed to
WebPReplaceTransparentPixels() in:
55a080e5 Add WebPReplaceTransparentPixels() in dsp

Change-Id: I91e32574e6add2748c0655146f100eb2b40498b2
2024-09-09 19:28:12 -07:00
James Zern
40e4ca60ea specs_generation.md: update kramdown command line
coderay was extracted from the core and the options removed in 2.0.0.
See:
49e1b12f52

Change-Id: I5191dcec296ba4bcde5f0bcbc46d1e1135d40ec2
2024-09-06 15:32:26 -07:00
James Zern
57883c78ed img2webp: add -exact/-noexact per-frame options
Bug: b:363409354
Change-Id: I4e7282ed2df091dbef6d79743be1c8c868c0d44a
2024-09-03 18:58:13 -07:00
James Zern
1c8eba978b img2webp,cosmetics: add missing '.' spacers to help
Change-Id: I98e853a8caa091c182d41ea9d95499021c8deb3a
2024-09-03 18:27:45 -07:00
Vincent Rabaud
2e81017c7a Convert predictor_enc.c to fixed point
Also remove the last float in histogram_enc.c

Change-Id: I6f647a5fc6dd34a19292820817472b4462c94f49
2024-08-30 09:22:48 +02:00
Vincent Rabaud
94de6c7fed Merge "Fix fuzztest link errors w/-DBUILD_SHARED_LIBS=1" into main 2024-08-30 07:15:24 +00:00
Vincent Rabaud
51d9832a36 Fix fuzztest link errors w/-DBUILD_SHARED_LIBS=1
Change-Id: I089a59baa3275f7a62483da0bc1d5269e51af74e
2024-08-28 11:39:11 +02:00
Vincent Rabaud
7bcb36b884 Merge "Fix static overflow warning." into main 2024-08-28 09:17:08 +00:00
Vincent Rabaud
8e0cc14c3e Fix static overflow warning.
In practice, this can never happen because:
- 'streak' is at most as long as a histogram
- 'count' counts the number of streaks

'streak' and 'count' are therefore at most as big as the histogram
length which is at most the max of VP8LHistogramNumCodes,
which is 256+24+(1<<10).

Change-Id: I31c8834543479c8a9260732313ea26b045519515
2024-08-28 10:23:54 +02:00
James Zern
cea684626d README.md: add security report note
The default template for https://issues.webmproject.org/ is a public bug
report. Security issues can be reported securely using the 'Security
report' template.

Change-Id: Id489253c0def8a4d6d26327ea93ef4c796703ff1
2024-08-26 18:34:04 -07:00
James Zern
615e58744f Merge "make VP8LPredictor[01]_C() static" into main 2024-08-22 17:35:52 +00:00
James Zern
233e86b91f Merge changes Ie43dc5ef,I94cd8bab into main
* changes:
  Do*Filter_*: remove row & num_rows parameters
  Do*Filter_C: remove dead 'inverse' code paths
2024-08-19 18:51:06 +00:00
James Zern
1a29fd2fc3 make VP8LPredictor[01]_C() static
Only predictors 2-13 are reused in lossless_enc.c.

Change-Id: Ia3a7342fccfb44b9ad5297f48d6be2d96af68ec8
2024-08-16 10:58:45 -07:00
James Zern
dd9d3770d7 Do*Filter_*: remove row & num_rows parameters
The row parameter became a constant in:
2102ccd update the Unfilter API in dsp to process one row independently

num_rows is always equal to height.

Change-Id: Ie43dc5ef222e442ce8c92766da0b9824ccbca236
2024-08-12 19:36:31 -07:00
James Zern
ab451a495c Do*Filter_C: remove dead 'inverse' code paths
The inverse parameter became a constant in:
2102ccd update the Unfilter API in dsp to process one row independently

The row parameter to these functions is in a similar state; it will be
removed in a follow up.

Change-Id: I94cd8babe0e42474ff794ba5fa29dd48039de5f8
2024-08-08 18:13:48 -07:00
James Zern
f9a480f7c3 {TrueMotion,TM16}_NEON: remove zero extension
Replace vmovl_u8 -> s16 + signed vaddq with unsigned vaddw.
No change in assembly with clang-16 (armv7 & aarch64) and gcc-13
(aarch64). armv7 gcc-13 had kept the vmovl instructions, those are now
gone.

Change-Id: Ibb4fbdd5680d3e9dd06933c100528a6f363de472
2024-08-07 16:43:14 -07:00
James Zern
04834acae7 Merge changes I25c30a9e,I0a192fc6,I4cf89575 into main
* changes:
  WASM: Enable VP8L_USE_FAST_LOAD
  WASM: don't use USE_GENERIC_TREE
  WASM: Enable 64-bit BITS caching
2024-08-01 18:36:34 +00:00
James Zern
39a602afe6 webp-lossless-bitstream-spec: normalize predictor transform ref
Replace the only use of 'prediction transform' with 'predictor
transform' which is used throughout the text.

Spotted by thakis@.

Bug: webp:355607636
Change-Id: Ic4e1f08e2ff94da82824cee24c86a4fa42c7ec28
2024-07-29 19:22:33 -07:00
James Zern
f28c837dc1 Merge "webp-container-spec: align anim pseudocode w/prose" into main 2024-07-29 17:17:16 +00:00
Vincent Rabaud
74be8e22d9 Fix implicit conversion issues
Change-Id: If2cc8a137371ef365cf4a9c55f1b6ab131fba564
2024-07-25 22:30:15 +02:00
Vincent Rabaud
0c01db7c3c Merge "Increase the transform bits if possible." into main 2024-07-19 22:44:13 +00:00
Vincent Rabaud
f2d6dc1eef Increase the transform bits if possible.
This brings minor size improvements because repetitive values in
the transform images are easily explainable through LZ77. Still,
it makes an upcoming pull request a bit more stable.

This is a rollforward of
7ec51c591608333fd5e6fdddbee16e1d65bef3db
ee26766a89a149afe5f73fdcb8f2493ec808f2b7

Change-Id: I254ab3ccd5053344f89099280e8d994ecd55aee0
2024-07-19 23:22:27 +02:00
James Zern
caa19e5b3a update link to issue tracker
https://bugs.chromium.org/p/webp ->
https://issues.webmproject.org

Change-Id: I45324210d4e9351238da127efd04b22627548545
2024-07-18 16:49:45 -07:00
James Zern
c9dd9bd40b webp-container-spec: align anim pseudocode w/prose
- add missing 'or application-defined color' when creating the canvas
- reference 'dispose_method' before rendering image

Bug: webp:646
Change-Id: I25734d1912644f0aa6c87e14b80ed8cd9b180056
2024-07-16 15:42:07 -07:00
wrv
8a7c8dc662 WASM: Enable VP8L_USE_FAST_LOAD
It is 2-5% faster to use VP8L fast load on WASM

Bug: webp:643
Change-Id: I25c30a9e6bcfc7cadd640122579eeebcb37e6fc0
2024-07-15 14:41:36 -05:00
wrv
f0c53cd966 WASM: don't use USE_GENERIC_TREE
It is 2-4% faster to use hard-coded tree on WASM

Bug: webp:643
Change-Id: I0a192fc6af210c79814a81084cd1f199714bf46c
2024-07-15 14:41:14 -05:00
wrv
eef903d04a WASM: Enable 64-bit BITS caching
Bug: webp:643
Change-Id: I4cf89575e0ebcfeaf9d84be8e188863657893a07
2024-07-15 14:40:45 -05:00
James Zern
6296cc8d0d iterator_enc: make VP8IteratorReset() static
This function is unused outside of iterator_enc.c.

Change-Id: I0f1ecedeb9ed4d9f51d0135f04b8ef00424f24cc
2024-07-12 15:23:10 -07:00
James Zern
fbd93896a6 histogram_enc: make VP8LGetHistogramSize static
This function is unused outside of histogram_enc.c.

Change-Id: I527f54408383d0bc9d04878ca397a3d044b350de
2024-07-12 15:23:10 -07:00
James Zern
cc7ff5459a cost_enc: make VP8CalculateLevelCosts[] static
This table is unused outside of cost_enc.c.

Change-Id: I0aa46554b8470fb09a7ffeae0e98d2356b40b671
2024-07-12 15:23:10 -07:00
James Zern
4e2828bae8 vp8l_dec: make VP8LClear() static
This function is unused outside of vp8l_dec.c.

Change-Id: I16733a44ea024ca9601c098641a3cd464bed2b53
2024-07-12 15:22:20 -07:00
James Zern
d742b24a88 Intra16Preds_NEON: fix truemotion saturation
This needs to be done with signed saturation as the sum may be negative.

fixes mismatch with C code after:
3bfb05e3 Add AArch64 Neon implementation of Intra16Preds

Change-Id: I017e939d7155cc3489ceb76fc8ad50ac9917f23d
2024-07-11 13:37:06 -07:00
James Zern
c7bb4cb585 Intra4Preds_NEON: fix truemotion saturation
This needs to be done with signed saturation as the sum may be negative.

fixes mismatch with C code after:
baa93808 Add AArch64 Neon implementation of Intra4Preds

Change-Id: I190c3d7f78cfd2c7ae83fb7059de41e307abda36
2024-07-11 13:37:06 -07:00
Vincent Rabaud
952a989b1b Merge "Remove TODO now that log is using fixed point." into main 2024-07-11 20:11:37 +00:00
Vincent Rabaud
dde11574b0 Remove TODO now that log is using fixed point.
Bug: webp:499

Change-Id: I39ab340ec6b5932db7535c6b7f31843c28de8415
2024-07-11 20:11:03 +00:00
Vincent Rabaud
a1ca153d51 Fix hidden myerr in my_error_exit
Change-Id: I0e3660eff2f6a20446b6fcd2925312757fda424c
2024-07-11 15:59:57 +02:00
James Zern
3bd9420289 Merge changes Iff6e47ed,I24c67cd5,Id781e761 into main
* changes:
  Use QuantizeBlock_NEON for VP8EncQuantizeBlockWHT on Arm
  Add AArch64 Neon implementation of Intra16Preds
  Add AArch64 Neon implementation of Intra4Preds
2024-07-11 02:04:42 +00:00
Vincent Rabaud
d27d246e42 Merge "Convert VP8LFastSLog2 to fixed point" into main 2024-07-10 21:52:39 +00:00
Vincent Rabaud
4838611f91 Disable msg_code use in fuzzing mode
bug:oss-fuzz:70102
bug:oss-fuzz:70112
Change-Id: I519c991c784bccb4bbaec622281f81015ab479a4
2024-07-10 22:55:21 +02:00
Istvan Stefan
314a142a34 Use QuantizeBlock_NEON for VP8EncQuantizeBlockWHT on Arm
Use the Neon implementation instead of falling back to
QuantizeBlock_C.

Change-Id: Iff6e47eda353cbaa9766f75040fa63aa34607816
2024-07-10 14:48:38 +01:00
Istvan Stefan
3bfb05e38c Add AArch64 Neon implementation of Intra16Preds
Add a Neon implementation of Intra16Preds for use on 64-bit Arm
platforms. (This implementation cannot be used on 32-bit Arm
platforms as it makes use of a number of AArch64-only Neon
instructions.)

Change-Id: I24c67cd54b66307e3924fd332c2795fd7422f082
2024-07-10 14:48:38 +01:00
Istvan Stefan
baa93808d9 Add AArch64 Neon implementation of Intra4Preds
Add Neon implementation of Intra4Preds for use on 64-bit Arm
platforms. (The same implementation cannot be used for 32-bit Arm
platforms as it uses a number of AArch64-only Neon instructions.)

Change-Id: Id781e7614f4e8e876dfeecd95cfc85e04611d8c6
2024-07-10 14:48:26 +01:00
Vincent Rabaud
41a5e582c2 Fix errors when compiling code as C++
Change-Id: Iba94e24e764038640f39d61fb2bc9cfb3434cc8f
2024-07-10 10:30:48 +02:00
Vincent Rabaud
fb444b692b Convert VP8LFastSLog2 to fixed point
Speedups: 1% with '-lossless', 2% with '-lossless -q 100 -m6'

Change-Id: I1d79ea8e3e9e4bac7bcea4d7cbcc1bd56273988e
2024-07-09 16:42:21 +02:00
Vincent Rabaud
c1c89f5189 Fix WEBP_NODISCARD comment and C++ version
Change-Id: I8b94974a46b7ac7d9bce179a48655ba8d9700edf
2024-07-09 14:24:00 +02:00
Vincent Rabaud
66408c2c7c Switch the histogram_enc.h API to fixed point
Speedups: 4% with '-lossless', 8% with '-lossless -q 100 -m6'

Change-Id: I8f1c244b290d48132c1edc6a1c9fc3f79fef68ec
2024-07-09 13:39:45 +02:00
Vincent Rabaud
ac1e410ded Remove leftover tiff dep
Change-Id: I880ee0f8d0b80fb0f0e476baaf91fe545195c029
2024-07-05 13:39:23 +02:00
Vincent Rabaud
b78d39571f Disable TIFF on fuzztest.
oss-fuzz does not support dynamic libraries so we stick to
static. But libtiff.a has undefined symbols on Ubuntu, so we
have to disable TIFF.

Change-Id: Ibd1932f5780a0af51b6b398ae6415eed8685a0be
2024-07-05 11:26:12 +02:00
Vincent Rabaud
cff21a7d87 Do not build statically on oss-fuzz.
This is to get TIFF support for imageio.

Change-Id: I3c9aea4b72661926568dc777644b7a9ddd499726
2024-07-04 15:44:12 +02:00
Vincent Rabaud
6853a8e5ac Merge "Move more internal fuzzers to public." into main 2024-07-02 13:47:01 +00:00
Vincent Rabaud
9bc09db4b8 Merge "Convert VP8LFastLog2 to fixed point" into main 2024-07-02 09:48:16 +00:00
Vincent Rabaud
0a9f1c19f8 Convert VP8LFastLog2 to fixed point
The lossless encoding speed-ups are:
- up to 1% with default parameters
- up to 4% in cruncher mode: -q 100 -m 6

Change-Id: Id92d4bad0b0a2c28c8aa9ff5280eea5717017f30
2024-07-02 10:29:38 +02:00
Vincent Rabaud
db0cb9c27e Move more internal fuzzers to public.
Change-Id: Idde75f374264666e4c54a17b1606464ad5d00d9c
2024-06-28 16:59:18 +02:00
James Zern
ff2b5b15ae Merge "advanced_api_fuzzer.cc: use crop dims in OOM check" into main 2024-06-26 18:30:07 +00:00
Vincent Rabaud
c4af79d053 Put 0 at the end of a palette and do not store it.
This only applies to kSortedDefault and kMinimizeDelta.

Change-Id: I9d4178406ed2ef91c5c55f0a1919cfc6605fedf9
2024-06-25 14:46:05 +02:00
Vincent Rabaud
0ec80aef3d Delete last references to delta palettization
Change-Id: I1f931d3aa587d2ae82895ae7c7f4c94fb82fbfb1
2024-06-25 10:53:43 +02:00
James Zern
96d79f8481 advanced_api_fuzzer.cc: use crop dims in OOM check
Apply crop dimensions before calculating scaled width/height to ensure
the check against fuzz_utils::kFuzzPxLimit will use the same dimensions
as the decoder.

Bug: oss-fuzz:69873
Change-Id: Icd0862eadf8575135b6d53376acc79d14733a0e5
2024-06-24 16:35:06 -07:00
Vincent Rabaud
c35c7e0240 Fix huffman fuzzer to not leak.
That was obviously intentional to see if the new fuzzer was
working :)

Bug: oss-fuzz=69825
Change-Id: Ie9465bb6225999fd792b712cc585ca3ee1ec528a
2024-06-24 10:13:16 +02:00
Vincent Rabaud
f2fe8decce Bump fuzztest dependency.
Also do not restrict the oss-fuzz script to libfuzzer:
this allows new fuzzer engines to try the script as is.
The libfuzzer restriction is done upstream anyway.

Bug: oss-fuzz:69508
Change-Id: I15685bc7193bef3b9ccb0e0a30a6262e7bfb6fb9
2024-06-21 18:27:37 +02:00
Vincent Rabaud
9ce982fdf2 Fix fuzz tests to work on oss-fuzz
- the tests now build/run/check_build with libfuzzer on oss-fuzz
- centipede is removed as it builds/runs but do not check_build
(timeout due to arguments not parsed correctly)

Bug: oss-fuzz:69508

Change-Id: Id063565fc4cce02fc5e36c7d8499d6de9ff54345
2024-06-20 15:09:57 +02:00
Vincent Rabaud
3ba8af1a33 Do not escape quotes anymore in build.sh
cat is used now, not an echo of a "".

Change-Id: I36036ff2110f94a99bf1581c6c0d30326161314b
2024-06-11 13:35:44 +02:00
Vincent Rabaud
ea0e121b6a Allow centipede to be used as a fuzzing engine.
fuzztest is compatible with libfuzzer in compatibility mode, and
fully compatible with centipede by default.

Change-Id: I0c8e636df642dede16d394d678008c5e064094b3
2024-06-10 18:13:37 +02:00
James Zern
27731afd47 make VP8I4ModeOffsets & VP8MakeIntra4Preds static
These are unused outside of quant_enc.c.

Change-Id: I2c5cd0df28c25f279cd05667b327fea14f3fa50e
2024-06-06 19:07:48 -07:00
James Zern
ddd6245eb7 oss-fuzz/build.sh: use heredoc for script creation
Rather than a quoted multi-line echo.

Change-Id: Ib51fa5693f2946e2bc991dc66a6b3449e6ee61c0
2024-06-06 10:31:33 -07:00
James Zern
50074930e3 oss-fuzz/build.sh,cosmetics: fix indent
Change-Id: I1b9ddb5a531fc829fc7374ecefe31a38ac27e02c
2024-06-06 10:28:13 -07:00
Vincent Rabaud
20e92f7d40 Limit the possible fuzz engines.
Change-Id: I8f2fd84bc7175e4e74c4fb418fcc4f5549018ac3
2024-06-06 13:21:09 +02:00
Vincent Rabaud
4f200de591 Switch public fuzz tests to fuzztest.
Change-Id: I75afb65058690585bbf2671c27d6a99a87bcaab7
2024-06-05 14:08:27 +02:00
wrv
64186bb36c Add huffman_fuzzer to .gitignore
Change-Id: I1ec33a29beb1a9111e57c85ef67e4c4616908c56
2024-06-01 10:21:54 -05:00
Vincent Rabaud
0905f61c85 Move build script from oss-fuzz repo to here.
This requires a change in the oss-fuzz repo similar to
https://github.com/AOMediaCodec/libavif/blob/main/tests/oss-fuzz/build.sh

Change-Id: I7bcdb52dcec7e6edd926aea93988cd758ef9a854
2024-05-31 22:02:17 +02:00
wrv
e86787586b Fix link to Javascript documentation
Change-Id: Ia65d307570a3dff1fc6894abb42dfaaaaa74f086
2024-05-30 17:06:57 -05:00
wrv
5e5b8f0c95 Fix SSE2 Transform_AC3 function name
Change-Id: I5fda3221612beafc3548d2abfa7c1e3f686aaaf0
2024-05-29 21:41:14 -05:00
James Zern
45129ee027 Revert "Check all the rows."
This reverts commit ee26766a89a149afe5f73fdcb8f2493ec808f2b7.

This change also reverts the parent.

Revert "Increase the transform bits if possible."

This reverts commit 7ec51c591608333fd5e6fdddbee16e1d65bef3db.

These changes result in non-lossless encodes.

Bug: oss-fuzz:69231, oss-fuzz:69109, oss-fuzz:69208
Bug: b:341475869, b:342743143
Change-Id: Ia28f558992e0aa6f024af1ff66da52e0a5e26fa3
2024-05-25 11:00:32 -07:00
Vincent Rabaud
ee26766a89 Check all the rows.
A 3 by 1 image would not have its 1st and 3rd lines compared at
the second iteration.

BUG=oss-fuzz:69208

Change-Id: I9213e73995d31907f358310a0b7d5ebb21c1f8b2
2024-05-24 23:11:20 +02:00
Vincent Rabaud
7ec51c5916 Increase the transform bits if possible.
This brings minor size improvements because repetitive values in
the transform images are easily explainable through LZ77. Still,
it makes an upcoming pull request a bit more stable.

This is 971a03d8204c3ab1e12db8ae68ba6f919c615ade with a fix to
not forget to analyze the end of the line.
A const has also been added to match VP8LColorSpaceTransform's
signature.

Change-Id: Iae03216fef298c7abc96a766f8a799552b05ade5
2024-05-23 14:04:34 +02:00
James Zern
3cd16fd3e2 Revert "Increase the transform bits if possible."
This reverts commit 971a03d8204c3ab1e12db8ae68ba6f919c615ade.

Reason for revert:
This creates non-lossless encodes.

Original change's description:
> Increase the transform bits if possible.
>
> This brings minor size improvements because repetitive values in
> the transform images are easily explainable through LZ77. Still,
> it makes an upcoming pull request a bit more stable.
>
> Change-Id: I1c7135675cb59b5e27ca960738d74465f10d0deb

Bug: oss-fuzz:69109, b:341475869
Change-Id: I3b9f21a5498735eb3681e62fb35bf9f9c2ed4f9f
2024-05-20 22:25:57 +00:00
Vincent Rabaud
971a03d820 Increase the transform bits if possible.
This brings minor size improvements because repetitive values in
the transform images are easily explainable through LZ77. Still,
it makes an upcoming pull request a bit more stable.

Change-Id: I1c7135675cb59b5e27ca960738d74465f10d0deb
2024-05-17 15:19:03 +02:00
Vincent Rabaud
1bf198a22b Allow transform_bits to be different during encoding.
The spec allows it but it is currently forced to the same value for simplicity.

Change-Id: I26197dbf3342f7a72115cc7f7805c154313a2afb
2024-05-13 16:56:19 +02:00
Vincent Rabaud
1e462ca80e Define MAX_TRANSFORM_BITS according to the specification.
Change-Id: I0d575aa84e143bea56b55deb8f42b44e13dd5f1e
2024-05-07 09:16:02 +02:00
Vincent Rabaud
64d1ec23ac Use (MIN/NUM)_(TRANSFORM/HUFFMAN)_BITS where appropriate
Change-Id: I849ff8864f7abcc723dfe2b7ee0f290c8ee89c3f
2024-05-06 22:46:44 +02:00
Vincent Rabaud
a90160e11a Refactor histograms in predictors.
Replace the 2d histograms with uint32_t 1d versions (to avoid
pointer casting and to use the optimized VP8LAddVectorEq).

Change-Id: I90b0fe98390b49e3fd03e3484289571cf7ae6eca
2024-05-03 22:09:38 +02:00
Vincent Rabaud
a7aa7525b8 Fix some function declarations
- fix some function declarations to match the implementation
- fix some consts

Change-Id: I8c89f49ec68d3dd1db7f8ee5cac73777f52d2576
2024-05-03 20:10:46 +02:00
James Zern
68ff4e1efe Merge "jpegdec: add a hint for EOF/READ errors" into main 2024-05-02 20:53:54 +00:00
James Zern
79e7968ad0 jpegdec: add a hint for EOF/READ errors
`jpegtran -copy all` may be able to process the file into something
libjpeg can read.

Bug: webp:562
Change-Id: I27a8a7a841c1d8d54f47c7c52e289d9d8c549220
2024-05-01 12:32:47 -07:00
James Zern
d33455cd31 man/*: s/BUGS/REPORTING BUGS/
BUGS is described by the man-pages man page as:
A list of limitations, known defects or inconveniences, and other
questionable activities.

Change-Id: I2781d48d7a01c173fd24ac0b60af1a84aec31c3b
2024-05-01 10:39:00 -07:00
James Zern
a67ff735a2 normalize example exit status
Use EXIT_SUCCESS / EXIT_FAILURE in most cases as more granularity isn't
useful. For anim_diff, use 0 (success), 1 (image difference) and 2
(error) to align it with other diff utilities (diff, etc.).

Bug: webp:637
Change-Id: I52925de8622a5a4d2141883279d69a1d95ef9b12
2024-05-01 10:38:44 -07:00
James Zern
edc289092a upsampling_{neon,sse41}: fix int sanitizer warning
fixes warnings of the form:
/src/dsp/upsampling_sse41.c:170:1: runtime error: implicit conversion
  from type 'int' of value -16 (32-bit, signed) to type 'uintptr_t' (aka
  'unsigned long') changed the value to 18446744073709551600 (64-bit,
  unsigned)

this is the same change as was done previously in upsampling_sse2.c:
2ee786c7 upsampling_sse2.c: clear int sanitizer warnings

Change-Id: I36064d837ad1a7a118918c16a5551fc732dec2ff
2024-04-30 13:06:09 -07:00
James Zern
3cada4cef4 ImgIoUtilReadFile: check ftell() return
This avoids attempting to allocate 0 bytes if the call fails. (An
additional byte is added to the result to allow a '\0' to be appended.)

Bug: chromium:334120888
Change-Id: Ifcb8ff7744c567cbd08051aa04cc66acf936078d
2024-04-19 12:50:01 -07:00
James Zern
dc9505855e libwebp-1.4.0
- 4/12/2024: version 1.4.0
   This is a binary compatible release.
   * API changes:
     - libwebpmux: WebPAnimEncoderSetChunk, WebPAnimEncoderGetChunk,
                   WebPAnimEncoderDeleteChunk
     - libsharpyuv: SharpYuvOptionsInit, SharpYuvConvertWithOptions
     - extras: SharpYuvEstimate420Risk
   * further security related hardening in libwebp & examples
   * some minor optimizations in the lossless encoder
   * added WEBP_NODISCARD to report unused result warnings; enable with
     -DWEBP_ENABLE_NODISCARD=1
   * improvements and corrections in webp-container-spec.txt and
     webp-lossless-bitstream-spec.txt (#611)
   * miscellaneous warning, bug & build fixes (#615, #619, #632, #635)
 -----BEGIN PGP SIGNATURE-----
 
 iQIzBAABCgAdFiEEaw5rcJdt4wPt8vYB+cPWvbgjK10FAmYZ5dsACgkQ+cPWvbgj
 K11+Lg//cTnfLXYUZYI3coork1BG6E+r3bCvF6oncgdyOpQGM/7dExsPM43dBHBp
 uMHqapnxECSaga3g05+13R0ouhS72j3cuWBVkwmhrad7nxX7SGrCHIhaauJEAuyh
 ZX/MuMWVynAw9aq4UyCSLEfJ8bzRn/BmBb87zY8yBQP5fxUjGZ/hzRw4+pEoy9XU
 FA6QHv28agiswM111iOwIHQcAsKlUKy7SyULjFV40Q+wkF3tWTkOA9ecnsjXdDAU
 q3x06lZ4StvjyD7xwoxLL7E+sUAl0DcTluP1IMfmhzXOIl80OR0ec5qzGthaHSQZ
 ReDd9F0YqrEQOj371KkBg1d+VyBmwQoqh6vzKiEfqcm+wSDEd5WoOk7FmDbUlwmx
 EyRWrlxrmF7MsvjPYfQxxYfMcojewoVFFm43xgGO7pYg1b8yGEZ69So/3NWBqv6x
 ANXJCIcLHikz2u+v4n5A6eg6mFSW3pdPq8HpELTmefveXfIAGoA/6zcACqfNN+sO
 bt4lh7fUHTTFJmW5EJYkZmY725eY0nH7IQc0Jpc0iKMgtISTg2bxGHFeCB+GUTd0
 BCKBCCeIHIP7n7HnFGfGkNeas70QkN5lG5kDSLw4KR0TT1/We2MVZEsWeFPhQeYq
 myrMjhSOBn2sPKtknCL9WilQtBdLDPFBUIB3yHVXcP+HGCs8d/w=
 =+gXF
 -----END PGP SIGNATURE-----

Merge tag 'v1.4.0'

libwebp-1.4.0

- 4/12/2024: version 1.4.0
  This is a binary compatible release.
  * API changes:
    - libwebpmux: WebPAnimEncoderSetChunk, WebPAnimEncoderGetChunk,
                  WebPAnimEncoderDeleteChunk
    - libsharpyuv: SharpYuvOptionsInit, SharpYuvConvertWithOptions
    - extras: SharpYuvEstimate420Risk
  * further security related hardening in libwebp & examples
  * some minor optimizations in the lossless encoder
  * added WEBP_NODISCARD to report unused result warnings; enable with
    -DWEBP_ENABLE_NODISCARD=1
  * improvements and corrections in webp-container-spec.txt and
    webp-lossless-bitstream-spec.txt (#611)
  * miscellaneous warning, bug & build fixes (#615, #619, #632, #635)

Bug: webp:627

* tag 'v1.4.0':
  update ChangeLog
  update NEWS
  provide a way to opt-out/override WEBP_NODISCARD
  update ChangeLog
  NEWS: fix date
  vwebp: fix window title when options are given
  update NEWS
  bump version to 1.4.0
  update AUTHORS

Change-Id: Ib09dee63d968b50166c9177f571d68082e50ca76
2024-04-12 19:05:47 -07:00
James Zern
845d5476a8 update ChangeLog
Bug: webp:627
Change-Id: I67a011b62087a8ad64df3b5eb0a1c051adeea60f
2024-04-12 13:48:48 -07:00
James Zern
8a6a55bba8 update NEWS
add a note about WEBP_NODISCARD / WEBP_ENABLE_NODISCARD

Bug: webp:627
Change-Id: I018848eaef33dd47b922d6c95fc2842248cc02df
2024-04-12 12:34:22 -07:00
James Zern
cf7c5a5de8 provide a way to opt-out/override WEBP_NODISCARD
Bug: webp:627
Change-Id: I95ef89f37e5b7bf0f806bcfc6a295f5168b1bf67
2024-04-11 12:34:46 -07:00
James Zern
cc34288aa3 update ChangeLog
Bug: webm:627
Change-Id: I63243ecb39aa73a04d06426828e10d3e419922f6
2024-04-02 18:25:23 -07:00
James Zern
f13c08868a NEWS: fix date
Bug: webp:627
Change-Id: Ia3c620c2a0857e32ed9d85f08a0ef3caeddf6796
2024-04-02 17:41:32 -07:00
James Zern
7455595072 Merge "vwebp: fix window title when options are given" into 1.4.0 2024-04-02 16:56:08 +00:00
James Zern
d781646c29 vwebp: fix window title when options are given
Options can precede the file name. This still won't be correct for
Unicode file names, but an approximation will be displayed (with '?'s)
rather than the first character if kParams.file_name were used.
glutCreateWindow() looks like it will prohibit correcting this as it
expects an ASCII string.

Change-Id: I96986a178a0bbce6971d2ac415222d4a456ce1a3
2024-04-01 19:34:17 -07:00
James Zern
c2e394de91 update NEWS
Bug: webp:627
Change-Id: I7deea5d982ea9967c4be6b945452b9361e02eb85
2024-04-01 15:46:40 -07:00
James Zern
f6d15cb747 bump version to 1.4.0
libwebp{,decoder} - 1.4.0
libwebp libtool - 8.9.1
libwebpdecoder libtool - 4.9.1

mux - 1.4.0
libtool - 4.0.1

demux - 1.4.0
libtool - 2.15.0

sharpyuv - 0.4.0
libtool - 1.0.1

Bug: webp:627
Change-Id: I9a61d83ee92809de1c2501d1b4fb68aa38f98850
2024-04-01 15:37:40 -07:00
James Zern
57c388b8ff update AUTHORS
Bug: webp:627
Change-Id: I517fdc5201a8a44f1cdc64ef16f68e0ed9677937
2024-04-01 15:37:40 -07:00
James Zern
b3d1b2cbf7 Merge changes I26f4aa22,I83386b6c,I320ed1a2 into main
* changes:
  webp_js/*.html: fix canvas mapping
  cmake,wasm: simplify SDL2 related flags
  cmake: fix vwebp_sdl compile w/libsdl-org release
2024-04-01 20:19:51 +00:00
James Zern
07216886a7 webp-container-spec: fix VP8 chunk ref ('VP8'->'VP8 ')
Change-Id: Iad8317660c6be7c8044421d7517c95c5034609d7
2024-03-29 19:28:52 -07:00
James Zern
f88666eb47 webp_js/*.html: fix canvas mapping
after:
24d7f9cb Switch code to SDL2.

fixes:
webp_wasm.js:1 Uncaught TypeError: Cannot read properties of null
    (reading 'addEventListener')
    at Object.registerOrRemoveHandler (webp_wasm.js:1:101330)
    at registerMouseEventCallback (webp_wasm.js:1:154227)
    at _emscripten_set_mousemove_callback_on_thread (webp_wasm.js:1:155015)
    ...

The SDL2 port forces the canvas id to '#canvas':
324df6865a/src/video/emscripten/SDL_emscriptenvideo.c (L210)

This change maps '#output_canvas' to this entry in specialHTMLTargets[]:
https://emscripten.org/docs/api_reference/html5.h.html

https://github.com/libsdl-org/SDL/issues/5260 &
https://github.com/emscripten-ports/SDL2/issues/130 may also be related.

Change-Id: I26f4aa22b9d68b0fc45b83edfe6fe074b59a82a7
Test: emscripten 3.1.16
2024-03-29 12:53:05 -07:00
James Zern
e2c8f233ef cmake,wasm: simplify SDL2 related flags
Use the result of find_package(SDL2); the cmake module is available
prior to downloading the port. Previously the result of this call was
ignored. This also updates the flags to use the results of
SDL2_LIBRARIES which may be more future proof than specifying them
manually.

SDL2_INCLUDE_DIRS do not appear to be necessary with -sUSE_SDL2.

Based in part on:
d0b3e8efe3/ports/libwebp/0008-sdl.patch

Bug: b:301040580
Change-Id: I83386b6c3d9628e3f0d9d17f20d47338d0db044a
2024-03-28 19:23:51 -07:00
James Zern
d537cd3704 cmake: fix vwebp_sdl compile w/libsdl-org release
Prebuilt SDL2 releases from https://github.com/libsdl-org/SDL/releases
provide include/SDL.h. Test for this and set WEBP_HAVE_JUST_SDL_H
accordingly.

This was inspired by:
d0b3e8efe3/ports/libwebp/0008-sdl.patch

Bug: b:301040580
Change-Id: I320ed1a23352fc4035d491399fdba184dc927554
Test: cmake .. -DCMAKE_PREFIX_PATH=<path-to-sdl2>/cmake
2024-03-28 14:11:46 -07:00
James Zern
6c484cbf92 CMakeLists.txt: add missing WEBP_BUILD_EXTRAS check
And include directories to imageenc/imagedec. This fixes the build with
`-DWEBP_BUILD_ANIM_UTILS=OFF -DWEBP_BUILD_CWEBP=OFF
-DWEBP_BUILD_DWEBP=OFF -DWEBP_BUILD_GIF2WEBP=OFF
-DWEBP_BUILD_IMG2WEBP=OFF -DWEBP_BUILD_LIBWEBPMUX=OFF
-DWEBP_BUILD_VWEBP=OFF -DWEBP_BUILD_WEBPINFO=OFF
-DWEBP_BUILD_WEBPMUX=OFF` and image dependencies outside of default
include locations (e.g., /usr/include).

Patch from:
d0b3e8efe3/ports/libwebp/0010-fix_build.patch

Bug: b:301040580
Change-Id: I2b9ad81dfe52316b102ca46ab8c60c42de3c0000
2024-03-27 18:55:20 -07:00
James Zern
7b0bc2352b man/cwebp.1: add more detail to -partition_limit
-m and -q can also affect the encoder's ability to satisfy the
partition limit.

Bug: webp:634
Change-Id: I89ea2b037c0cf1e109c251f45c09378ce501862b
2024-03-26 13:00:35 -07:00
James Zern
3c0011bbd1 WebPMuxGetChunk: add an assert
assert idx != IDX_LAST_CHUNK to quiet a static analysis warning
(reported by Coverity):
  overrun-local: Overrunning array kChunks of 11 12-byte elements at
    element index 11 (byte offset 143) using index idx (which evaluates
    to 11).

Change-Id: I85ae159e338d5670c007f76277ffe94e7a1dcafc
2024-03-21 18:32:55 -07:00
James Zern
955a3d14ae Merge "muxread,MuxGet: add an assert" into main 2024-03-22 01:01:04 +00:00
James Zern
00abc0007c muxread,MuxGet: add an assert
assert idx != IDX_LAST_CHUNK to quiet a static analysis warning
(reported by Coverity):
  Indexing array kChunks of size 11 with idx.

Change-Id: I5e54b5c09d23c26abbd1a7919b6f828b35fe4f75
2024-03-20 12:36:37 -07:00
Vincent Rabaud
40e85a0b56 Have the window title reflect the filename.
This is from https://github.com/webmproject/libwebp/pull/3

Change-Id: Ia54f9b6a2ac0d078e931c088694924ed914c18fd
2024-03-20 14:33:54 +01:00
James Zern
1bf46358c4 man/cwebp.1: clarify -pass > 1 behavior w/o -size/-psnr
A PSNR value of 40dB will be used in this case.

Bug: webp:635
Change-Id: I74964a08a1f0a6b92ecfa482753a171ce6f3ae18
2024-03-14 19:34:39 -07:00
James Zern
eba03acb05 webp-container-spec: replace 'above' with 'earlier'
https://developers.google.com/style/word-list#above

Change-Id: Ib20395c00289d0e37f532b383dec0bf14d4bec73
2024-03-12 16:22:31 -07:00
James Zern
a16d30cb57 webp-container-spec: clarify chunk order requirements
based on comments from:
https://datatracker.ietf.org/doc/draft-zern-webp/ballot/#draft-zern-webp_robert-wilton

Change-Id: If2cd956b607c51b714e82e8eee7a1c4375c3c632
2024-03-11 14:01:40 -07:00
James Zern
8a7e911231 Merge "CMakeLists.txt: apply cmake-format" into main 2024-03-07 19:21:20 +00:00
Vincent Rabaud
7fac6c1bf2 Merge "Copy C code to not have multiplication overflow" into main 2024-03-07 12:14:57 +00:00
Vincent Rabaud
e2922e4390 Merge "Check for the presence of the ANDROID_ABI variable" into main 2024-03-07 08:54:42 +00:00
Vincent Rabaud
501d9274a7 Copy C code to not have multiplication overflow
Change-Id: I9375170ce1217921a334c5b93dc3e0084f976688
2024-03-07 09:22:20 +01:00
James Zern
fba7d62ee5 CMakeLists.txt: apply cmake-format
Change-Id: I23b848d6936e5dd3b6a56f1e3218da5ed6f2539b
2024-03-06 15:56:36 -08:00
James Zern
661c1b6641 Merge "windows exports: use dllexport attribute, instead of visibility." into main 2024-03-06 23:54:57 +00:00
Ozkan Sezer
8487860a8c windows exports: use dllexport attribute, instead of visibility.
With older toolchains, at the least, visibility attributes don't
work and all symbols are exported along with lots of unsupported
warnings.

Change-Id: I6ffe220b7589a6bda00f42c17ead35592de7cc5a
2024-03-07 01:14:37 +03:00
James Zern
8ea678b990 webp/mux.h: data lifetime note w/copy_data=0
The data mostly must persist until a call to Assemble() is made. If the
data is discarded and subsequent calls are made the behavior is
undefined.

Change-Id: I64b39034ae4663e9ca25b85040b6068d09dfac04
2024-03-06 11:11:24 -08:00
Vincent Rabaud
79e05c7f9f Check for the presence of the ANDROID_ABI variable
BUG=webp:632

Change-Id: I8169be37d7b739b206ffb6555d58ff79a34c3605
2024-03-06 14:50:30 +01:00
natewood
45f995a37e Expose functions for managing non-image chunks on WebPAnimEncoder
Change-Id: Ie6376267eee6df3517417b6cadafcdf6112bd854
2024-02-27 16:55:24 -08:00
James Zern
1fb9f3dcf1 gifdec: fix ErrorGIFNotAvailable() declaration
A void parameter list should be (void), not (). Fixes a
-Wstrict-prototypes warning.

Change-Id: I180efbf7c58956695359320072cce1171d79e377
2024-02-22 13:58:19 -08:00
James Zern
4723db65bc cosmetics: s/SANITY_CHECK/DCHECK/
'sanity' is not an inclusive term. This is a debug check so DCHECK
better shows the intent.

https://source.android.com/docs/setup/contribute/respectful-code

Change-Id: I4cdad3ef9ddf0404d26e46b8430e3ad1d715c5b2
2024-02-16 11:57:16 -08:00
James Zern
f4b9bc9ea1 clear -Wextra-semi-stmt warnings
This is available with clang. Clears warnings of the form:
  warning: empty expression statement has no effect; remove unnecessary
    ';' to silence this warning [-Wextra-semi-stmt]

As a side-effect it also clear a few -Wpedantic warnings with gcc:
  warning: ISO C does not allow extra ';' outside of a function
    [-Wpedantic]

Change-Id: I9295c767aad475c68b1fbbdff855b0d6650a25f5
2024-02-15 18:55:22 -08:00
Yannis Guyon
713982b883 Limit animdecoder_fuzzer to 320MB
Change-Id: Ic139ea870b98c58a2ecf46e81844f647fa0d2aba
2024-02-15 10:16:54 +00:00
Ozkan Sezer
cbe825e4cc cmake: fix sharpyuv simd files' build
Without this, when targeting x86, the compiler may not enable sse2
by default without -msse2 switch and therefore leaves WEBP_USE_SSE2
undefined and the SSE2 procedure won't be built.

Change-Id: If983df5cd12c962cf153094468fb549ec3f2c89b
2024-02-10 00:58:20 +03:00
James Zern
f99305e9e5 Makefile.vc: add ARM64 support
This enables the executables and the correct flags, it's a full desktop
platform. This is different from the old Windows mobile ARM target.

Change-Id: I610d1579e5dac7b0a6a50ab9194a5f1fef2fc907
2024-01-31 14:12:03 -08:00
James Zern
5efd6300dc mv SharpYuvEstimate420Risk to extras/
There's no need for this in libsharpyuv currently. This avoids an ABI
bump and library size increase.

Change-Id: I3e4c79052fdb4d628a2d36491547233dd0b6dc34
2024-01-12 15:25:27 -08:00
James Zern
e78e924f84 Makefile.vc: add sharpyuv_risk_table.obj
missed in:
d7a0506d Add YUV420 riskiness metric.

Change-Id: I5c3cfeaf6757792ac97902f587e04bf95fd4c5a1
2023-12-21 15:43:17 -08:00
Maryla
d7a0506dcc Add YUV420 riskiness metric.
Basic version for 8 bit only and C only (no simd).

Hidden behind a compile flag because the precompiled table is
fairly large (114kiB) and more than triples the size of the library.

Change-Id: I165c78e863df6a17b32f578bdbffe3adda9ac1d0
2023-12-05 10:17:15 +01:00
Vincent Rabaud
89c5b91746 Merge "BuildHuffmanTable check sorted[] array bounds before writing" into main 2023-11-22 15:45:18 +00:00
Vincent Rabaud
34c8074915 Remove alpha encoding pessimization.
This was created to have outputs readable with libwebp 0.4.x
Jelly-Bean and Kit-Kat are not supported anymore:
https://android-developers.googleblog.com/2021/07/google-play-services-discontinuing-jelly-bean.html
https://android-developers.googleblog.com/2023/07/google-play-services-discontinuing-updates-for-kitkat.html

Change-Id: I0b9ff3091412ce12eb50da301d7dacace9b54cc3
2023-11-14 14:18:12 +01:00
Vincent Rabaud
13d9c30b2b Add a WEBP_NODISCARD
Change-Id: Ice66f2aa6358474d728fb19c571edc86ed139a49
2023-11-10 13:57:07 +01:00
Vincent Rabaud
24d7f9cb6e Switch code to SDL2.
Also simplify wasm html (now that it is suppported by all browsers).

Change-Id: I352b08594b93d3dd7d44832d4328b3546ccc1b90
2023-10-28 23:36:35 +02:00
Jonathan Grant
0b56dedc98 BuildHuffmanTable check sorted[] array bounds before writing
Change-Id: I6a83f414e86311121451e9da26004dfc3ac9b21f
2023-10-27 00:17:27 +01:00
James Zern
a429c0de64 sharpyuv: convert some for() to do/while
With loops that don't use an immediate value in the conditional, this
can produce fewer tests.

Change-Id: I75401c51f7f7653be2f8c04d5f3c4ce04aefc3fc
2023-10-25 12:25:16 -07:00
James Zern
f0cd786125 DoSharpArgbToYuv: remove constant from loop
pre-calculating rgb_bit_depth + GetPrecisionShift(rgb_bit_depth)
produces better assembly with clang.

Change-Id: Ic4c3a620c1634fb5ea7001fa709d28c547769f79
2023-10-25 12:25:12 -07:00
James Zern
339231cc37 SharpYuvConvertWithOptions,cosmetics: fix formatting
Change-Id: Ieffe5877c6d715d168b0e9526d8fa1a946860771
2023-10-25 12:25:08 -07:00
Arthur Eubanks
307071f144 Remove medium/large code model-specific inline asm
Initially added to workaround gcc implementation issues that clang
does not have. (gcc hardcodes rbx as the PIC register, clang uses a
virtual register)

Change-Id: I1a3277abf02b1ff437b4aea4d28f4cb1c0176b80
2023-10-24 09:48:12 +02:00
Maryla
deadc339d5 Fix transfer functions where toGamma and toLinear are swapped.
Change-Id: I2f7ef84d227009181dad1c17883741bd98bf92b6
2023-10-12 16:57:32 +02:00
Maryla Ustarroz-Calonge
e7b78d4375 Merge "Fix bug in FromLinearLog100." into main 2023-10-12 08:28:34 +00:00
James Zern
15a1309efc Merge "webp-lossless-bitstream-spec: delete extra blank line" into main 2023-10-11 18:31:37 +00:00
Maryla
54ca975245 Fix bug in FromLinearLog100.
Change-Id: Iddfa7d16fe44e375a93deae9636eadc8bef42767
2023-10-11 15:08:24 +02:00
Vincent Rabaud
d2cb2d8cfc Dereference after NULL check.
Change-Id: Ia592affff075b2e00c150b89febcf676c7dcbbd2
2023-10-11 14:21:54 +02:00
James Zern
e9d5010718 webp-lossless-bitstream-spec: delete extra blank line
This clears a lint warning.

Change-Id: I87926cb6e2448332d7bbf7a3fe064e7aaf791a72
2023-10-10 15:55:16 -07:00
James Zern
786579711f Merge changes Ief442c90,Ie6e9c9a5 into main
* changes:
  webp-lossless-bitstream-spec: update variable names
  webp-lossless-bitstream-spec: simplify abstract
2023-10-10 18:16:58 +00:00
James Zern
e30a588456 webp-lossless-bitstream-spec: update variable names
This syncs the document with the draft RFC.

block_xsize -> transform_width
i -> distance_code
x/ysize -> image_width/height

Change-Id: Ief442c90157e82c518e8cb175a522c519b16ac69
2023-10-09 21:24:01 -07:00
James Zern
09ca136801 Merge "webp-container-spec: change assert to MUST be TRUE" into main 2023-10-10 00:26:53 +00:00
James Zern
38cb4fc0ea iosbuild,xcframeworkbuild: add SharpYuv framework
Provides the missing symbols in WebP.framework & WebP.xcframework:
Undefined symbols for architecture arm64:
  "_SharpYuvConvert", referenced from:
      _ImportYUVAFromRGBA in libwebp.a(libwebpencode_la-picture_csp_enc.o)
  "_SharpYuvGetConversionMatrix", referenced from:
      _ImportYUVAFromRGBA in libwebp.a(libwebpencode_la-picture_csp_enc.o)
  "_SharpYuvInit", referenced from:
      _ImportYUVAFromRGBA in libwebp.a(libwebpencode_la-picture_csp_enc.o)

This was missed in:
  c3d0c2d7 fix ios build scripts after sharpyuv dep added

Bug: webp:623
Change-Id: I1c4582ec2cee801b52867674d553900d6028bea8
Fixed: webp:623
2023-10-06 18:41:03 -07:00
James Zern
40afa9269b webp-lossless-bitstream-spec: simplify abstract
This syncs the document with the draft RFC.

Change-Id: Ie6e9c9a50527378cb1b24e2c130a0a09855fe96e
2023-10-06 11:46:24 -07:00
James Zern
9db21143d0 webp-container-spec: change assert to MUST be TRUE
in the 'Canvas Assembly from Frames' section. This matches the format in
the RFC draft; assert was not defined

Change-Id: Ib943b42f75fd1b4c281848f14e0626df9c868f59
2023-10-06 11:33:23 -07:00
Anuraag Agrawal
cdbf88aed2 Fix typo in API docs for incremental decoding
Change-Id: I410450a9d2c5192086da9fceaeaabefb7b0f5e57
2023-10-02 10:51:49 +02:00
Vincent Rabaud
05c469843c Reformat vcpkg build instructions.
Change-Id: I2ca7bd2feb85103c2377cc48daf3453dc5d859e4
2023-09-20 13:03:30 +02:00
Vincent Rabaud
8534f53960 Merge "Never send VP8_STATUS_SUSPENDED back in non-incremental." into main 2023-09-19 09:23:01 +00:00
Vincent Rabaud
35e197bdb7 Never send VP8_STATUS_SUSPENDED back in non-incremental.
Add the incremental_ member to the internal VP8Decoder,
to mimic VP8LDecoder

Change-Id: I34842e473bb566f51c18fe42afda63e66c0185b6
2023-09-19 10:28:02 +02:00
Jonliu1993
61441425fe Add vcpkg installation instructions
Change-Id: Id6396a9c31cb47bb7b1d743da7d5554505cd81a8
2023-09-15 13:59:30 +02:00
Masahiro Hanada
dce8397fec Fix next is invalid pointer when WebPSafeMalloc fails
When WebPSafeMalloc fails on VP8LHuffmanTablesAllocate,
next is not initialized to NULL.
VP8LHuffmanTablesDeallocate uses next to know the following nodes.
A patch fixes this issue.

Change-Id: I144ae84cd97e5bca227018ef1afa95361267902c
2023-09-15 13:59:30 +02:00
Frank
57c58105f3 Cmake: wrong public macro WEBP_INCLUDE_DIRS
Change-Id: I2220e5a094fe7ca6274e654bcedb6cca194663eb
2023-09-15 13:59:30 +02:00
Vincent Rabaud
c1ffd9ac75 Merge "vp8l_enc: fix non-C90 code" into main 2023-09-15 06:45:52 +00:00
Vincent Rabaud
a3965948e0 Merge changes If628bb93,Ic79f6309,I45f0db23 into main
* changes:
  Update lossless spec for two simple codes.
  Fix non-C90 code.
  Fix static analyzer warnings.
2023-09-15 06:44:42 +00:00
James Zern
f80e9b7e4c vp8l_enc: fix non-C90 code
Change-Id: I14b5288c1b9392dcb64db09b9852f1d7d47b3200
2023-09-14 16:21:04 -07:00
Vincent Rabaud
accd141da3 Update lossless spec for two simple codes.
Bug: webp:611
Change-Id: If628bb9332ebca6dd11b3561c3458e0f43ed54a3
2023-09-14 22:43:45 +02:00
Vincent Rabaud
ac17ffffcb Fix non-C90 code.
Thank you OpenCV: https://github.com/opencv/opencv/blob/
1e54e5657927996e86b155d89f51c7b5a73461d2/3rdparty/libwebp/
CMakeLists.txt#L24

Change-Id: Ic79f6309951f96c380e44b3167c1a36aae6d8903
2023-09-14 22:43:45 +02:00
Vincent Rabaud
433c7dca11 Fix static analyzer warnings.
Change-Id: I45f0db2310b1188809963af93240e3d438f807b8
2023-09-14 22:43:45 +02:00
James Zern
5fac76cf8d libwebp-1.3.2
- 9/13/2023: version 1.3.2
   This is a binary compatible release.
   * security fix for lossless decoder (chromium: #1479274, CVE-2023-4863)
 -----BEGIN PGP SIGNATURE-----
 
 iQIzBAABCgAdFiEEaw5rcJdt4wPt8vYB+cPWvbgjK10FAmUCZrcACgkQ+cPWvbgj
 K12xQBAAoR6PIMHsttDUvgrCmgM19HbDVYmN3fK1VSL2yhT2Nj71hloIBQ46j+pJ
 aLyOhLX92yvvDEORDvm12LO7e7VwbPxc66Lwh5q0AjgsliMD1sR0yFJHVnZTOrJ/
 ndF0G1dNkrwYYYLWPIDtxrfr2eyB0+el8zjUCkWuKn5WSeaiV3FNfjHmNjQsgf1K
 dyy4DHcmZb5N2eJ6OvsiGvp7JwOjTpoHmYB2TbqfzqbV3Wq/aWgLsuGffpcNiEgP
 i/GCTapAFTdYW7StqXUGWML0IV3E3CrcBYjlWJqR499/DTfX1jrNcyWbuR0iaM9e
 yKlYS4PeylB6xdyEGVNM+8j3Trt3YYxvTGO/ydh9D4CtjaJPzlLfs2646AaV6TFW
 34t9mUDm1ZqQP8yJNqpSF00iwH0LA5/dKTd9Xr/MSifB/nvF3aqQjEDHLeTgD6pS
 D0Kf6OkhBtRuDbw7bTMwTGOZ5Z/VLG9JFni9JPt/KylBANUXQAI8vn0jjZRmpAki
 ketic0AgoDtH1TmPA+AzbiPWxKuFHfH3CpoECsgbpJjuMjbJ7EuXDfiG6cUIqTrD
 Lk+r1jgkCTWikB0KnGxDaNnDx+U0iatH4XfuAqp0o3pEHdgH0p4Gk3Kb8oraSZNv
 Y9AM9TaUaGPZxdyXfyR8glvHSu3li15DF1l1Ewml9qSxuqs/4Ls=
 =Rv7k
 -----END PGP SIGNATURE-----

Merge tag 'v1.3.2'

libwebp-1.3.2

- 9/13/2023: version 1.3.2
  This is a binary compatible release.
  * security fix for lossless decoder (chromium: #1479274, CVE-2023-4863)

* tag 'v1.3.2':
  update ChangeLog
  update NEWS
  bump version to 1.3.2
  Fix OOB write in BuildHuffmanTable.

Bug: webp:620
Change-Id: I094a4fe6ab4f3f8ada6fb662ba9cc6ec0f3bdd87
2023-09-13 19:08:16 -07:00
James Zern
ca332209cb update ChangeLog
Bug: webp:620
Change-Id: I5703f222de7262736339dbfd6ba82f2039dfc850
2023-09-13 15:11:07 -07:00
James Zern
1ace578c91 update NEWS
Bug: webp:620
Change-Id: I393c58cc23ccf98fa3c5d1568f0689a36e64575b
2023-09-13 13:33:58 -07:00
James Zern
63234c4296 bump version to 1.3.2
libwebp{,decoder} - 1.3.2
libwebp libtool - 8.8.1
libwebpdecoder libtool - 4.8.1

mux - 1.3.2
libtool - 3.13.0

demux - 1.3.2
libtool - 2.14.0

sharpyuv - 0.2.1 (no change)
libtool - 0.1.0 (no change)

Bug: webp:620
Change-Id: I9a61d83ee92809de1c2501d1b4fb68aa38f98850
2023-09-13 13:24:49 -07:00
Vincent Rabaud
a35ea50de4 Add a fuzzer for ReadHuffmanCodes
Change-Id: If8c30aaa87c34007ae455a03daa7b3c0f22fc8c3
2023-09-12 23:41:29 +02:00
Vincent Rabaud
95ea5226c8 Fix invalid incremental decoding check.
The first condition is only necessary if we have not read enough
(enough being defined by src_last, not src_end which is the end
of the image).
The second condition now fits the comment below: "if not
incremental, and we are past the end of buffer".

BUG=oss-fuzz:62136

Change-Id: I0700f67c62db8e1c02c2e429a069a71e606a5e4f
2023-09-12 09:22:53 +02:00
Vincent Rabaud
2af26267cd Fix OOB write in BuildHuffmanTable.
First, BuildHuffmanTable is called to check if the data is valid.
If it is and the table is not big enough, more memory is allocated.

This will make sure that valid (but unoptimized because of unbalanced
codes) streams are still decodable.

Bug: chromium:1479274
Change-Id: I31c36dbf3aa78d35ecf38706b50464fd3d375741
(cherry picked from commit 902bc9190331343b2017211debcec8d2ab87e17a)
2023-09-07 15:14:39 -07:00
Vincent Rabaud
902bc91903 Fix OOB write in BuildHuffmanTable.
First, BuildHuffmanTable is called to check if the data is valid.
If it is and the table is not big enough, more memory is allocated.

This will make sure that valid (but unoptimized because of unbalanced
codes) streams are still decodable.

Bug: chromium:1479274
Change-Id: I31c36dbf3aa78d35ecf38706b50464fd3d375741
2023-09-07 21:16:03 +02:00
Vincent Rabaud
7ba44f80f3 Homogenize "__asm__ volatile" vs "asm volatile"
According to https://gcc.gnu.org/onlinedocs/gcc/extensions-to-the-c-language-family/how-to-use-inline-assembly-language-in-c-code.html

For the C language, the asm keyword is a GNU extension. When
writing C code that can be compiled with -ansi and the -std options
that select C dialects without GNU extensions, use __asm__ instead
of asm (see Alternate Keywords). For the C++ language, asm is a
standard keyword, but __asm__ can be used for code compiled with
-fno-asm.

Change-Id: I4af950e67c857c890290c1e3d9cc886da0748784
2023-09-06 17:15:05 +02:00
James Zern
68e271354e webp-container-spec: reorder example chunk layout
place the unknown 'XYZW' chunk at the end of the file to agree with the
order given by the 'Extended File Format' section.

Change-Id: I5cec5a61069a03f3487f5f9ff9209f5ead6de24c
2023-09-01 15:00:53 -07:00
James Zern
943b932a7e Merge changes I6a4d0a04,Ibc37b91e into main
* changes:
  decode.h: wrap idec example in /* */
  decode.h: fix decode example
2023-08-18 00:38:04 +00:00
James Zern
1cc94f9521 decode.h: wrap idec example in /* */
This makes it easier to read and copy/paste, though this is just rough
pseudo-code. It also matches the formatting of the advanced decoder
example.

Change-Id: I6a4d0a04a12bfc1f1956ac965ff4869cefc4f3df
2023-08-15 19:11:50 -07:00
James Zern
63acdd1e06 decode.h: fix decode example
spotted by tsutsui123 at gmail

Bug: webp:615
Change-Id: Ibc37b91e85427b2424b698043a40cce98bae356d
Fixed: webp:615
2023-08-15 19:07:11 -07:00
James Zern
aac5c5d0df ReadHuffmanCode: rm redundant num code lengths check
4 bits are read ([0, 15]) with 4 added to the result. The check that the
result is not > NUM_CODE_LENGTH_CODES (19) is redundant. This makes the
check an assert for documentation purposes.

webp-lossless-bitstream-spec.txt is updated accordingly.

Bug: webp:611
Change-Id: Ie461017dc9de3da4cfe6856543d3dcf58f53a180
2023-08-14 18:07:17 -07:00
James Zern
a2de25f6b6 webp-lossless-bitstream-spec: normalize list item case
In Section 6.2 Details, use uppercase after a :. This is more consistent
with the rest of the doc.

Bug: webp:611
Change-Id: I7ac862c90fd8e5fe0bad0dd5e3515d3095a6dc9a
2023-08-14 17:38:06 -07:00
James Zern
68820f0e53 webp-lossless-bitstream-spec: normalize pixel ref
x, y -> (x, y)

Bug: webp:611
Change-Id: Ic25ae76a9978156e7cd67ad17432ee1a1e172641
2023-08-14 17:38:03 -07:00
James Zern
cdb31aa806 webp-lossless-bitstream-spec: add missing periods
in ordered list in "6.2. Details". This is more consistent with the rest
of the document.

Bug: webp:611
Change-Id: Ie467c771afd5813a30855b24c80cf92673a5281c
2023-08-14 17:37:57 -07:00
James Zern
0535a8cf88 webp-lossless-bitstream-spec: fix grammar
...in same row... -> in the same row

Bug: webp:611
Change-Id: I837ab571084b206cc1a57c534c05cdcd0dfff0fa
2023-08-14 17:37:39 -07:00
James Zern
b6c4ce2635 normalize numbered list item format
from edits made during the RFC AUTH48 process

Change-Id: I82a5d78c0ea611e71927ffb13aa78ccdddfd6dd0
2023-08-09 13:51:38 -07:00
James Zern
dd7364c3ce Merge "palette.c: fix msvc warnings" into main 2023-07-28 20:05:58 +00:00
James Zern
c63c5df618 palette.c: fix msvc warnings
after:
1432ebba Refactor palette sorting computation.

fixes:
src\utils\palette.c(384): warning C4028: formal parameter 2 different
  from declaration
src\utils\palette.c(384): warning C4028: formal parameter 3 different
  from declaration
src\utils\palette.c(384): warning C4028: formal parameter 5 different
  from declaration

Change-Id: If29205f346e674108646045b7a3d90f078fed9b0
2023-07-28 09:07:11 -07:00
James Zern
0a2cad5115 webp-container-spec: move terms from intro section
to 'Terminology & Basics'

Change-Id: Iec9923086a2d339f12025c55da53b1e8a6919380
2023-07-27 16:18:57 -07:00
James Zern
dd88d2ff3e webp-lossless-bitstream-spec: color_cache -> color cache
The text is referring to the color cache, not a variable.

Bug: webp:611
Change-Id: Ife7e8246817ea0831993702bc050ed79998a0ee4
2023-07-27 12:41:04 -07:00
James Zern
6e75054736 Merge changes I644d7d39,Icf05491e,Ic02e6652,I63b11258 into main
* changes:
  webp-lossless-bitstream-spec: fix code blocks
  webp-lossless-bitstream-spec: block -> chunk
  webp-lossless-bitstream-spec: add some missing commas
  webp-lossless-bitstream-spec: normalize item text in 5.1
2023-07-27 19:34:20 +00:00
James Zern
67a7cc2b07 webp-lossless-bitstream-spec: fix code blocks
+ change "> 19" to "greater than 19" as it's referred to in prose

Bug: webp:611
Change-Id: I644d7d39f9c4a19050ff0256114873057aee95ef
2023-07-26 09:42:00 -07:00
Vincent Rabaud
1432ebbadb Refactor palette sorting computation.
This will ease the integration of new methods.

Change-Id: Icec3eddaa4ab9030d28ccfe579eb6dc13ded2f02
2023-07-26 10:25:14 +02:00
James Zern
cd436142f6 webp-lossless-bitstream-spec: block -> chunk
when referring to the RIFF chunk size; this is more consistent with
other documentation.

Bug: webp:611
Change-Id: Icf05491ee79f5c48fab0b4935da397b4e4e45a71
2023-07-25 22:10:06 -07:00
James Zern
3cb66f64b0 webp-lossless-bitstream-spec: add some missing commas
The serial comma change is based on the Chicago Manual of Style
(CMOS), 17th edition.

Bug: webp:611
Change-Id: Ic02e6652662608414c16e0fead2912781a47633d
2023-07-25 22:09:59 -07:00
James Zern
56471a53cf webp-lossless-bitstream-spec: normalize item text in 5.1
Makes references to earlier sections consistent. Based on RFC editor
update.

Bug: webp:611
Change-Id: I63b1125810a3d8afa957d392e98c68a632749d76
2023-07-25 22:08:51 -07:00
James Zern
af7fbfd2d9 vp8l_dec,ReadTransform: improve error status reporting
ExpandColorMap() can fail due to a memory allocation failure.

Found by Nallocfuzz (https://github.com/catenacyber/nallocfuzz).

Change-Id: I868c5db2fee18e876f4aa3b63e744d7297d1a91b
2023-07-21 16:30:50 -07:00
James Zern
7d8e0896e9 vp8l_dec: add VP8LSetError()
similar to VP8SetError(); the first error set takes precedence

Change-Id: Id00eb134cac328f72142a2ec0909e72768a6be0e
2023-07-21 16:30:49 -07:00
James Zern
a71ce1cf74 animencoder_fuzzer: fix error check w/Nallocfuzz
WebPAnimEncoderAdd() may fail due to muxer errors that are reported as
booleans. When running under the nallocfuzz engine, ignore all failures.

Found by Nallocfuzz (https://github.com/catenacyber/nallocfuzz).

Change-Id: I36589545d20ac30a67f7e09264146db085dee6ca
2023-07-21 16:30:48 -07:00
James Zern
e94b36d66d webp-lossless-bitstream-spec: relocate details from 5.1
Move the details given for meta prefix codes and the transforms from
"5.1. Roles of Image Data" to their corresponding sections.

Bug: webp:611
Change-Id: I750a3f45956d0a3928a22113180a2590ac1a36db
2023-07-21 15:50:38 -07:00
James Zern
84628e5611 webp-lossless-bitstream-spec: clarify image width changes
After processing the Color Indexing Transform the image width is
subsampled by the transform's width_bits.

Bug: webp:611
Change-Id: If8d2d47dbe05e5c8085fb3fb4c1b63552be9028b
2023-07-20 17:54:20 -07:00
James Zern
ee72299796 alpha_dec: add missing VP8SetError()
in AllocateAlphaPlane() and VP8DecompressAlphaRows().

Found by Nallocfuzz (https://github.com/catenacyber/nallocfuzz).

Change-Id: I39eb305abfe9f4d7915cce5d91e72917f482bc20
2023-07-18 16:25:29 -07:00
James Zern
0081693d61 enc_dec_fuzzer: use WebPDecode()
rather than WebPDecodeRGBA(). This allows finer grained error detection
and avoids an abort() when running under the nallocfuzz engine.

Change-Id: I8ff37f2fe7e1c8b39bd4a8bfe7b26ac41149ba42
2023-07-18 16:24:11 -07:00
James Zern
0fcb311cfc enc_dec_fuzzer: fix WebPEncode/pic.error_code check
pic.error_code may be set to VP8_ENC_ERROR_BAD_WRITE if the writer fails
due to a memory allocation failure.

Found by Nallocfuzz (https://github.com/catenacyber/nallocfuzz).

Change-Id: I912c9e5f9a37b78832c52d9ab6f0710967fbadac
2023-07-18 16:24:09 -07:00
James Zern
982c177c8a webp-lossless-bitstream-spec: fix struct member refs
remove trailing '_' to match the definition of ColorTransformElement

Bug: webp:611
Change-Id: I741213b389fc88473c72c64090a4733f51d87925
2023-07-14 15:13:27 -07:00
James Zern
56cf562570 webp-lossless-bitstream-spec: use RFC 7405 for ABNF
This allows for case sensitive literals.

Bug: webp:611
Change-Id: I5258c67ab12c48593d433449328fd85d461a05d2
2023-07-14 15:13:27 -07:00
James Zern
6c6b3fd317 webp-lossless-bitstream-spec,cosmetics: delete blank lines
This normalizes the spacing between sections and quiets some lint
warnings.

Bug: webp:611
Change-Id: Ic36eb08d55a566def74f746e2ec225c67ff8aecf
2023-07-14 15:12:35 -07:00
James Zern
29b9eb1517 Merge changes Id56ca4fd,I662bd1d7 into main
* changes:
  webp-lossless-bitstream-spec: add validity note for max_symbol
  webp-lossless-bitstream-spec: fix max_symbol definition
2023-07-13 20:43:51 +00:00
James Zern
47c0af8daf ReadHuffmanCodes: rm max_alphabet_size calc
This is unnecessary as green will have the largest value; the sizes are
currently: 256 + 24 + color_cache_size, 256, 40, in that order.

Change-Id: Ib9ce3292285a7b9c6089557b68a87184b68d17a5
2023-07-12 12:04:57 -07:00
James Zern
b92deba353 animencoder_fuzzer: no WebPAnimEncoderAssemble check w/nallocfuzz
This function may fail due to allocation failures. Use the
NALLOC_FUZZ_VERSION environment variable to detect the engine. This was
added in:
9c9a9883cc

Change-Id: Ia5b6fd9458ffa1f810152a10ab49a48c75d17687
2023-07-10 15:10:00 -07:00
James Zern
6be9bf8bae animencoder_fuzzer: fix leak on alloc failure
Change-Id: Id626145a336fc33c4a4158719957f3c96db156c8
2023-07-10 15:09:17 -07:00
James Zern
5c965e55dd vp8l_dec,cosmetics: add some /*param=*/ comments
Change-Id: I8912a5d8a8f550517e644e1af6b468b49505247f
2023-07-07 19:57:47 -07:00
James Zern
e4fc2f78c7 webp-lossless-bitstream-spec: add validity note for max_symbol
Bug: webp:611
Change-Id: Id56ca4fd0ad3cfc17c9c971281ccfb8ce7eaa2f4
2023-07-07 15:54:34 -07:00
James Zern
71916726b6 webp-lossless-bitstream-spec: fix max_symbol definition
If ReadBits(0) == 0, the value of max_symbol is set to the alphabet size
for each symbol type.

See vp8l_dec.c, ReadHuffmanCode(), which passes alphabet_size to
ReadHuffmanCodeLengths() as num_symbols, and ReadHuffmanCodeLengths()
then sets max_symbol to that.

Bug: webp:611
Change-Id: I662bd1d7f372e7f2e9c71cc86f87aefd02f36647
2023-07-07 15:54:34 -07:00
Vincent Rabaud
eac3bd5c53 Have the palette code be in its own file.
Change-Id: I099a342effedd9f451c94d00a14aead27079e6cc
2023-07-06 22:09:24 +02:00
Vincent Rabaud
e2c85878f6 Add an initializer for the SharpYuvOptions struct.
Change-Id: I36510bc361b040d3d3e7d261ab67b24ffc3013a6
2023-07-01 21:15:37 +02:00
James Zern
4222b00679 libwebp-1.3.1
- 6/23/2023: version 1.3.1
   This is a binary compatible release.
   * security fixes for lossless encoder (#603, chromium: #1420107, #1455619,
     CVE-2023-1999)
   * improve error reporting through WebPPicture error codes
   * fix upsampling for RGB565 and RGBA4444 in NEON builds
   * img2webp: add -sharp_yuv & -near_lossless
   * Windows builds:
     - fix compatibility with clang-cl (#607)
     - improve Arm64 performance with cl.exe
     - add Arm64EC support
   * fix webp_js with emcc >= 3.1.27 (stack size change, #614)
   * CMake fixes (#592, #610, #612)
   * further updates to the container and lossless bitstream docs (#581, #611)
 -----BEGIN PGP SIGNATURE-----
 
 iQIzBAABCgAdFiEEaw5rcJdt4wPt8vYB+cPWvbgjK10FAmSc53oACgkQ+cPWvbgj
 K120Fg//f0JkK3oKnO8P4B5XSAK26/5845xBPU8D06UuUqhct+mjfF5kM1CFxxex
 49W4rT7RJCpgGlwmRFFgRB3a9j7cW4C+Kt5MAfM++vudVrxnpnX6o3rdVDQ60PEZ
 C4T5u2jio/HuZAkPWYwwmIAz1vfqTjYpi0D12hn7yoBoketGcISlMuTgmwfjyQKg
 bn3JcjcjKtERfXSH36aCtnGAXJdf0Ok2WJtwS4kAcZiMByi5wf0AdEK0pnhmE3Y6
 YFPc0/RM50RXITnsDxmLZVRqpsAYr4l3RZvHwDDWVFMELWBsGWNF/kgzWlZ3/KjO
 4CUPE+810P4oVGJuRZ8++0hMSD0L1qh17awElpqLoBlDXfS1fEIw5QodbmoJzi0H
 mhiLH7fIZlpjoZyWuwNCzlkhykRLO4cEIaxxq28p5eoC70LXsv77rWqomfAja/6/
 88BQz6wrxHr0k4MmdOa+G8B5sMOBRVXXeW4bP1XCVGUfk8FN2rz0vlhbHk8sx/6/
 jqW19Bk3t2QnUZschBi1GKHKa0KkefFhTezTm/CV4fPmT50Z4k/+TTjJ6snSxAAX
 oYabJDtVARLgPxOcN64Hbsy1t5L9pWGLTfwbYBTVipX4lmofL9SHhgyg6oYVnZd5
 qbCVdqpYOOrbXXT/AByOuzo3tuaLMd8Ytas0I5/HHnI6QCTthg0=
 =/atT
 -----END PGP SIGNATURE-----

Merge tag 'v1.3.1'

libwebp-1.3.1

- 6/23/2023: version 1.3.1
  This is a binary compatible release.
  * security fixes for lossless encoder (#603, chromium: #1420107, #1455619,
    CVE-2023-1999)
  * improve error reporting through WebPPicture error codes
  * fix upsampling for RGB565 and RGBA4444 in NEON builds
  * img2webp: add -sharp_yuv & -near_lossless
  * Windows builds:
    - fix compatibility with clang-cl (#607)
    - improve Arm64 performance with cl.exe
    - add Arm64EC support
  * fix webp_js with emcc >= 3.1.27 (stack size change, #614)
  * CMake fixes (#592, #610, #612)
  * further updates to the container and lossless bitstream docs (#581, #611)

* tag 'v1.3.1':
  update ChangeLog
  update NEWS
  enc/*: normalize WebPEncodingSetError() calls
  enc/*: add missing WebPEncodingSetError() calls
  EncodeAlphaInternal: add missing error check
  vp8l_enc,WriteImage: add missing error check
  muxread,MuxImageParse: add missing error checks
  cmake,emscripten: explicitly set stack size
  WebPDecodeYUV: check u/v/stride/uv_stride ptrs
  Call png_get_channels() to see if image has alpha
  update ChangeLog
  update NEWS
  bump version to 1.3.1
  update AUTHORS
  update .mailmap

Bug: webp:608
Bug: b/281615350
Change-Id: Ic3e1956c92fef0ae22040bbc3e81b297c65008af
2023-06-28 19:34:13 -07:00
Vincent Rabaud
25d94f473b Implement more transfer functions in libsharpyuv
This is inspired by https://github.com/AOMediaCodec/libavif/pull/444/files

Change-Id: I98fae61696b3b8bbc1b5941e7950810d3ac3d588
2023-06-28 11:43:37 +02:00
James Zern
2153a6797c Merge changes Id0300937,I5dba5ccf,I57bb68e0,I2dba7b4e,I172aca36, ... into main
* changes:
  webp-lossless-bitstream-spec: add PredictorTransformOutput
  webp-lossless-bitstream-spec: fix RIFF-header ABNF
  webp-lossless-bitstream-spec: split LZ77 Backward Ref section
  webp-lossless-bitstream-spec: split Meta Prefix Codes section
  webp-lossless-bitstream-spec: note transform order
  webp-lossless-bitstream-spec: update transformations text
2023-06-27 21:56:43 +00:00
James Zern
4298e9765c webp-lossless-bitstream-spec: add PredictorTransformOutput
Describe the addition of the residual value to the predicted value.

Bug: webp:611
Change-Id: Id0300937eeebbafec3b2cd15376c56418c98a3bf
2023-06-26 12:51:36 -07:00
James Zern
cd7e02bece webp-lossless-bitstream-spec: fix RIFF-header ABNF
0x2f is a part of the image header, not RIFF header

Bug: webp:611
Change-Id: I5dba5ccfebeb25586723a1f3e00eebc317806928
2023-06-26 12:51:36 -07:00
James Zern
6c3845f9e0 webp-lossless-bitstream-spec: split LZ77 Backward Ref section
Make Distance Mapping its section for ease of reference.

Bug: webp:611
Change-Id: I57bb68e0fcf4d23ce0013f327adce93c6377be3a
2023-06-26 12:51:36 -07:00
James Zern
7f1b6799db webp-lossless-bitstream-spec: split Meta Prefix Codes section
Make Entropy Image and Interpretation of Meta Prefix Codes their own
section for ease of reference.

Bug: webp:611
Change-Id: I2dba7b4efd02d8bb250810ebff42ac1687262804
2023-06-26 12:51:36 -07:00
James Zern
7b634d8f0c webp-lossless-bitstream-spec: note transform order
transforms are applied in reverse bitstream order.

Bug: webp:611
Change-Id: I172aca36bbd5c3358a71b0acb49c5704ceee63d7
2023-06-26 12:51:36 -07:00
James Zern
6d6d4915ce webp-lossless-bitstream-spec: update transformations text
follow up to:
29c9f2d4 webp-lossless-bitstream-spec: minor wording updates

Universally use 'transform' over 'transformation'. The doc generally
uses 'transform' to talk about the individual transforms themselves as
well as their related data.

Bug: webp:611
Change-Id: I097701873bbc440bd399ab5440a914a14f7c62f6
2023-06-26 12:50:39 -07:00
James Zern
fd7bb21c0c update ChangeLog
Bug: webp:608
Change-Id: Id619a5e39a71d1372fd2209774f4f57d87712aa7
2023-06-23 11:52:38 -07:00
James Zern
e1adea50ed update NEWS
Bug: webp:608
Change-Id: I8c09742daa8502e7a1fdc626afa3b747e03569bf
2023-06-23 10:16:35 -07:00
James Zern
6b1c722a5b lossless_common.h,cosmetics: fix a typo
Change-Id: I22d2f96fa1fd2e3c9f059c26996fb11d998159a9
2023-06-22 18:31:36 -07:00
James Zern
08d60d6006 webp-lossless-bitstream-spec: split code length section
Make Simple / Normal Code Length Code their own section for ease of
reference.

Bug: webp:611
Change-Id: I1e6ed50d98f9258cacb163d2059716b5356e8b6f
2023-06-21 19:20:12 -07:00
James Zern
7a12afcc54 webp-lossless-bitstream-spec: rm unused anchor
The last use of #decoding-the-code-lengths was removed in:
86f94ee0 Update lossless spec with Huffman codes.

Also remove the redundant section header associated with it.

Bug: webp:611
Change-Id: I7f6bb1a1b75255324f185f4591313d9e6d49d1e9
2023-06-21 19:16:39 -07:00
James Zern
4339332038 enc/*: normalize WebPEncodingSetError() calls
return WebPEncodingSetError() directly where possible (it returns 0 /
failure for convenience).

Change-Id: I89a937778886c15ecbbe078af5b4c8c89ef0f9af
2023-06-21 16:43:00 -07:00
James Zern
287fdefe95 enc/*: add missing WebPEncodingSetError() calls
Users of the encoder (including anim_encode.c) and areas of the encoder
itself rely on the status returned via WebPPicture.

Change-Id: Id786176b8ac3b2329d1e41b9dacbb8dcc5d822e4
2023-06-21 16:43:00 -07:00
James Zern
c3bd7cff2e EncodeAlphaInternal: add missing error check
VP8LBitWriterFinish() may cause the VP8LBitWriter's buffer to be grown.
If that allocation fails, VP8LBitWriterNumBytes() will return a size
larger than the current allocation resulting in a heap overwrite of the
missing bytes.

==13==ERROR: AddressSanitizer: heap-buffer-overflow on address
0x61900005b880 at pc 0x00000049ffc1 bp 0x7fff144f5b40 sp 0x7fff144f5310
READ of size 1028 at 0x61900005b880 thread T0
    #0 0x49ffc0 in __asan_memcpy
    #1 0x695861 in VP8BitWriterAppend src/utils/bit_writer_utils.c:186:3
    #2 0x65acf9 in EncodeAlphaInternal src/enc/alpha_enc.c:169:14

Found by Nallocfuzz (https://github.com/catenacyber/nallocfuzz).

This is the same issue that was fixed in the non-alpha lossless path in:
d49cfbb3 vp8l_enc,WriteImage: add missing error check

Bug: chromium:1455619
Change-Id: I6bd10de213707d3d6b7ce3d0d2b3942af45d317f
2023-06-21 16:43:00 -07:00
James Zern
14a9dbfba0 webp-lossless-bitstream-spec: refine single node text
Remove the ambiguous 'should' which in other contexts might result in
questions as to whether it is a SHOULD or a MUST.

Change-Id: I9b396187ebde5ea5a0dbaf42daee6acf541258cd
2023-06-20 19:30:20 -07:00
Vincent Rabaud
64819c7cf3 Implement ExtractGreen_SSE2
Change-Id: I74f50e0c01603a640aa8cf7c9658d477e696ea8a
2023-06-19 13:31:46 +02:00
James Zern
d49cfbb348 vp8l_enc,WriteImage: add missing error check
VP8LBitWriterFinish() may cause the VP8LBitWriter's buffer to be grown.
If that allocation fails, VP8LBitWriterNumBytes() will return a size
larger than the current allocation resulting in a heap overwrite of the
missing bytes.

==3531848==ERROR: AddressSanitizer: heap-buffer-overflow on address
0x61d000000880 at pc 0x556eddfa1007 bp 0x7ffe434c7a90 sp 0x7ffe434c7260
READ of size 2052 at 0x61d000000880 thread T0
    #0 0x556eddfa1006 in __asan_memcpy
    #1 0x556eddfeeccf in WebPMemoryWrite src/enc/picture_enc.c:220:5
    #2 0x556ede0f9f87 in WriteImage src/enc/vp8l_enc.c:1454:8

Found by Nallocfuzz (https://github.com/catenacyber/nallocfuzz).

Change-Id: Ib1c9454c2c51849b0ba58c5347e6bd5b02a12fbe
2023-06-15 15:09:10 -07:00
James Zern
2e5a9ec3b6 muxread,MuxImageParse: add missing error checks
This prevents leaks should an allocation fail.

Spotted by Philippe Antoine (p dot antoine at catenacyber dot fr)
and https://github.com/catenacyber/nallocfuzz.

Change-Id: I07a8a475a282b18bf2f9015cc5b1120772babd48
2023-06-14 13:53:59 -07:00
James Zern
ebb6f949f4 cmake,emscripten: explicitly set stack size
The default was changed from 5MB to 64KB in 3.1.27 [1] causing image
decodes to fail. This restores the old default. In testing, 1536KB was
enough for the sample image, 1024KB was not.

[1]: https://github.com/emscripten-core/emscripten/blob/main/ChangeLog.md#3127---112922

Bug: webp:614
Change-Id: I1ff7afc72fa49d88d2efe88d2a04dfadbea3b1a5
Fixed: webp:614
Test: emcc 3.1.18 & 3.1.41
2023-06-13 21:47:52 -07:00
James Zern
59a2b1f9e3 WebPDecodeYUV: check u/v/stride/uv_stride ptrs
The buffers are made mandatory to match WebPDecodeYUVInto(), though this
conflicts with WebPIDecGetYUVA().

spotted by Oliver Kunz (okunz at google dot com)

Change-Id: Ic4740c53b75da6b93d4f3462303fb9be0ebfbd48
2023-06-13 17:39:45 -07:00
Wan-Teh Chang
8e965ccb0f Call png_get_channels() to see if image has alpha
After the png_read_update_info() call, call png_get_channels() to find
out if the image has alpha.

Change-Id: I6fa709418744b4de90d10ff96eaeefe454ffa290
2023-06-13 17:35:31 -07:00
James Zern
fe80fbbd6b webp-container-spec: add some missing commas
The serial comma change is based on the Chicago Manual of Style
(CMOS), 17th edition.

Change-Id: I642d6eb87492bb671869b25415c59b96b749c798
2023-06-12 22:03:01 -07:00
Pascal Massimino
e8ed317609 Merge "treat FILTER_NONE as a regular Unfilter[] call" into main 2023-06-12 14:19:04 +00:00
James Zern
03a7a04892 webp-lossless-bitstream-spec: rm redundant statement
Within the 'Entropy image' subsection, its clear this is what is being
described in the following paragraphs. Remove 'as described below' from
the first sentence.

Bug: webp:611
Change-Id: I365d69c8f6963cd826849ebdd96e46206d38b55d
2023-06-08 11:22:10 -07:00
James Zern
c437c7aace webp-lossless-bitstream-spec: mv up prefix code group def
Move this to the top-level of the "Details" section as prefix codes are
discussed in both "Decoding and Building the Prefix Codes" and "Decoding
of Meta Prefix Codes"

Bug: webp:611
Change-Id: Ide2dfedf081d6c94122ac16ecded968ed760f90c
2023-06-08 11:22:10 -07:00
James Zern
e4f17a31a7 webp-lossless-bitstream-spec: fix section reference
in the Transformations section describing decoding of the transform
data followed by the image data. The section numbers were adjusted by 1
in:
337cf69f webp-lossless-bitstream-spec: mv Nomenclature after Intro

Bug: webp:611
Change-Id: I4eede0d068fabdef51a140a0268436ab6629e8bb
2023-06-08 11:22:10 -07:00
James Zern
e2ecd5e937 webp-lossless-bitstream-spec: clarify ABNF syntax
Give some examples of repetition and binary value notation to limit the
need to follow the ABNF reference.

Bug: webp:611
Change-Id: I5b5a7632f011e1523b4a528653fe3630afba3e3e
2023-06-08 11:22:10 -07:00
James Zern
8b55425a56 webp-lossless-bitstream-spec: refine pixel copy text
in 6.2.3 Decoding Entropy-Coded Image Data.

The copying of distance code pixels cause some confusion during the
AUTH48 portion of the RFC review process.

Bug: webp:611
Change-Id: I78f547ae10c95f180355a4c93ec6d48acdc09141
2023-06-08 11:22:10 -07:00
James Zern
29c9f2d410 webp-lossless-bitstream-spec: minor wording updates
Mostly grammatical and addition/subtraction of commas from the AUTH48
portion of the RFC review process.

The serial comma changes are based on the Chicago Manual of Style
(CMOS), 17th edition.

Bug: webp:611
Change-Id: I5ae2d1cc0196009dbf3a4c2195cc73c2ef809b49
2023-06-08 11:21:55 -07:00
skal
6b02f66015 treat FILTER_NONE as a regular Unfilter[] call
Removes the hard-coded memcpy() in alpha-decoding.

Change-Id: I1dfd98db206893d7715a79d05a1bd9272690471a
2023-06-07 15:42:16 +02:00
James Zern
7f75c91ced webp-container-spec: fix location of informative msg
preprocessing bits are informative, not the filtering bits.

since:
391f9db9 Ordering of description of bits in container spec

Change-Id: I1c0da963074ce9cf4d33a13b4b36c9421b3e3b9d
2023-06-06 22:09:41 -07:00
James Zern
f6499943c4 webp-container-spec: consistently quote FourCCs
from the AUTH48 portion of the RFC review process

Change-Id: I3aad4b32c95517735e98ffa0120228ee24be6a4d
2023-06-06 18:47:20 -07:00
James Zern
49918af32b webp-container-spec: minor wording updates
Mostly grammatical and addition/subtraction of commas from the AUTH48
portion of the RFC review process.

The serial comma changes are based on the Chicago Manual of Style
(CMOS), 17th edition.

Change-Id: Ic75abf2e53e09c8a849e28e9c40e16c127515287
2023-06-05 18:26:34 -07:00
James Zern
7f0a341943 update ChangeLog
Bug: webp:608
Change-Id: Ic2188807076eee4c311ea20b999ba66265df9003
2023-06-02 09:37:51 -07:00
James Zern
bab7efbe73 update NEWS
Bug: webp:608
Change-Id: I96245759d1f0d7ccb42de47e10e18677a509feaa
2023-06-02 09:31:46 -07:00
James Zern
7138bf8fc3 bump version to 1.3.1
libwebp{,decoder} - 1.3.1
libwebp libtool - 8.7.1
libwebpdecoder libtool - 4.7.1

mux - 1.3.1
libtool - 3.12.0

demux - 1.3.1
libtool - 2.13.0

sharpyuv - 0.2.1
libtool - 0.1.0

Bug: webp:608
Change-Id: Ia80c54651a45caa1baa595f66820a3c1091d05c4
2023-06-01 18:56:12 -07:00
James Zern
435b4ded42 update AUTHORS
Bug: webp:608
Change-Id: I84f5ea6a9de352cfb216198aee9f6fd204cd1c46
2023-06-01 17:13:22 -07:00
James Zern
473512298a update .mailmap
Bug: webp:608
Change-Id: Ib7d6fd5d9537770f7e4c6a3290a5071f617f9b91
2023-06-01 17:13:21 -07:00
Vincent Rabaud
46bc4fc9d9 Merge "Switch ExtraCost to ints and implement it in SSE." into main 2023-06-01 11:05:12 +00:00
Vincent Rabaud
828b4ce062 Switch ExtraCost to ints and implement it in SSE.
The histograms count the occurrences of len/dist in entropy images.
Those (at most (1<<14) by (1<<14)) are sub-sampled by at least
MIN_HUFFMAN_BITS == 2, hence at most 24 bits in a histogram value.
At most, we multiply by 19 (because the longest histogram is of
size 40 and we do 40>>1, cf code) for the bit cost. So it all fits
in 32 bits.

Change-Id: Ife24b035f54794851ff31f2fac07901f724c6d7f
2023-06-01 10:17:13 +02:00
James Zern
ff6c7f4e71 CONTRIBUTING.md: add C style / cmake-format notes
Change-Id: I54ad0e27341025a6385a736d5a79ab8b6556a6ec
2023-05-30 13:54:12 -07:00
James Zern
dd530437f6 add .cmake-format.py
Created with cmake-format 0.6.13 using:
--dump-config --max-subgroups-hwrap 3 --first-comment-is-literal true

Change-Id: Ica8ca81086dcf466d4ea9693ffcb4e31aa0af002
2023-05-30 13:54:06 -07:00
James Zern
adbe2cb17e cmake,cosmetics: apply cmake-format
using the defaults present in 0.6.13 and setting
--first-comment-is-literal to avoid reflowing the copyright block and
--max-subgroups-hwrap 3 (default is 2) to avoid making some short set()
statements multi-line.

Change-Id: I3d90c025b5b2bb353046f4da19b8e442a044b902
2023-05-30 12:14:28 -07:00
James Zern
15b365083d doc/webp-container-spec: rm future codec comment
From the compression standpoint the file format is fixed at this point.

Change-Id: I788fcf7106e4840bf2f9950dfb099a7bab88b3bf
2023-05-26 15:48:31 -07:00
James Zern
c369c4bf0b doc/webp-lossless-bitstream-spec: improve link text
Reference the section by number, rather than 'this section'. Fixes a
lint warning:

Style notice: Write unique, descriptive link text that makes sense
without the surrounding text. Don't use phrases such as this document,
this article, or click here.
https://developers.google.com/style/link-text?hl=en#write-link-text

Change-Id: Iab33e4980528dddb5eed4404d25a4a746705131a
2023-05-26 15:48:28 -07:00
James Zern
1de35f476b doc/webp-container-spec: don't use 'currently'
Provide examples of formats that WebP performs better than.

https://developers.google.com/style/timeless-documentation

Change-Id: I4ead60be349d8650478788484989bde9ff18f6b6
2023-05-26 15:48:26 -07:00
James Zern
bb06a16ed1 doc/webp-container-spec: prefer present tense
https://developers.google.com/style/tense

Change-Id: I0cd4e1431cddc340adf5634c07f0c60635b3d4f2
2023-05-26 15:48:23 -07:00
James Zern
9f38b71e01 doc/webp-lossless-bitstream-spec: prefer present tense
https://developers.google.com/style/tense

Change-Id: I1151ad0f585afd388920e6910a30aca4c2d0cc32
2023-05-26 15:48:17 -07:00
James Zern
7acb6b829a doc/webp-container-spec: avoid i.e. & e.g.
Using 'that is' or 'for example' is recommended:
https://developers.google.com/style/abbreviations#dont-use

Change-Id: I25b45f5b41687dfbd25a0fbea4978d6bc8e44ad2
2023-05-26 15:48:12 -07:00
James Zern
4967e7cd78 doc/webp-lossless-bitstream-spec: avoid i.e. & e.g.
Using 'that is' or 'for example' is recommended:
https://developers.google.com/style/abbreviations#dont-use

Change-Id: I5d0dad2ee7ae5ebaf73661d5d79a4a2f1dc1802a
2023-05-26 15:48:09 -07:00
Vincent Rabaud
e3366659a0 Merge "Do not find_package image libraries if not needed." into main 2023-05-26 20:55:09 +00:00
Jyrki Alakuijala
428588ef90 clarify single leaf node trees and use of canonical prefix coding
remove AMENDED-notes (the last functional spec change to match with the
implementation is from 2014, other amendments are clarifications)

Bug: webp:581
Change-Id: Ic47739be0fd5a975fd734d6813567ca615304f1d
2023-05-25 17:25:48 -07:00
Vincent Rabaud
709ec152df Do not find_package image libraries if not needed.
This can be tested by running:
cmake ../ -DWEBP_BUILD_ANIM_UTILS=OFF -DWEBP_BUILD_CWEBP=OFF -DWEBP_BUILD_DWEBP=OFF -DWEBP_BUILD_GIF2WEBP=OFF -DWEBP_BUILD_IMG2WEBP=OFF -DWEBP_BUILD_EXTRAS=OFF

Bug: webp:612

Change-Id: Ie06d8f0535676d6d31ff0047ff7a6c026e16118e
2023-05-26 00:14:05 +02:00
James Zern
8dd80ef814 fuzz_utils.h: lower kFuzzPxLimit w/ASan
prevents some timeouts when decoding large jpeg source images.

Change-Id: I5cb6a10cbf0658a71fa9f49fc7da4c8d3e70fa00
2023-05-24 19:39:38 -07:00
Vincent Rabaud
8f187b9f7f Clean message calls in CMake
Change-Id: If1a959d9b8d544c9f4671c84880b1d0d11d3d285
2023-05-24 19:39:26 -07:00
James Zern
cba300781f WebPConfig.cmake.in: use calculated include path
when setting WebP_INCLUDE_DIRS; this value is relative to the
WebPConfig.cmake install location (${PACKAGE_PREFIX_DIR}/include) and
allows the install to be relocated after creation.

See also:
https://cmake.org/cmake/help/latest/module/CMakePackageConfigHelpers.html#example-generating-package-files

Bug: webp:610
Change-Id: If877625e96584a9808b0bba902e3f0b2a744aa60
Fixed: webp:610
2023-05-16 17:39:50 -07:00
James Zern
6cf9a76ae2 Merge "webp-lossless-bitstream-spec: remove use of 'dynamics'" into main 2023-05-16 22:00:51 +00:00
James Zern
740943b276 Merge "Specialize and optimize ITransform_SSE2 using do_two" into main 2023-05-16 19:57:48 +00:00
Yannis Guyon
2d547e24dc Compare kFuzzPxLimit to max_num_operations
To avoid timeouts caused by extreme rescaling such as
1x14339 -> 51712x1

Change-Id: I291d8e3b24155c190256411a506b7312abde8c45
2023-05-16 13:20:14 +02:00
Nozomi Isozaki
ac42dde1c5 Specialize and optimize ITransform_SSE2 using do_two
Change-Id: I976eb4a0cc4e669a02b55012d4aba1536f193781
2023-05-16 12:07:58 +09:00
James Zern
17e0ef1da5 webp-lossless-bitstream-spec: remove use of 'dynamics'
when bit width or precision are meant.

Change-Id: I89c2279e99b02c3e8a3bf39860364d2ce6d909c8
2023-05-12 15:10:30 -07:00
James Zern
ed27437160 neon.h,cosmetics: clear a couple lint warnings
Missing space after ,  [whitespace/comma] [3]

Change-Id: Ib8fc05c31cbef5318a752e98ab5106dad55d69e9
2023-05-02 17:32:14 -07:00
James Zern
3fb8294762 cpu.h,cosmetics: segment defines
Change-Id: Idc6dcd31e95de1c89b2a35b4c67fa66b92fe1a60
2023-05-02 12:28:50 -07:00
James Zern
0c496a4ff9 cpu.h: add WEBP_AARCH64
and define it to true for __aarch64__ and Win Arm64 + Visual Studio.

Microsoft's compiler (cl.exe) does not define __aarch64__, but relies on
_M_ARM64 & _M_ARM64EC

Bug: b/277254922
Change-Id: I20e4fa07a4031599db69e3d7ba9050345315ef51
2023-05-02 12:28:50 -07:00
James Zern
8151f388eb move VP8GetCPUInfo declaration to cpu.c
This avoids defining a version in each translation unit when using
__declspec(dllexport) which causes failures due to multiply defined
symbols with clang-cl:

lld-link: error: duplicate symbol: VP8GetCPUInfo
>>> defined at CMakeFiles\webpdecode.dir\Debug\src\dec\alpha_dec.c.obj
>>> defined at CMakeFiles\webpdsp.dir\Debug\src\dsp\dec_sse41.c.obj
...

Bug: webp:607
Change-Id: I6cd1ee75b3db984aa513263a05516e867a64925d
2023-04-27 12:39:13 -07:00
Yannis Guyon
916548c28c Make kFuzzPxLimit sanitizer dependent
Change-Id: Ib70f3c05fc845494c45cb357e70e9602a7e876a3
2023-04-25 08:14:22 +02:00
James Zern
4070b271ab advanced_api_fuzzer: reduce scaling limit
avoids another timeout while fuzzing with ASan

Change-Id: Ic5dfed15347bdd36f42274b8b2a25aec79fd568c
2023-04-18 16:56:23 -07:00
James Zern
761f49c3ab Merge "webp-lossless-bitstream-spec: add missing bits to ABNF" into main 2023-04-13 20:53:32 +00:00
James Zern
84d04c4845 webp-lossless-bitstream-spec: add missing bits to ABNF
alpha-is-used and the version number were missing before 'image-stream'

spotted by thakis@

Change-Id: I7a4f1d2e0f0962bb1a79a0400c229738159d88a5
2023-04-13 12:13:34 -07:00
James Zern
0696e1a7fb advanced_api_fuzzer: reduce scaling limit
avoids another timeout while fuzzing with ASan

Change-Id: Icf7209f3f93b894684ac7364864e4568b6b2c057
2023-04-11 12:16:39 -07:00
James Zern
93d88aa25b Merge "deps.cmake: remove unneeded header checks" into main 2023-04-11 19:13:10 +00:00
James Zern
118e0035df deps.cmake: remove unneeded header checks
These were picked up when matching autoconf's default checks and aren't
useful except to compare the generated config.h. Removing them speeds up
cmake, especially on windows where creating new processes is slow.

Change-Id: Ie891aad0a809af16357168d2ff7fd65922ee4011
2023-04-11 11:37:24 -07:00
James Zern
4c3d7018c0 webp-lossless-bitstream-spec: condense normal-prefix-code
Have this match simple-prefix-code and redirect to "Normal Code Length
Code" as the added indirection to 'code-length-code' and the undefined
'encoded-code-lengths' doesn't add much.

spotted by thakis@

Change-Id: Icd6b64a47c4e0001e93271d9ae5585be4a6d5906
2023-04-10 17:22:55 -07:00
James Zern
a6a09b3296 webp-lossless-bitstream-spec: fix 2 code typos
- add missing '(' in DIV_ROUND_UP
- in 6.2.2, rename 'pos' variable reference to match definition
  ('position')

spotted by thakis@

Change-Id: Ida3ed281c2c753ebbb0e1eb3c4ed04dadc79ca24
2023-04-10 17:18:52 -07:00
James Zern
50ac4f7c97 Merge "cpu.h: enable NEON w/_M_ARM64EC" into main 2023-04-07 20:31:49 +00:00
Yannis Guyon
4b7d7b4f2b Add contribution instructions
Change-Id: Icc58ef6c1e79e59977e0093973ad353237560e8e
2023-04-07 15:10:16 +02:00
James Zern
0afbd97b45 cpu.h: enable NEON w/_M_ARM64EC
The Arm64EC (Emulation Compatible) ABI was added for Windows 11 [1].

[1] https://learn.microsoft.com/en-us/windows/arm/arm64ec

Bug: b/277254922
Change-Id: I3767e1b3db61fa9c33eef7a9ed7abee7c502e36f
2023-04-06 13:49:36 -07:00
James Zern
349f4353dd Merge changes Ibd89e56b,Ic57e7f84,I89096614 into main
* changes:
  advanced_api_fuzzer: reduce scaling limit
  Skip slow scaling in libwebp advanced_api_fuzzer
  Reduce libwebp advanced_api_fuzzer threshold
2023-03-25 01:50:02 +00:00
James Zern
8f7513b7c0 upsampling_neon.c: fix WEBP_SWAP_16BIT_CSP check
this is always defined by default to 0 since:
v0.6.0-158-g663a6d9d unify the ALTERNATE_CODE flag usage

previously the !defined() check would cause a mismatch between C and
assembly.

Change-Id: Idca0b8e39ca90d63785fd4125aeb7af86c5aae61
2023-03-24 11:20:35 -07:00
James Zern
cbf624b561 advanced_api_fuzzer: reduce scaling limit
avoids another timeout while fuzzing with ASan

Change-Id: Ibd89e56bf936aeea040cd4c47ccae20960417ac0
2023-03-24 10:52:46 -07:00
yguyon@google.com
89edfdd1e9 Skip slow scaling in libwebp advanced_api_fuzzer
Change-Id: Ic57e7f8418afec42f042197a401aaf4cc047b23f
2023-03-24 10:52:43 -07:00
yguyon@google.com
859f19f74f Reduce libwebp advanced_api_fuzzer threshold
To avoid timeouts.

Change-Id: I8909661479cdbcb940bb44c6f9130906cab3f271
2023-03-24 10:52:40 -07:00
James Zern
a4f0483579 Merge changes Ic389aaa2,I329ccd79 into main
* changes:
  img2webp: normalize help output
  cwebp: reflow -near_lossless help text
2023-03-20 19:46:23 +00:00
James Zern
1275fac820 Makefile.vc: fix img2webp link w/dynamic cfg
add a dependency on libsharpyuv, which is needed after:
0825faa4c img2webp: add -sharp_yuv/-near_lossless

Change-Id: I2471549aa85a4ead6e00d6c459d9774ea4254eaa
2023-03-18 13:58:21 -07:00
James Zern
2fe27bb96d img2webp: normalize help output
this makes the output from img2webp and the ordering in doc/tools.md and
man/img2webp.1 consistent

Change-Id: Ic389aaa29c20128f2b87f231be383094602f125b
2023-03-17 15:37:55 -07:00
James Zern
24bed3d9fb cwebp: reflow -near_lossless help text
this matches the output from img2webp added in:
0825faa4 img2webp: add -sharp_yuv/-near_lossless

Change-Id: I329ccd796d7e9bee36de1429fceafe83d7dc5532
2023-03-17 15:17:31 -07:00
jzern@google.com
0825faa4c1 img2webp: add -sharp_yuv/-near_lossless
Both are global settings. Modifying them at the frame level is left as a
follow up based on need.

Bug: b/272739498
Change-Id: If15256c052f73fe3df56be5e0095e76d9870cc0f
2023-03-17 09:35:29 -07:00
James Zern
d64e6d7d9d Merge "PaletteSortModifiedZeng: fix leak on error" into main 2023-02-28 00:23:05 +00:00
James Zern
0e12a22d88 Merge "EncodeAlphaInternal: clear result->bw on error" into main 2023-02-28 00:22:57 +00:00
James Zern
0edbb6ea71 PaletteSortModifiedZeng: fix leak on error
Change-Id: I462bd9a3bc4670efdf251c295f6771a38c08a6ce
2023-02-23 22:03:31 -08:00
James Zern
41ffe04e12 Merge "Update yapf style from "chromium" to "yapf"" into main 2023-02-24 01:29:40 +00:00
Thiago Perrotta
2d9d9265f5 Update yapf style from "chromium" to "yapf"
yapf v0.30.0 renamed "chromium" style to "yapf".

Bug: chromium:1306598
Change-Id: I2a637d2c5d64f81ba411b1c0d07339ad7480bd66
2023-02-23 18:10:53 -05:00
James Zern
a486d800b6 EncodeAlphaInternal: clear result->bw on error
This avoids a double free should the function fail prior to
VP8BitWriterInit() and a previous trial result's buffer carried over.
Previously in ApplyFiltersAndEncode() trial.bw (with a previous
iteration's buffer) would be freed, followed by best.bw pointing to the
same buffer.

Since:
187d379d add a fallback to ALPHA_NO_COMPRESSION

In addition, check the return value of VP8BitWriterInit() in this
function.

Bug: webp:603
Change-Id: Ic258381ee26c8c16bc211d157c8153831c8c6910
2023-02-22 22:23:41 -08:00
Yannis Guyon
1347a32d82 Skip big scaled advanced_api_fuzzer
To avoid timeouts.

Change-Id: I8f04fd45313bef47004a616d2460be992692030d
2023-02-08 10:53:40 +01:00
Yannis Guyon
52b6f06703 Fix scaling limit in advanced_api_fuzzer.c
config.options.scaled_width or config.options.scaled_height being 0
means a ratio-conservative scaling so 7361842 was not enough.

Change-Id: Ib75241eb683cf824bc46222c5c07535b6c6d7313
2023-02-07 18:05:42 +01:00
Yannis Guyon
7361842839 Limit scaling in libwebp advanced_api_fuzzer.c
Change-Id: Ic1e3fdc76f4bdcb1ac68cf4f9334d2e77ca29374
2023-01-27 14:39:14 +01:00
James Zern
b54d21a01d Merge "CMakeLists.txt: allow CMAKE_INSTALL_RPATH to be set empty" into main 2023-01-18 19:10:44 +00:00
James Zern
31c28db53c libwebp{,demux,mux}.pc.in: Requires -> Requires.private
The libraries don't expose the symbols in libsharpyuv / libwebp, they're
only needed when static linking.

Noted for libwebp (Requires: libsharpyuv) in:
https://crbug.com/webp/590#c5. libwebpdemux and libwebpmux had a similar
issue with libwebp.

See also:
https://web.archive.org/web/20190921014607/https://wiki.openmandriva.org/en/Overlinking_issues_in_packaging

Change-Id: Ia1866b6b44cbb1ef1a77fd45fbcf10c027eae788
2023-01-17 18:32:44 -08:00
James Zern
d9a505ffb6 CMakeLists.txt: allow CMAKE_INSTALL_RPATH to be set empty
this allows the user to override the default non-empty value added in:
b4994eaa CMake: set rpath for shared objects

Bug: webp:592
Change-Id: I069dcbcd8c2f1e8654d9bc98149139f398ac2c93
Fixed: webp:592
2023-01-17 18:22:47 -08:00
James Zern
bdf33d03b0 libwebp-1.3.0
- 12/16/2022: version 1.3.0
   This is a binary compatible release.
   * add libsharpyuv, which exposes -sharp_yuv/config.use_sharp_yuv
     functionality to other libraries; libwebp now depends on this library
   * major updates to the container and lossless bitstream docs (#448, #546,
     #551)
   * miscellaneous warning, bug & build fixes (#576, #583, #584)
 -----BEGIN PGP SIGNATURE-----
 
 iQIzBAABCgAdFiEEaw5rcJdt4wPt8vYB+cPWvbgjK10FAmPAtgoACgkQ+cPWvbgj
 K11C9A/9FVNCbB6BTa0q2iZsgoEj49k+6KCsYQs80yhAwBBKtB+b2qHbjoaoGYQN
 cRNeanWvP2XxWcInPvkr6CIOhOaP9U3j3PKlubCeWv4YzI58mOx6uVGv1T9r6Isr
 ogPXrSOATUnVnlgG0RtJLRivOadY0mY+u4JNj2R8kHmSgp50poZRrw8GIiclh1ml
 KVq9RJ9St/p8ps4mJROLowxnaB5pH2jTif5T1rkmq4GsQskkLzPtHfELrM4hQjMz
 dc/pcdT0DCMMRqJZ/ePGMK0BjVjzHEBsxHYuHGfayKesO+MYajwfsTyYxxSGOD3y
 fEb0H7NCwHemGm94AyYj6NyjKUuIG2G2dku+0h0dWn/Ml855RzghGLIqCzqMXs0s
 AwaSpoyxWMBJw39pHcuk+ZuVX+uhy7dndLC5OtTLfEDCDwxKAktGaUdzRIy1nL/k
 NzH0IWCOnb/awux6heamP1gmTfKIKk+IsJwFiFJyfi+VQwxil7jD4rVCYsavL5f0
 hTkBFcZNzZsNSkuFJzqDiCnCFtcXWJ8mQ9fwx38wlvESH+U3k0yggo02cXmLpH8J
 pSYdlOU5kCpipdfgmS7Aa4HHo91SgkjlvL4+bzOa22UBpMQEgD3wgMnkVUm4dZ9F
 bgwMsZLt9KQYso6OKBdvOx+wy6Bp7/gOnIhVPleRZZk/HWoAHdE=
 =67V9
 -----END PGP SIGNATURE-----

Merge tag 'v1.3.0'

libwebp-1.3.0

- 12/16/2022: version 1.3.0
  This is a binary compatible release.
  * add libsharpyuv, which exposes -sharp_yuv/config.use_sharp_yuv
    functionality to other libraries; libwebp now depends on this library
  * major updates to the container and lossless bitstream docs (#448, #546,
    #551)
  * miscellaneous warning, bug & build fixes (#576, #583, #584)

* tag 'v1.3.0':
  update ChangeLog
  update NEWS
  bump version to 1.3.0
  update AUTHORS

Bug: webp:590
Bug: b/262806895
Change-Id: I4bc5cfb0708fab3569dc567d22bfdbcb5ff2a1ad
2023-01-12 17:58:29 -08:00
223 changed files with 16976 additions and 5235 deletions

240
.cmake-format.py Normal file
View File

@ -0,0 +1,240 @@
# ----------------------------------
# Options affecting listfile parsing
# ----------------------------------
with section("parse"):
# Specify structure for custom cmake functions
additional_commands = { 'foo': { 'flags': ['BAR', 'BAZ'],
'kwargs': {'DEPENDS': '*', 'HEADERS': '*', 'SOURCES': '*'}}}
# Override configurations per-command where available
override_spec = {}
# Specify variable tags.
vartags = []
# Specify property tags.
proptags = []
# -----------------------------
# Options affecting formatting.
# -----------------------------
with section("format"):
# Disable formatting entirely, making cmake-format a no-op
disable = False
# How wide to allow formatted cmake files
line_width = 80
# How many spaces to tab for indent
tab_size = 2
# If true, lines are indented using tab characters (utf-8 0x09) instead of
# <tab_size> space characters (utf-8 0x20). In cases where the layout would
# require a fractional tab character, the behavior of the fractional
# indentation is governed by <fractional_tab_policy>
use_tabchars = False
# If <use_tabchars> is True, then the value of this variable indicates how
# fractional indentions are handled during whitespace replacement. If set to
# 'use-space', fractional indentation is left as spaces (utf-8 0x20). If set
# to `round-up` fractional indentation is replaced with a single tab character
# (utf-8 0x09) effectively shifting the column to the next tabstop
fractional_tab_policy = 'use-space'
# If an argument group contains more than this many sub-groups (parg or kwarg
# groups) then force it to a vertical layout.
max_subgroups_hwrap = 3
# If a positional argument group contains more than this many arguments, then
# force it to a vertical layout.
max_pargs_hwrap = 6
# If a cmdline positional group consumes more than this many lines without
# nesting, then invalidate the layout (and nest)
max_rows_cmdline = 2
# If true, separate flow control names from their parentheses with a space
separate_ctrl_name_with_space = False
# If true, separate function names from parentheses with a space
separate_fn_name_with_space = False
# If a statement is wrapped to more than one line, than dangle the closing
# parenthesis on its own line.
dangle_parens = False
# If the trailing parenthesis must be 'dangled' on its on line, then align it
# to this reference: `prefix`: the start of the statement, `prefix-indent`:
# the start of the statement, plus one indentation level, `child`: align to
# the column of the arguments
dangle_align = 'prefix'
# If the statement spelling length (including space and parenthesis) is
# smaller than this amount, then force reject nested layouts.
min_prefix_chars = 4
# If the statement spelling length (including space and parenthesis) is larger
# than the tab width by more than this amount, then force reject un-nested
# layouts.
max_prefix_chars = 10
# If a candidate layout is wrapped horizontally but it exceeds this many
# lines, then reject the layout.
max_lines_hwrap = 2
# What style line endings to use in the output.
line_ending = 'unix'
# Format command names consistently as 'lower' or 'upper' case
command_case = 'canonical'
# Format keywords consistently as 'lower' or 'upper' case
keyword_case = 'unchanged'
# A list of command names which should always be wrapped
always_wrap = []
# If true, the argument lists which are known to be sortable will be sorted
# lexicographicall
enable_sort = True
# If true, the parsers may infer whether or not an argument list is sortable
# (without annotation).
autosort = False
# By default, if cmake-format cannot successfully fit everything into the
# desired linewidth it will apply the last, most agressive attempt that it
# made. If this flag is True, however, cmake-format will print error, exit
# with non-zero status code, and write-out nothing
require_valid_layout = False
# A dictionary mapping layout nodes to a list of wrap decisions. See the
# documentation for more information.
layout_passes = {}
# ------------------------------------------------
# Options affecting comment reflow and formatting.
# ------------------------------------------------
with section("markup"):
# What character to use for bulleted lists
bullet_char = '*'
# What character to use as punctuation after numerals in an enumerated list
enum_char = '.'
# If comment markup is enabled, don't reflow the first comment block in each
# listfile. Use this to preserve formatting of your copyright/license
# statements.
first_comment_is_literal = True
# If comment markup is enabled, don't reflow any comment block which matches
# this (regex) pattern. Default is `None` (disabled).
literal_comment_pattern = None
# Regular expression to match preformat fences in comments default=
# ``r'^\s*([`~]{3}[`~]*)(.*)$'``
fence_pattern = '^\\s*([`~]{3}[`~]*)(.*)$'
# Regular expression to match rulers in comments default=
# ``r'^\s*[^\w\s]{3}.*[^\w\s]{3}$'``
ruler_pattern = '^\\s*[^\\w\\s]{3}.*[^\\w\\s]{3}$'
# If a comment line matches starts with this pattern then it is explicitly a
# trailing comment for the preceeding argument. Default is '#<'
explicit_trailing_pattern = '#<'
# If a comment line starts with at least this many consecutive hash
# characters, then don't lstrip() them off. This allows for lazy hash rulers
# where the first hash char is not separated by space
hashruler_min_length = 10
# If true, then insert a space between the first hash char and remaining hash
# chars in a hash ruler, and normalize its length to fill the column
canonicalize_hashrulers = True
# enable comment markup parsing and reflow
enable_markup = True
# ----------------------------
# Options affecting the linter
# ----------------------------
with section("lint"):
# a list of lint codes to disable
disabled_codes = []
# regular expression pattern describing valid function names
function_pattern = '[0-9a-z_]+'
# regular expression pattern describing valid macro names
macro_pattern = '[0-9A-Z_]+'
# regular expression pattern describing valid names for variables with global
# (cache) scope
global_var_pattern = '[A-Z][0-9A-Z_]+'
# regular expression pattern describing valid names for variables with global
# scope (but internal semantic)
internal_var_pattern = '_[A-Z][0-9A-Z_]+'
# regular expression pattern describing valid names for variables with local
# scope
local_var_pattern = '[a-z][a-z0-9_]+'
# regular expression pattern describing valid names for privatedirectory
# variables
private_var_pattern = '_[0-9a-z_]+'
# regular expression pattern describing valid names for public directory
# variables
public_var_pattern = '[A-Z][0-9A-Z_]+'
# regular expression pattern describing valid names for function/macro
# arguments and loop variables.
argument_var_pattern = '[a-z][a-z0-9_]+'
# regular expression pattern describing valid names for keywords used in
# functions or macros
keyword_pattern = '[A-Z][0-9A-Z_]+'
# In the heuristic for C0201, how many conditionals to match within a loop in
# before considering the loop a parser.
max_conditionals_custom_parser = 2
# Require at least this many newlines between statements
min_statement_spacing = 1
# Require no more than this many newlines between statements
max_statement_spacing = 2
max_returns = 6
max_branches = 12
max_arguments = 5
max_localvars = 15
max_statements = 50
# -------------------------------
# Options affecting file encoding
# -------------------------------
with section("encode"):
# If true, emit the unicode byte-order mark (BOM) at the start of the file
emit_byteorder_mark = False
# Specify the encoding of the input file. Defaults to utf-8
input_encoding = 'utf-8'
# Specify the encoding of the output file. Defaults to utf-8. Note that cmake
# only claims to support utf-8 so be careful when using anything else
output_encoding = 'utf-8'
# -------------------------------------
# Miscellaneous configurations options.
# -------------------------------------
with section("misc"):
# A dictionary containing any per-command configuration overrides. Currently
# only `command_case` is supported.
per_command = {}

1
.gitignore vendored
View File

@ -52,5 +52,6 @@ tests/fuzzer/animdecoder_fuzzer
tests/fuzzer/animencoder_fuzzer
tests/fuzzer/demux_api_fuzzer
tests/fuzzer/enc_dec_fuzzer
tests/fuzzer/huffman_fuzzer
tests/fuzzer/mux_demux_api_fuzzer
tests/fuzzer/simple_api_fuzzer

View File

@ -16,3 +16,4 @@ James Zern <jzern@google.com>
Roberto Alanis <alanisbaez@google.com>
Brian Ledger <brianpl@google.com>
Maryla Ustarroz-Calonge <maryla@google.com>
Yannis Guyon <yguyon@google.com>

View File

@ -1,2 +1,2 @@
[style]
based_on_style = chromium
based_on_style = yapf

12
AUTHORS
View File

@ -2,6 +2,8 @@ Contributors:
- Aidan O'Loan (aidanol at gmail dot com)
- Alan Browning (browning at google dot com)
- Alexandru Ardelean (ardeleanalex at gmail dot com)
- Anuraag Agrawal (anuraaga at gmail dot com)
- Arthur Eubanks (aeubanks at google dot com)
- Brian Ledger (brianpl at google dot com)
- Charles Munger (clm at google dot com)
- Cheng Yi (cyi at google dot com)
@ -9,16 +11,20 @@ Contributors:
- Christopher Degawa (ccom at randomderp dot com)
- Clement Courbet (courbet at google dot com)
- Djordje Pesut (djordje dot pesut at imgtec dot com)
- Frank (1433351828 at qq dot com)
- Frank Barchard (fbarchard at google dot com)
- Hui Su (huisu at google dot com)
- H. Vetinari (h dot vetinari at gmx dot com)
- Ilya Kurdyukov (jpegqs at gmail dot com)
- Ingvar Stepanyan (rreverser at google dot com)
- Istvan Stefan (Istvan dot Stefan at arm dot com)
- James Zern (jzern at google dot com)
- Jan Engelhardt (jengelh at medozas dot de)
- Jehan (jehan at girinstud dot io)
- Jeremy Maitin-Shepard (jbms at google dot com)
- Johann Koenig (johann dot koenig at duck dot com)
- Jonathan Grant (jgrantinfotech at gmail dot com)
- Jonliu1993 (13720414433 at 163 dot com)
- Jovan Zelincevic (jovan dot zelincevic at imgtec dot com)
- Jyrki Alakuijala (jyrki at google dot com)
- Konstantin Ivlev (tomskside at gmail dot com)
@ -28,12 +34,16 @@ Contributors:
- Marcin Kowalczyk (qrczak at google dot com)
- Martin Olsson (mnemo at minimum dot se)
- Maryla Ustarroz-Calonge (maryla at google dot com)
- Masahiro Hanada (hanada at atmark-techno dot com)
- Mikołaj Zalewski (mikolajz at google dot com)
- Mislav Bradac (mislavm at google dot com)
- natewood (natewood at fb dot com)
- Nico Weber (thakis at chromium dot org)
- Noel Chromium (noel at chromium dot org)
- Nozomi Isozaki (nontan at pixiv dot co dot jp)
- Oliver Wolff (oliver dot wolff at qt dot io)
- Owen Rodley (orodley at google dot com)
- Ozkan Sezer (sezeroz at gmail dot com)
- Parag Salasakar (img dot mips1 at gmail dot com)
- Pascal Massimino (pascal dot massimino at gmail dot com)
- Paweł Hajdan, Jr (phajdan dot jr at chromium dot org)
@ -47,12 +57,14 @@ Contributors:
- Somnath Banerjee (somnath dot banerjee at gmail dot com)
- Sriraman Tallam (tmsriram at google dot com)
- Tamar Levy (tamar dot levy at intel dot com)
- Thiago Perrotta (tperrotta at google dot com)
- Timothy Gu (timothygu99 at gmail dot com)
- Urvang Joshi (urvang at google dot com)
- Vikas Arora (vikasa at google dot com)
- Vincent Rabaud (vrabaud at google dot com)
- Vlad Tsyrklevich (vtsyrklevich at chromium dot org)
- Wan-Teh Chang (wtc at google dot com)
- wrv (wrv at utexas dot edu)
- Yang Zhang (yang dot zhang at arm dot com)
- Yannis Guyon (yguyon at google dot com)
- Zhi An Ng (zhin at chromium dot org)

View File

@ -164,6 +164,7 @@ utils_dec_srcs := \
src/utils/color_cache_utils.c \
src/utils/filters_utils.c \
src/utils/huffman_utils.c \
src/utils/palette.c \
src/utils/quant_levels_dec_utils.c \
src/utils/random_utils.c \
src/utils/rescaler_utils.c \

View File

@ -9,11 +9,7 @@
if(APPLE)
cmake_minimum_required(VERSION 3.17)
else()
cmake_minimum_required(VERSION 3.7)
endif()
if(POLICY CMP0072)
cmake_policy(SET CMP0072 NEW)
cmake_minimum_required(VERSION 3.16)
endif()
project(WebP C)
@ -45,12 +41,15 @@ option(WEBP_BUILD_LIBWEBPMUX "Build the libwebpmux library." 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_FUZZTEST "Build the fuzztest tests." OFF)
option(WEBP_USE_THREAD "Enable threading support" ON)
option(WEBP_NEAR_LOSSLESS "Enable near-lossless encoding" ON)
option(WEBP_ENABLE_SWAP_16BIT_CSP "Enable byte swap for 16 bit colorspaces."
OFF)
set(WEBP_BITTRACE "0" CACHE STRING "Bit trace mode (0=none, 1=bit, 2=bytes)")
set_property(CACHE WEBP_BITTRACE PROPERTY STRINGS 0 1 2)
option(WEBP_ENABLE_WUNUSED_RESULT "Add [[nodiscard]] to some functions. \
CMake must be at least 3.21 to force C23" OFF)
if(WEBP_LINK_STATIC)
if(WIN32)
@ -82,7 +81,8 @@ if(WEBP_BUILD_WEBP_JS)
set(WEBP_USE_THREAD OFF)
if(WEBP_ENABLE_SIMD)
message("wasm2js does not support SIMD, disabling webp.js generation.")
message(NOTICE
"wasm2js does not support SIMD, disabling webp.js generation.")
endif()
endif()
@ -98,10 +98,20 @@ if(NOT CMAKE_BUILD_TYPE)
endif()
# Include dependencies.
if(WEBP_BUILD_ANIM_UTILS
OR WEBP_BUILD_CWEBP
OR WEBP_BUILD_DWEBP
OR WEBP_BUILD_EXTRAS
OR WEBP_BUILD_GIF2WEBP
OR WEBP_BUILD_IMG2WEBP)
set(WEBP_FIND_IMG_LIBS TRUE)
else()
set(WEBP_FIND_IMG_LIBS FALSE)
endif()
include(cmake/deps.cmake)
include(GNUInstallDirs)
if(BUILD_SHARED_LIBS AND NOT CMAKE_INSTALL_RPATH)
if(BUILD_SHARED_LIBS AND NOT DEFINED CMAKE_INSTALL_RPATH)
# Set the rpath to match autoconf/libtool behavior. Note this must be set
# before target creation.
set(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}")
@ -122,7 +132,7 @@ if(WEBP_UNICODE)
add_definitions(-DUNICODE -D_UNICODE)
endif()
if(MSVC AND BUILD_SHARED_LIBS)
if(WIN32 AND BUILD_SHARED_LIBS)
add_definitions(-DWEBP_DLL)
endif()
@ -150,7 +160,20 @@ if(MSVC)
set(CMAKE_STATIC_LIBRARY_PREFIX "${webp_libname_prefix}")
endif()
set(CMAKE_C_VISIBILITY_PRESET hidden)
if(NOT WIN32)
set(CMAKE_C_VISIBILITY_PRESET hidden)
endif()
if(WEBP_ENABLE_WUNUSED_RESULT)
if(CMAKE_VERSION VERSION_GREATER_EQUAL 3.21.0)
set(CMAKE_C_STANDARD 23)
else()
unset(CMAKE_C_STANDARD)
add_compile_options($<$<COMPILE_LANGUAGE:C>:-std=gnu2x>)
endif()
add_compile_options(-Wunused-result)
add_definitions(-DWEBP_ENABLE_NODISCARD=1)
endif()
# ##############################################################################
# Android only.
@ -349,9 +372,11 @@ if(XCODE)
endif()
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}>)
webpdecoder
PRIVATE ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR}
INTERFACE
"$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR};${CMAKE_CURRENT_BINARY_DIR}>"
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>)
set_target_properties(
webpdecoder
PROPERTIES PUBLIC_HEADER "${CMAKE_CURRENT_SOURCE_DIR}/src/webp/decode.h;\
@ -452,6 +477,8 @@ endif()
if(WEBP_BUILD_ANIM_UTILS
OR WEBP_BUILD_CWEBP
OR WEBP_BUILD_DWEBP
OR WEBP_BUILD_EXTRAS
OR WEBP_BUILD_FUZZTEST
OR WEBP_BUILD_GIF2WEBP
OR WEBP_BUILD_IMG2WEBP
OR WEBP_BUILD_VWEBP
@ -488,6 +515,8 @@ if(WEBP_BUILD_ANIM_UTILS
TARGET exampleutil imageioutil imagedec imageenc
PROPERTY INCLUDE_DIRECTORIES ${CMAKE_CURRENT_SOURCE_DIR}/src
${CMAKE_CURRENT_BINARY_DIR}/src)
target_include_directories(imagedec PRIVATE ${WEBP_DEP_IMG_INCLUDE_DIRS})
target_include_directories(imageenc PRIVATE ${WEBP_DEP_IMG_INCLUDE_DIRS})
endif()
if(WEBP_BUILD_DWEBP)
@ -534,7 +563,8 @@ if(WEBP_BUILD_GIF2WEBP)
add_executable(gif2webp ${GIF2WEBP_SRCS})
target_link_libraries(gif2webp exampleutil imageioutil webp libwebpmux
${WEBP_DEP_GIF_LIBRARIES})
target_include_directories(gif2webp PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/src)
target_include_directories(gif2webp PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/src
${CMAKE_CURRENT_SOURCE_DIR})
install(TARGETS gif2webp RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
endif()
@ -546,7 +576,8 @@ if(WEBP_BUILD_IMG2WEBP)
add_executable(img2webp ${IMG2WEBP_SRCS})
target_link_libraries(img2webp exampleutil imagedec imageioutil webp
libwebpmux)
target_include_directories(img2webp PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/src)
target_include_directories(img2webp PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/src
${CMAKE_CURRENT_SOURCE_DIR})
install(TARGETS img2webp RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
endif()
@ -626,44 +657,82 @@ if(WEBP_BUILD_EXTRAS)
${CMAKE_CURRENT_BINARY_DIR})
# vwebp_sdl
find_package(SDL)
if(WEBP_BUILD_VWEBP AND SDL_FOUND)
find_package(SDL2 QUIET)
if(WEBP_BUILD_VWEBP AND SDL2_FOUND)
add_executable(vwebp_sdl ${VWEBP_SDL_SRCS})
target_link_libraries(vwebp_sdl ${SDL_LIBRARY} imageioutil webp)
target_link_libraries(vwebp_sdl ${SDL2_LIBRARIES} imageioutil webp)
target_include_directories(
vwebp_sdl PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR}
${CMAKE_CURRENT_BINARY_DIR}/src ${SDL_INCLUDE_DIR})
${CMAKE_CURRENT_BINARY_DIR}/src ${SDL2_INCLUDE_DIRS})
set(WEBP_HAVE_SDL 1)
target_compile_definitions(vwebp_sdl PUBLIC WEBP_HAVE_SDL)
set(CMAKE_REQUIRED_INCLUDES "${SDL2_INCLUDE_DIRS}")
check_c_source_compiles(
"
#define SDL_MAIN_HANDLED
#include \"SDL.h\"
int main(void) {
return 0;
}
"
HAVE_JUST_SDL_H)
set(CMAKE_REQUIRED_INCLUDES)
if(HAVE_JUST_SDL_H)
target_compile_definitions(vwebp_sdl PRIVATE WEBP_HAVE_JUST_SDL_H)
endif()
endif()
endif()
if(WEBP_BUILD_WEBP_JS)
# The default stack size changed from 5MB to 64KB in 3.1.27. See
# https://crbug.com/webp/614.
if(EMSCRIPTEN_VERSION VERSION_GREATER_EQUAL "3.1.27")
# TOTAL_STACK size was renamed to STACK_SIZE in 3.1.27. The old name was
# kept for compatibility, but prefer the new one in case it is removed in
# the future.
set(emscripten_stack_size "-sSTACK_SIZE=5MB")
else()
set(emscripten_stack_size "-sTOTAL_STACK=5MB")
endif()
find_package(SDL2 REQUIRED)
# wasm2js does not support SIMD.
if(NOT WEBP_ENABLE_SIMD)
# JavaScript version
add_executable(webp_js ${CMAKE_CURRENT_SOURCE_DIR}/extras/webp_to_sdl.c)
target_link_libraries(webp_js webpdecoder SDL)
target_link_libraries(webp_js webpdecoder SDL2)
target_include_directories(webp_js PRIVATE ${CMAKE_CURRENT_BINARY_DIR})
set(WEBP_HAVE_SDL 1)
set_target_properties(
webp_js
PROPERTIES LINK_FLAGS "-sWASM=0 \
PROPERTIES
# Emscripten puts -sUSE_SDL2=1 in this variable, though it's needed at
# compile time to ensure the headers are downloaded.
COMPILE_OPTIONS "${SDL2_LIBRARIES}"
LINK_FLAGS
"-sWASM=0 ${emscripten_stack_size} \
-sEXPORTED_FUNCTIONS=_WebPToSDL -sINVOKE_RUN=0 \
-sEXPORTED_RUNTIME_METHODS=cwrap")
-sEXPORTED_RUNTIME_METHODS=cwrap ${SDL2_LIBRARIES} \
-sALLOW_MEMORY_GROWTH")
set_target_properties(webp_js PROPERTIES OUTPUT_NAME webp)
target_compile_definitions(webp_js PUBLIC EMSCRIPTEN WEBP_HAVE_SDL)
endif()
# WASM version
add_executable(webp_wasm ${CMAKE_CURRENT_SOURCE_DIR}/extras/webp_to_sdl.c)
target_link_libraries(webp_wasm webpdecoder SDL)
target_link_libraries(webp_wasm webpdecoder SDL2)
target_include_directories(webp_wasm PRIVATE ${CMAKE_CURRENT_BINARY_DIR})
set_target_properties(
webp_wasm
PROPERTIES LINK_FLAGS "-sWASM=1 \
PROPERTIES
# Emscripten puts -sUSE_SDL2=1 in this variable, though it's needed at
# compile time to ensure the headers are downloaded.
COMPILE_OPTIONS "${SDL2_LIBRARIES}"
LINK_FLAGS
"-sWASM=1 ${emscripten_stack_size} \
-sEXPORTED_FUNCTIONS=_WebPToSDL -sINVOKE_RUN=0 \
-sEXPORTED_RUNTIME_METHODS=cwrap")
-sEXPORTED_RUNTIME_METHODS=cwrap ${SDL2_LIBRARIES} \
-sALLOW_MEMORY_GROWTH")
target_compile_definitions(webp_wasm PUBLIC EMSCRIPTEN WEBP_HAVE_SDL)
target_compile_definitions(webpdspdecode PUBLIC EMSCRIPTEN)
@ -703,6 +772,10 @@ if(WEBP_BUILD_ANIM_UTILS)
target_include_directories(anim_dump PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/src)
endif()
if(WEBP_BUILD_FUZZTEST)
add_subdirectory(tests/fuzzer)
endif()
# Install the different headers and libraries.
install(
TARGETS ${INSTALLED_LIBRARIES}
@ -742,7 +815,8 @@ endif()
configure_package_config_file(
${CMAKE_CURRENT_SOURCE_DIR}/cmake/WebPConfig.cmake.in
${CMAKE_CURRENT_BINARY_DIR}/WebPConfig.cmake
INSTALL_DESTINATION ${ConfigPackageLocation})
INSTALL_DESTINATION ${ConfigPackageLocation}
PATH_VARS CMAKE_INSTALL_INCLUDEDIR)
# Install the generated CMake files.
install(FILES "${CMAKE_CURRENT_BINARY_DIR}/WebPConfigVersion.cmake"

View File

@ -19,10 +19,59 @@ again.
All submissions, including submissions by project members, require review. We
use a [Gerrit](https://www.gerritcodereview.com) instance hosted at
https://chromium-review.googlesource.com for this purpose. See the
https://chromium-review.googlesource.com for this purpose.
## Sending patches
The basic git workflow for modifying libwebp code and sending for review is:
1. Get the latest version of the repository locally:
```sh
git clone https://chromium.googlesource.com/webm/libwebp && cd libwebp
```
2. Copy the commit-msg script into ./git/hooks (this will add an ID to all of
your commits):
```sh
curl -Lo .git/hooks/commit-msg https://chromium-review.googlesource.com/tools/hooks/commit-msg && chmod u+x .git/hooks/commit-msg
```
3. Modify the local copy of libwebp. Make sure the code
[builds successfully](https://chromium.googlesource.com/webm/libwebp/+/HEAD/doc/building.md#cmake).
4. Choose a short and representative commit message:
```sh
git commit -a -m "Set commit message here"
```
5. Send the patch for review:
```sh
git push https://chromium-review.googlesource.com/webm/libwebp HEAD:refs/for/main
```
Go to https://chromium-review.googlesource.com to view your patch and
request a review from the maintainers.
See the
[WebM Project page](https://www.webmproject.org/code/contribute/submitting-patches/)
for additional details.
## Code Style
The C code style is based on the
[Google C++ Style Guide](https://google.github.io/styleguide/cppguide.html) and
`clang-format --style=Google`, though this project doesn't use the tool to
enforce the formatting.
CMake files are formatted with
[cmake-format](https://cmake-format.readthedocs.io/en/latest/). `cmake-format
-i` can be used to format individual files, it will use the settings from
`.cmake-format.py`.
## Community Guidelines
This project follows

373
ChangeLog
View File

@ -1,3 +1,370 @@
c3d85ce4 update NEWS
ad14e811 tests/fuzzer/*: add missing <string_view> include
74cd026e fuzz_utils.cc: fix build error w/WEBP_REDUCE_SIZE
a027aa93 mux_demux_api_fuzzer.cc: fix -Wshadow warning
25e17c68 update ChangeLog (tag: v1.5.0-rc1)
aa2684fc update NEWS
36923846 bump version to 1.5.0
ceea8ff6 update AUTHORS
e4f7a9f0 img2webp: add a warning for unused options
1b4c967f Merge "Properly check the data size against the end of the RIFF chunk" into main
9e5ecfaf Properly check the data size against the end of the RIFF chunk
da0d9c7d examples: exit w/failure w/no args
fcff86c7 {gif,img}2webp: sync -m help w/cwebp
b76c4a84 man/img2webp.1: sync -m text w/cwebp.1 & gif2webp.1
30633519 muxread: fix reading of buffers > riff size
4c85d860 yuv.h: update RGB<->YUV coefficients in comment
0ab789e0 Merge changes I6dfedfd5,I2376e2dc into main
03236450 {ios,xcframework}build.sh: fix compilation w/Xcode 16
61e2cfda rework AddVectorEq_SSE2
7bda3deb rework AddVector_SSE2
2ddaaf0a Fix variable names in SharpYuvComputeConversionMatrix
a3ba6f19 Makefile.vc: fix gif2webp link error
f999d94f gif2webp: add -sharp_yuv/-near_lossless
dfdcb7f9 Merge "lossless.h: fix function declaration mismatches" into main (tag: webp-rfc9649)
78ed6839 fix overread in Intra4Preds_NEON
d516a68e lossless.h: fix function declaration mismatches
87406904 Merge "Improve documentation of SharpYuvConversionMatrix." into main
fdb229ea Merge changes I07a7e36a,Ib29980f7,I2316122d,I2356e314,I32b53dd3, ... into main
0c3cd9cc Improve documentation of SharpYuvConversionMatrix.
169dfbf9 disable Intra4Preds_NEON
2dd5eb98 dsp/yuv*: use WEBP_RESTRICT qualifier
23bbafbe dsp/upsampling*: use WEBP_RESTRICT qualifier
35915b38 dsp/rescaler*: use WEBP_RESTRICT qualifier
a32b436b dsp/lossless*: use WEBP_RESTRICT qualifier
04d4b4f3 dsp/filters*: use WEBP_RESTRICT qualifier
b1cb37e6 dsp/enc*: use WEBP_RESTRICT qualifier
201894ef dsp/dec*: use WEBP_RESTRICT qualifier
02eac8a7 dsp/cost*: use WEBP_RESTRICT qualifier
84b118c9 Merge "webp-container-spec: normalize notes & unknown chunk link" into main
052cf42f webp-container-spec: normalize notes & unknown chunk link
220ee529 Search for best predictor transform bits
78619478 Try to reduce the sampling for the entropy image
14f09ab7 webp-container-spec: reorder chunk size - N text
a78c5356 Remove a useless malloc for entropy image
bc491763 Merge "Refactor predictor finding" into main
34f92238 man/{cwebp,img2webp}.1: rm 'if needed' from -sharp_yuv
367ca938 Refactor predictor finding
a582b53b webp-lossless-bitstream-spec: clarify some text
0fd25d84 Merge "anim_encode.c: fix function ref in comment" into main
f8882913 anim_encode.c: fix function ref in comment
40e4ca60 specs_generation.md: update kramdown command line
57883c78 img2webp: add -exact/-noexact per-frame options
1c8eba97 img2webp,cosmetics: add missing '.' spacers to help
2e81017c Convert predictor_enc.c to fixed point
94de6c7f Merge "Fix fuzztest link errors w/-DBUILD_SHARED_LIBS=1" into main
51d9832a Fix fuzztest link errors w/-DBUILD_SHARED_LIBS=1
7bcb36b8 Merge "Fix static overflow warning." into main
8e0cc14c Fix static overflow warning.
cea68462 README.md: add security report note
615e5874 Merge "make VP8LPredictor[01]_C() static" into main
233e86b9 Merge changes Ie43dc5ef,I94cd8bab into main
1a29fd2f make VP8LPredictor[01]_C() static
dd9d3770 Do*Filter_*: remove row & num_rows parameters
ab451a49 Do*Filter_C: remove dead 'inverse' code paths
f9a480f7 {TrueMotion,TM16}_NEON: remove zero extension
04834aca Merge changes I25c30a9e,I0a192fc6,I4cf89575 into main
39a602af webp-lossless-bitstream-spec: normalize predictor transform ref
f28c837d Merge "webp-container-spec: align anim pseudocode w/prose" into main
74be8e22 Fix implicit conversion issues
0c01db7c Merge "Increase the transform bits if possible." into main
f2d6dc1e Increase the transform bits if possible.
caa19e5b update link to issue tracker
c9dd9bd4 webp-container-spec: align anim pseudocode w/prose
8a7c8dc6 WASM: Enable VP8L_USE_FAST_LOAD
f0c53cd9 WASM: don't use USE_GENERIC_TREE
eef903d0 WASM: Enable 64-bit BITS caching
6296cc8d iterator_enc: make VP8IteratorReset() static
fbd93896 histogram_enc: make VP8LGetHistogramSize static
cc7ff545 cost_enc: make VP8CalculateLevelCosts[] static
4e2828ba vp8l_dec: make VP8LClear() static
d742b24a Intra16Preds_NEON: fix truemotion saturation
c7bb4cb5 Intra4Preds_NEON: fix truemotion saturation
952a989b Merge "Remove TODO now that log is using fixed point." into main
dde11574 Remove TODO now that log is using fixed point.
a1ca153d Fix hidden myerr in my_error_exit
3bd94202 Merge changes Iff6e47ed,I24c67cd5,Id781e761 into main
d27d246e Merge "Convert VP8LFastSLog2 to fixed point" into main
4838611f Disable msg_code use in fuzzing mode
314a142a Use QuantizeBlock_NEON for VP8EncQuantizeBlockWHT on Arm
3bfb05e3 Add AArch64 Neon implementation of Intra16Preds
baa93808 Add AArch64 Neon implementation of Intra4Preds
41a5e582 Fix errors when compiling code as C++
fb444b69 Convert VP8LFastSLog2 to fixed point
c1c89f51 Fix WEBP_NODISCARD comment and C++ version
66408c2c Switch the histogram_enc.h API to fixed point
ac1e410d Remove leftover tiff dep
b78d3957 Disable TIFF on fuzztest.
cff21a7d Do not build statically on oss-fuzz.
6853a8e5 Merge "Move more internal fuzzers to public." into main
9bc09db4 Merge "Convert VP8LFastLog2 to fixed point" into main
0a9f1c19 Convert VP8LFastLog2 to fixed point
db0cb9c2 Move more internal fuzzers to public.
ff2b5b15 Merge "advanced_api_fuzzer.cc: use crop dims in OOM check" into main
c4af79d0 Put 0 at the end of a palette and do not store it.
0ec80aef Delete last references to delta palettization
96d79f84 advanced_api_fuzzer.cc: use crop dims in OOM check
c35c7e02 Fix huffman fuzzer to not leak.
f2fe8dec Bump fuzztest dependency.
9ce982fd Fix fuzz tests to work on oss-fuzz
3ba8af1a Do not escape quotes anymore in build.sh
ea0e121b Allow centipede to be used as a fuzzing engine.
27731afd make VP8I4ModeOffsets & VP8MakeIntra4Preds static
ddd6245e oss-fuzz/build.sh: use heredoc for script creation
50074930 oss-fuzz/build.sh,cosmetics: fix indent
20e92f7d Limit the possible fuzz engines.
4f200de5 Switch public fuzz tests to fuzztest.
64186bb3 Add huffman_fuzzer to .gitignore
0905f61c Move build script from oss-fuzz repo to here.
e8678758 Fix link to Javascript documentation
5e5b8f0c Fix SSE2 Transform_AC3 function name
45129ee0 Revert "Check all the rows."
ee26766a Check all the rows.
7ec51c59 Increase the transform bits if possible.
3cd16fd3 Revert "Increase the transform bits if possible."
971a03d8 Increase the transform bits if possible.
1bf198a2 Allow transform_bits to be different during encoding.
1e462ca8 Define MAX_TRANSFORM_BITS according to the specification.
64d1ec23 Use (MIN/NUM)_(TRANSFORM/HUFFMAN)_BITS where appropriate
a90160e1 Refactor histograms in predictors.
a7aa7525 Fix some function declarations
68ff4e1e Merge "jpegdec: add a hint for EOF/READ errors" into main
79e7968a jpegdec: add a hint for EOF/READ errors
d33455cd man/*: s/BUGS/REPORTING BUGS/
a67ff735 normalize example exit status
edc28909 upsampling_{neon,sse41}: fix int sanitizer warning
3cada4ce ImgIoUtilReadFile: check ftell() return
dc950585 Merge tag 'v1.4.0'
845d5476 update ChangeLog (tag: v1.4.0, origin/1.4.0)
8a6a55bb update NEWS
cf7c5a5d provide a way to opt-out/override WEBP_NODISCARD
cc34288a update ChangeLog (tag: v1.4.0-rc1)
f13c0886 NEWS: fix date
74555950 Merge "vwebp: fix window title when options are given" into 1.4.0
d781646c vwebp: fix window title when options are given
c2e394de update NEWS
f6d15cb7 bump version to 1.4.0
57c388b8 update AUTHORS
b3d1b2cb Merge changes I26f4aa22,I83386b6c,I320ed1a2 into main
07216886 webp-container-spec: fix VP8 chunk ref ('VP8'->'VP8 ')
f88666eb webp_js/*.html: fix canvas mapping
e2c8f233 cmake,wasm: simplify SDL2 related flags
d537cd37 cmake: fix vwebp_sdl compile w/libsdl-org release
6c484cbf CMakeLists.txt: add missing WEBP_BUILD_EXTRAS check
7b0bc235 man/cwebp.1: add more detail to -partition_limit
3c0011bb WebPMuxGetChunk: add an assert
955a3d14 Merge "muxread,MuxGet: add an assert" into main
00abc000 muxread,MuxGet: add an assert
40e85a0b Have the window title reflect the filename.
1bf46358 man/cwebp.1: clarify -pass > 1 behavior w/o -size/-psnr
eba03acb webp-container-spec: replace 'above' with 'earlier'
a16d30cb webp-container-spec: clarify chunk order requirements
8a7e9112 Merge "CMakeLists.txt: apply cmake-format" into main
7fac6c1b Merge "Copy C code to not have multiplication overflow" into main
e2922e43 Merge "Check for the presence of the ANDROID_ABI variable" into main
501d9274 Copy C code to not have multiplication overflow
fba7d62e CMakeLists.txt: apply cmake-format
661c1b66 Merge "windows exports: use dllexport attribute, instead of visibility." into main
8487860a windows exports: use dllexport attribute, instead of visibility.
8ea678b9 webp/mux.h: data lifetime note w/copy_data=0
79e05c7f Check for the presence of the ANDROID_ABI variable
45f995a3 Expose functions for managing non-image chunks on WebPAnimEncoder
1fb9f3dc gifdec: fix ErrorGIFNotAvailable() declaration
4723db65 cosmetics: s/SANITY_CHECK/DCHECK/
f4b9bc9e clear -Wextra-semi-stmt warnings
713982b8 Limit animdecoder_fuzzer to 320MB
cbe825e4 cmake: fix sharpyuv simd files' build
f99305e9 Makefile.vc: add ARM64 support
5efd6300 mv SharpYuvEstimate420Risk to extras/
e78e924f Makefile.vc: add sharpyuv_risk_table.obj
d7a0506d Add YUV420 riskiness metric.
89c5b917 Merge "BuildHuffmanTable check sorted[] array bounds before writing" into main
34c80749 Remove alpha encoding pessimization.
13d9c30b Add a WEBP_NODISCARD
24d7f9cb Switch code to SDL2.
0b56dedc BuildHuffmanTable check sorted[] array bounds before writing
a429c0de sharpyuv: convert some for() to do/while
f0cd7861 DoSharpArgbToYuv: remove constant from loop
339231cc SharpYuvConvertWithOptions,cosmetics: fix formatting
307071f1 Remove medium/large code model-specific inline asm
deadc339 Fix transfer functions where toGamma and toLinear are swapped.
e7b78d43 Merge "Fix bug in FromLinearLog100." into main
15a1309e Merge "webp-lossless-bitstream-spec: delete extra blank line" into main
54ca9752 Fix bug in FromLinearLog100.
d2cb2d8c Dereference after NULL check.
e9d50107 webp-lossless-bitstream-spec: delete extra blank line
78657971 Merge changes Ief442c90,Ie6e9c9a5 into main
e30a5884 webp-lossless-bitstream-spec: update variable names
09ca1368 Merge "webp-container-spec: change assert to MUST be TRUE" into main
38cb4fc0 iosbuild,xcframeworkbuild: add SharpYuv framework
40afa926 webp-lossless-bitstream-spec: simplify abstract
9db21143 webp-container-spec: change assert to MUST be TRUE
cdbf88ae Fix typo in API docs for incremental decoding
05c46984 Reformat vcpkg build instructions.
8534f539 Merge "Never send VP8_STATUS_SUSPENDED back in non-incremental." into main
35e197bd Never send VP8_STATUS_SUSPENDED back in non-incremental.
61441425 Add vcpkg installation instructions
dce8397f Fix next is invalid pointer when WebPSafeMalloc fails
57c58105 Cmake: wrong public macro WEBP_INCLUDE_DIRS
c1ffd9ac Merge "vp8l_enc: fix non-C90 code" into main
a3965948 Merge changes If628bb93,Ic79f6309,I45f0db23 into main
f80e9b7e vp8l_enc: fix non-C90 code
accd141d Update lossless spec for two simple codes.
ac17ffff Fix non-C90 code.
433c7dca Fix static analyzer warnings.
5fac76cf Merge tag 'v1.3.2'
ca332209 update ChangeLog (tag: v1.3.2)
1ace578c update NEWS
63234c42 bump version to 1.3.2
a35ea50d Add a fuzzer for ReadHuffmanCodes
95ea5226 Fix invalid incremental decoding check.
2af26267 Fix OOB write in BuildHuffmanTable.
902bc919 Fix OOB write in BuildHuffmanTable.
7ba44f80 Homogenize "__asm__ volatile" vs "asm volatile"
68e27135 webp-container-spec: reorder example chunk layout
943b932a Merge changes I6a4d0a04,Ibc37b91e into main
1cc94f95 decode.h: wrap idec example in /* */
63acdd1e decode.h: fix decode example
aac5c5d0 ReadHuffmanCode: rm redundant num code lengths check
a2de25f6 webp-lossless-bitstream-spec: normalize list item case
68820f0e webp-lossless-bitstream-spec: normalize pixel ref
cdb31aa8 webp-lossless-bitstream-spec: add missing periods
0535a8cf webp-lossless-bitstream-spec: fix grammar
b6c4ce26 normalize numbered list item format
dd7364c3 Merge "palette.c: fix msvc warnings" into main
c63c5df6 palette.c: fix msvc warnings
0a2cad51 webp-container-spec: move terms from intro section
dd88d2ff webp-lossless-bitstream-spec: color_cache -> color cache
6e750547 Merge changes I644d7d39,Icf05491e,Ic02e6652,I63b11258 into main
67a7cc2b webp-lossless-bitstream-spec: fix code blocks
1432ebba Refactor palette sorting computation.
cd436142 webp-lossless-bitstream-spec: block -> chunk
3cb66f64 webp-lossless-bitstream-spec: add some missing commas
56471a53 webp-lossless-bitstream-spec: normalize item text in 5.1
af7fbfd2 vp8l_dec,ReadTransform: improve error status reporting
7d8e0896 vp8l_dec: add VP8LSetError()
a71ce1cf animencoder_fuzzer: fix error check w/Nallocfuzz
e94b36d6 webp-lossless-bitstream-spec: relocate details from 5.1
84628e56 webp-lossless-bitstream-spec: clarify image width changes
ee722997 alpha_dec: add missing VP8SetError()
0081693d enc_dec_fuzzer: use WebPDecode()
0fcb311c enc_dec_fuzzer: fix WebPEncode/pic.error_code check
982c177c webp-lossless-bitstream-spec: fix struct member refs
56cf5625 webp-lossless-bitstream-spec: use RFC 7405 for ABNF
6c6b3fd3 webp-lossless-bitstream-spec,cosmetics: delete blank lines
29b9eb15 Merge changes Id56ca4fd,I662bd1d7 into main
47c0af8d ReadHuffmanCodes: rm max_alphabet_size calc
b92deba3 animencoder_fuzzer: no WebPAnimEncoderAssemble check w/nallocfuzz
6be9bf8b animencoder_fuzzer: fix leak on alloc failure
5c965e55 vp8l_dec,cosmetics: add some /*param=*/ comments
e4fc2f78 webp-lossless-bitstream-spec: add validity note for max_symbol
71916726 webp-lossless-bitstream-spec: fix max_symbol definition
eac3bd5c Have the palette code be in its own file.
e2c85878 Add an initializer for the SharpYuvOptions struct.
4222b006 Merge tag 'v1.3.1'
25d94f47 Implement more transfer functions in libsharpyuv
2153a679 Merge changes Id0300937,I5dba5ccf,I57bb68e0,I2dba7b4e,I172aca36, ... into main
4298e976 webp-lossless-bitstream-spec: add PredictorTransformOutput
cd7e02be webp-lossless-bitstream-spec: fix RIFF-header ABNF
6c3845f9 webp-lossless-bitstream-spec: split LZ77 Backward Ref section
7f1b6799 webp-lossless-bitstream-spec: split Meta Prefix Codes section
7b634d8f webp-lossless-bitstream-spec: note transform order
6d6d4915 webp-lossless-bitstream-spec: update transformations text
fd7bb21c update ChangeLog (tag: v1.3.1-rc2, tag: v1.3.1)
e1adea50 update NEWS
6b1c722a lossless_common.h,cosmetics: fix a typo
08d60d60 webp-lossless-bitstream-spec: split code length section
7a12afcc webp-lossless-bitstream-spec: rm unused anchor
43393320 enc/*: normalize WebPEncodingSetError() calls
287fdefe enc/*: add missing WebPEncodingSetError() calls
c3bd7cff EncodeAlphaInternal: add missing error check
14a9dbfb webp-lossless-bitstream-spec: refine single node text
64819c7c Implement ExtractGreen_SSE2
d49cfbb3 vp8l_enc,WriteImage: add missing error check
2e5a9ec3 muxread,MuxImageParse: add missing error checks
ebb6f949 cmake,emscripten: explicitly set stack size
59a2b1f9 WebPDecodeYUV: check u/v/stride/uv_stride ptrs
8e965ccb Call png_get_channels() to see if image has alpha
fe80fbbd webp-container-spec: add some missing commas
e8ed3176 Merge "treat FILTER_NONE as a regular Unfilter[] call" into main
03a7a048 webp-lossless-bitstream-spec: rm redundant statement
c437c7aa webp-lossless-bitstream-spec: mv up prefix code group def
e4f17a31 webp-lossless-bitstream-spec: fix section reference
e2ecd5e9 webp-lossless-bitstream-spec: clarify ABNF syntax
8b55425a webp-lossless-bitstream-spec: refine pixel copy text
29c9f2d4 webp-lossless-bitstream-spec: minor wording updates
6b02f660 treat FILTER_NONE as a regular Unfilter[] call
7f75c91c webp-container-spec: fix location of informative msg
f6499943 webp-container-spec: consistently quote FourCCs
49918af3 webp-container-spec: minor wording updates
7f0a3419 update ChangeLog (tag: v1.3.1-rc1)
bab7efbe update NEWS
7138bf8f bump version to 1.3.1
435b4ded update AUTHORS
47351229 update .mailmap
46bc4fc9 Merge "Switch ExtraCost to ints and implement it in SSE." into main
828b4ce0 Switch ExtraCost to ints and implement it in SSE.
ff6c7f4e CONTRIBUTING.md: add C style / cmake-format notes
dd530437 add .cmake-format.py
adbe2cb1 cmake,cosmetics: apply cmake-format
15b36508 doc/webp-container-spec: rm future codec comment
c369c4bf doc/webp-lossless-bitstream-spec: improve link text
1de35f47 doc/webp-container-spec: don't use 'currently'
bb06a16e doc/webp-container-spec: prefer present tense
9f38b71e doc/webp-lossless-bitstream-spec: prefer present tense
7acb6b82 doc/webp-container-spec: avoid i.e. & e.g.
4967e7cd doc/webp-lossless-bitstream-spec: avoid i.e. & e.g.
e3366659 Merge "Do not find_package image libraries if not needed." into main
428588ef clarify single leaf node trees and use of canonical prefix coding
709ec152 Do not find_package image libraries if not needed.
8dd80ef8 fuzz_utils.h: lower kFuzzPxLimit w/ASan
8f187b9f Clean message calls in CMake
cba30078 WebPConfig.cmake.in: use calculated include path
6cf9a76a Merge "webp-lossless-bitstream-spec: remove use of 'dynamics'" into main
740943b2 Merge "Specialize and optimize ITransform_SSE2 using do_two" into main
2d547e24 Compare kFuzzPxLimit to max_num_operations
ac42dde1 Specialize and optimize ITransform_SSE2 using do_two
17e0ef1d webp-lossless-bitstream-spec: remove use of 'dynamics'
ed274371 neon.h,cosmetics: clear a couple lint warnings
3fb82947 cpu.h,cosmetics: segment defines
0c496a4f cpu.h: add WEBP_AARCH64
8151f388 move VP8GetCPUInfo declaration to cpu.c
916548c2 Make kFuzzPxLimit sanitizer dependent
4070b271 advanced_api_fuzzer: reduce scaling limit
761f49c3 Merge "webp-lossless-bitstream-spec: add missing bits to ABNF" into main
84d04c48 webp-lossless-bitstream-spec: add missing bits to ABNF
0696e1a7 advanced_api_fuzzer: reduce scaling limit
93d88aa2 Merge "deps.cmake: remove unneeded header checks" into main
118e0035 deps.cmake: remove unneeded header checks
4c3d7018 webp-lossless-bitstream-spec: condense normal-prefix-code
a6a09b32 webp-lossless-bitstream-spec: fix 2 code typos
50ac4f7c Merge "cpu.h: enable NEON w/_M_ARM64EC" into main
4b7d7b4f Add contribution instructions
0afbd97b cpu.h: enable NEON w/_M_ARM64EC
349f4353 Merge changes Ibd89e56b,Ic57e7f84,I89096614 into main
8f7513b7 upsampling_neon.c: fix WEBP_SWAP_16BIT_CSP check
cbf624b5 advanced_api_fuzzer: reduce scaling limit
89edfdd1 Skip slow scaling in libwebp advanced_api_fuzzer
859f19f7 Reduce libwebp advanced_api_fuzzer threshold
a4f04835 Merge changes Ic389aaa2,I329ccd79 into main
1275fac8 Makefile.vc: fix img2webp link w/dynamic cfg
2fe27bb9 img2webp: normalize help output
24bed3d9 cwebp: reflow -near_lossless help text
0825faa4 img2webp: add -sharp_yuv/-near_lossless
d64e6d7d Merge "PaletteSortModifiedZeng: fix leak on error" into main
0e12a22d Merge "EncodeAlphaInternal: clear result->bw on error" into main
0edbb6ea PaletteSortModifiedZeng: fix leak on error
41ffe04e Merge "Update yapf style from "chromium" to "yapf"" into main
2d9d9265 Update yapf style from "chromium" to "yapf"
a486d800 EncodeAlphaInternal: clear result->bw on error
1347a32d Skip big scaled advanced_api_fuzzer
52b6f067 Fix scaling limit in advanced_api_fuzzer.c
73618428 Limit scaling in libwebp advanced_api_fuzzer.c
b54d21a0 Merge "CMakeLists.txt: allow CMAKE_INSTALL_RPATH to be set empty" into main
31c28db5 libwebp{,demux,mux}.pc.in: Requires -> Requires.private
d9a505ff CMakeLists.txt: allow CMAKE_INSTALL_RPATH to be set empty
bdf33d03 Merge tag 'v1.3.0'
b5577769 update ChangeLog (tag: v1.3.0-rc1, tag: v1.3.0)
0ba77244 update NEWS
e763eb1e bump version to 1.3.0
2a8686fc update AUTHORS
@ -103,7 +470,7 @@ c626e7d5 cwebp: fix WebPPictureHasTransparency call
866e349c Merge tag 'v1.2.4'
c170df38 Merge "Create libsharpyuv.a in makefile.unix." into main
9d7ff74a Create libsharpyuv.a in makefile.unix.
0d1f1254 update ChangeLog (tag: v1.2.4, origin/1.2.4)
0d1f1254 update ChangeLog (tag: v1.2.4)
fcbc2d78 Merge "doc/*.txt: restrict code to 69 columns" into main
4ad0e189 Merge "webp-container-spec.txt: normalize fourcc spelling" into main
980d2488 update NEWS
@ -1134,7 +1501,7 @@ b016cb91 NEON: faster fancy upsampling
f04eb376 Merge tag 'v0.5.2'
341d711c NEON: 5% faster conversion to RGB565 and RGBA4444
abb54827 remove Clang warnings with unused arch arguments.
ece9684f update ChangeLog (tag: v0.5.2-rc2, tag: v0.5.2, origin/0.5.2)
ece9684f update ChangeLog (tag: v0.5.2-rc2, tag: v0.5.2)
aa7744ca anim_util: quiet implicit conv warnings in 32-bit
d9120271 jpegdec: correct ContextFill signature
24eb3940 Remove some errors when compiling the code as C++.
@ -1421,7 +1788,7 @@ bbb6ecd9 Merge "Add MSA optimized distortion functions"
c0991a14 io,EmitRescaledAlphaYUV: factor out a common expr
48bf5ed1 build.gradle: remove tab
bfef6c9f Merge tag 'v0.5.1'
3d97bb75 update ChangeLog (tag: v0.5.1, origin/0.5.1)
3d97bb75 update ChangeLog (tag: v0.5.1)
deb54d91 Clarify the expected 'config' lifespan in WebPIDecode()
435308e0 Add MSA optimized encoder transform functions
dce64bfa Add MSA optimized alpha filter functions

View File

@ -12,6 +12,8 @@ LIBSHARPYUV_BASENAME = libsharpyuv
ARCH = x86
!ELSE IF ! [ cl 2>&1 | find "x64" > NUL ]
ARCH = x64
!ELSE IF ! [ cl 2>&1 | find "ARM64" > NUL ]
ARCH = ARM64
!ELSE IF ! [ cl 2>&1 | find "ARM" > NUL ]
ARCH = ARM
!ELSE
@ -30,7 +32,7 @@ PLATFORM_LDFLAGS = /SAFESEH
NOLOGO = /nologo
CCNODBG = cl.exe $(NOLOGO) /O2 /DNDEBUG
CCDEBUG = cl.exe $(NOLOGO) /Od /Zi /D_DEBUG /RTC1
CFLAGS = /I. /Isrc $(NOLOGO) /W3 /EHsc /c
CFLAGS = /I. /Isrc $(NOLOGO) /MP /W3 /EHsc /c
CFLAGS = $(CFLAGS) /DWIN32 /D_CRT_SECURE_NO_WARNINGS /DWIN32_LEAN_AND_MEAN
LDFLAGS = /LARGEADDRESSAWARE /MANIFEST:EMBED /NXCOMPAT /DYNAMICBASE
LDFLAGS = $(LDFLAGS) $(PLATFORM_LDFLAGS)
@ -229,6 +231,7 @@ DSP_DEC_OBJS = \
$(DIROBJ)\dsp\lossless_neon.obj \
$(DIROBJ)\dsp\lossless_sse2.obj \
$(DIROBJ)\dsp\lossless_sse41.obj \
$(DIROBJ)\dsp\lossless_avx2.obj \
$(DIROBJ)\dsp\rescaler.obj \
$(DIROBJ)\dsp\rescaler_mips32.obj \
$(DIROBJ)\dsp\rescaler_mips_dsp_r2.obj \
@ -268,6 +271,7 @@ DSP_ENC_OBJS = \
$(DIROBJ)\dsp\lossless_enc_neon.obj \
$(DIROBJ)\dsp\lossless_enc_sse2.obj \
$(DIROBJ)\dsp\lossless_enc_sse41.obj \
$(DIROBJ)\dsp\lossless_enc_avx2.obj \
$(DIROBJ)\dsp\ssim.obj \
$(DIROBJ)\dsp\ssim_sse2.obj \
@ -321,6 +325,7 @@ ENC_OBJS = \
EXTRAS_OBJS = \
$(DIROBJ)\extras\extras.obj \
$(DIROBJ)\extras\quality_estimate.obj \
$(DIROBJ)\extras\sharpyuv_risk_table.obj \
IMAGEIO_UTIL_OBJS = \
$(DIROBJ)\imageio\imageio_util.obj \
@ -336,6 +341,7 @@ UTILS_DEC_OBJS = \
$(DIROBJ)\utils\color_cache_utils.obj \
$(DIROBJ)\utils\filters_utils.obj \
$(DIROBJ)\utils\huffman_utils.obj \
$(DIROBJ)\utils\palette.obj \
$(DIROBJ)\utils\quant_levels_dec_utils.obj \
$(DIROBJ)\utils\rescaler_utils.obj \
$(DIROBJ)\utils\random_utils.obj \
@ -389,7 +395,7 @@ $(DIRBIN)\dwebp.exe: $(IMAGEIO_UTIL_OBJS)
$(DIRBIN)\dwebp.exe: $(LIBWEBPDEMUX)
$(DIRBIN)\gif2webp.exe: $(DIROBJ)\examples\gif2webp.obj $(EX_GIF_DEC_OBJS)
$(DIRBIN)\gif2webp.exe: $(EX_UTIL_OBJS) $(IMAGEIO_UTIL_OBJS) $(LIBWEBPMUX)
$(DIRBIN)\gif2webp.exe: $(LIBWEBP)
$(DIRBIN)\gif2webp.exe: $(LIBWEBP) $(LIBSHARPYUV)
$(DIRBIN)\vwebp.exe: $(DIROBJ)\examples\vwebp.obj $(EX_UTIL_OBJS)
$(DIRBIN)\vwebp.exe: $(IMAGEIO_UTIL_OBJS) $(LIBWEBPDEMUX) $(LIBWEBP)
$(DIRBIN)\vwebp_sdl.exe: $(DIROBJ)\extras\vwebp_sdl.obj
@ -400,7 +406,7 @@ $(DIRBIN)\webpmux.exe: $(EX_UTIL_OBJS) $(IMAGEIO_UTIL_OBJS) $(LIBWEBP)
$(DIRBIN)\img2webp.exe: $(DIROBJ)\examples\img2webp.obj $(LIBWEBPMUX)
$(DIRBIN)\img2webp.exe: $(IMAGEIO_DEC_OBJS)
$(DIRBIN)\img2webp.exe: $(EX_UTIL_OBJS) $(IMAGEIO_UTIL_OBJS)
$(DIRBIN)\img2webp.exe: $(LIBWEBPDEMUX) $(LIBWEBP)
$(DIRBIN)\img2webp.exe: $(LIBWEBPDEMUX) $(LIBWEBP) $(LIBSHARPYUV)
$(DIRBIN)\get_disto.exe: $(DIROBJ)\extras\get_disto.obj
$(DIRBIN)\get_disto.exe: $(IMAGEIO_DEC_OBJS) $(IMAGEIO_UTIL_OBJS)
$(DIRBIN)\get_disto.exe: $(LIBWEBPDEMUX) $(LIBWEBP)

56
NEWS
View File

@ -1,3 +1,59 @@
- 12/19/2024 version 1.5.0
This is a binary compatible release.
API changes:
- `cross_color_transform_bits` added to WebPAuxStats
* minor lossless encoder speed and compression improvements
* lossless encoding does not use floats anymore
* additional Arm optimizations for lossy & lossless + general code generation
improvements
* improvements to WASM performance (#643)
* improvements and corrections in webp-container-spec.txt and
webp-lossless-bitstream-spec.txt (#646, #355607636)
* further security related hardening and increased fuzzing coverage w/fuzztest
(oss-fuzz: #382816119, #70112, #70102, #69873, #69825, #69508, #69208)
* miscellaneous warning, bug & build fixes (#499, #562, #381372617,
#381109771, #42340561, #375011696, #372109644, chromium: #334120888)
Tool updates:
* gif2webp: add -sharp_yuv & -near_lossless
* img2webp: add -exact & -noexact
* exit codes normalized; running an example program with no
arguments will output its help and exit with an error (#42340557,
#381372617)
- 4/12/2024: version 1.4.0
This is a binary compatible release.
* API changes:
- libwebpmux: WebPAnimEncoderSetChunk, WebPAnimEncoderGetChunk,
WebPAnimEncoderDeleteChunk
- libsharpyuv: SharpYuvOptionsInit, SharpYuvConvertWithOptions
- extras: SharpYuvEstimate420Risk
* further security related hardening in libwebp & examples
* some minor optimizations in the lossless encoder
* added WEBP_NODISCARD to report unused result warnings; enable with
-DWEBP_ENABLE_NODISCARD=1
* improvements and corrections in webp-container-spec.txt and
webp-lossless-bitstream-spec.txt (#611)
* miscellaneous warning, bug & build fixes (#615, #619, #632, #635)
- 9/13/2023: version 1.3.2
This is a binary compatible release.
* security fix for lossless decoder (chromium: #1479274, CVE-2023-4863)
- 6/23/2023: version 1.3.1
This is a binary compatible release.
* security fixes for lossless encoder (#603, chromium: #1420107, #1455619,
CVE-2023-1999)
* improve error reporting through WebPPicture error codes
* fix upsampling for RGB565 and RGBA4444 in NEON builds
* img2webp: add -sharp_yuv & -near_lossless
* Windows builds:
- fix compatibility with clang-cl (#607)
- improve Arm64 performance with cl.exe
- add Arm64EC support
* fix webp_js with emcc >= 3.1.27 (stack size change, #614)
* CMake fixes (#592, #610, #612)
* further updates to the container and lossless bitstream docs (#581, #611)
- 12/16/2022: version 1.3.0
This is a binary compatible release.
* add libsharpyuv, which exposes -sharp_yuv/config.use_sharp_yuv

View File

@ -7,7 +7,7 @@
\__\__/\____/\_____/__/ ____ ___
/ _/ / \ \ / _ \/ _/
/ \_/ / / \ \ __/ \__
\____/____/\_____/_____/____/v1.3.0
\____/____/\_____/_____/____/v1.5.0
```
WebP codec is a library to encode and decode images in WebP format. This package
@ -42,7 +42,8 @@ See the [APIs documentation](doc/api.md), and API usage examples in the
## Bugs
Please report all bugs to the issue tracker: https://bugs.chromium.org/p/webp
Please report all bugs to the [issue tracker](https://issues.webmproject.org).
For security reports, select 'Security report' from the Template dropdown.
Patches welcome! See [how to contribute](CONTRIBUTING.md).

View File

@ -173,6 +173,7 @@ model {
include "color_cache_utils.c"
include "filters_utils.c"
include "huffman_utils.c"
include "palette.c"
include "quant_levels_dec_utils.c"
include "random_utils.c"
include "rescaler_utils.c"

View File

@ -8,9 +8,12 @@ if(@WEBP_USE_THREAD@)
find_dependency(Threads REQUIRED)
endif()
include ("${CMAKE_CURRENT_LIST_DIR}/@PROJECT_NAME@Targets.cmake")
include("${CMAKE_CURRENT_LIST_DIR}/@PROJECT_NAME@Targets.cmake")
set(WebP_INCLUDE_DIRS "@CMAKE_INSTALL_FULL_INCLUDEDIR@")
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 "${WebP_LIBRARIES}")
check_required_components(WebP)

View File

@ -16,48 +16,18 @@
/* Define to 1 if you have the <cpu-features.h> header file. */
#cmakedefine HAVE_CPU_FEATURES_H 1
/* Define to 1 if you have the <dlfcn.h> header file. */
#cmakedefine HAVE_DLFCN_H 1
/* Define to 1 if you have the <GLUT/glut.h> header file. */
#cmakedefine HAVE_GLUT_GLUT_H 1
/* Define to 1 if you have the <GL/glut.h> header file. */
#cmakedefine HAVE_GL_GLUT_H 1
/* Define to 1 if you have the <inttypes.h> header file. */
#cmakedefine HAVE_INTTYPES_H 1
/* Define to 1 if you have the <memory.h> header file. */
#cmakedefine HAVE_MEMORY_H 1
/* Define to 1 if you have the <OpenGL/glut.h> header file. */
#cmakedefine HAVE_OPENGL_GLUT_H 1
/* Have PTHREAD_PRIO_INHERIT. */
#cmakedefine HAVE_PTHREAD_PRIO_INHERIT @HAVE_PTHREAD_PRIO_INHERIT@
/* Define to 1 if you have the <shlwapi.h> header file. */
#cmakedefine HAVE_SHLWAPI_H 1
/* Define to 1 if you have the <stdint.h> header file. */
#cmakedefine HAVE_STDINT_H 1
/* Define to 1 if you have the <stdlib.h> header file. */
#cmakedefine HAVE_STDLIB_H 1
/* Define to 1 if you have the <strings.h> header file. */
#cmakedefine HAVE_STRINGS_H 1
/* Define to 1 if you have the <string.h> header file. */
#cmakedefine HAVE_STRING_H 1
/* Define to 1 if you have the <sys/stat.h> header file. */
#cmakedefine HAVE_SYS_STAT_H 1
/* Define to 1 if you have the <sys/types.h> header file. */
#cmakedefine HAVE_SYS_TYPES_H 1
/* Define to 1 if you have the <unistd.h> header file. */
#cmakedefine HAVE_UNISTD_H 1
@ -93,9 +63,6 @@
/* Define to the version of this package. */
#cmakedefine PACKAGE_VERSION "@PACKAGE_VERSION@"
/* Define to 1 if you have the ANSI C header files. */
#cmakedefine STDC_HEADERS 1
/* Version number of package */
#cmakedefine VERSION "@VERSION@"
@ -127,6 +94,9 @@
/* Set to 1 if SSE4.1 is supported */
#cmakedefine WEBP_HAVE_SSE41 1
/* Set to 1 if AVX2 is supported */
#cmakedefine WEBP_HAVE_AVX2 1
/* Set to 1 if TIFF library is installed */
#cmakedefine WEBP_HAVE_TIFF 1

View File

@ -38,9 +38,9 @@ function(webp_check_compiler_flag WEBP_SIMD_FLAG ENABLE_SIMD)
endfunction()
# those are included in the names of WEBP_USE_* in c++ code.
set(WEBP_SIMD_FLAGS "SSE41;SSE2;MIPS32;MIPS_DSP_R2;NEON;MSA")
set(WEBP_SIMD_FLAGS "AVX2;SSE41;SSE2;MIPS32;MIPS_DSP_R2;NEON;MSA")
set(WEBP_SIMD_FILE_EXTENSIONS
"_sse41.c;_sse2.c;_mips32.c;_mips_dsp_r2.c;_neon.c;_msa.c")
"_avx2.c;_sse41.c;_sse2.c;_mips32.c;_mips_dsp_r2.c;_neon.c;_msa.c")
if(MSVC AND CMAKE_C_COMPILER_ID STREQUAL "MSVC")
# With at least Visual Studio 12 (2013)+ /arch is not necessary to build SSE2
# or SSE4 code unless a lesser /arch is forced. MSVC does not have a SSE4
@ -50,18 +50,18 @@ if(MSVC AND CMAKE_C_COMPILER_ID STREQUAL "MSVC")
if(MSVC_VERSION GREATER_EQUAL 1800 AND NOT CMAKE_C_FLAGS MATCHES "/arch:")
set(SIMD_ENABLE_FLAGS)
else()
set(SIMD_ENABLE_FLAGS "/arch:AVX;/arch:SSE2;;;;")
set(SIMD_ENABLE_FLAGS "/arch:AVX2;/arch:AVX;/arch:SSE2;;;;")
endif()
set(SIMD_DISABLE_FLAGS)
else()
set(SIMD_ENABLE_FLAGS "-msse4.1;-msse2;-mips32;-mdspr2;-mfpu=neon;-mmsa")
set(SIMD_DISABLE_FLAGS "-mno-sse4.1;-mno-sse2;;-mno-dspr2;;-mno-msa")
set(SIMD_ENABLE_FLAGS "-mavx2;-msse4.1;-msse2;-mips32;-mdspr2;-mfpu=neon;-mmsa")
set(SIMD_DISABLE_FLAGS "-mno-avx2;-mno-sse4.1;-mno-sse2;;-mno-dspr2;;-mno-msa")
endif()
set(WEBP_SIMD_FILES_TO_INCLUDE)
set(WEBP_SIMD_FLAGS_TO_INCLUDE)
if(${ANDROID})
if(ANDROID AND ANDROID_ABI)
if(${ANDROID_ABI} STREQUAL "armeabi-v7a")
# This is because Android studio uses the configuration "-march=armv7-a
# -mfloat-abi=softfp -mfpu=vfpv3-d16" that does not trigger neon
@ -106,8 +106,9 @@ foreach(I_SIMD RANGE ${WEBP_SIMD_FLAGS_RANGE})
endif()
# Check which files we should include or not.
list(GET WEBP_SIMD_FILE_EXTENSIONS ${I_SIMD} WEBP_SIMD_FILE_EXTENSION)
file(GLOB SIMD_FILES "${CMAKE_CURRENT_LIST_DIR}/../"
"src/dsp/*${WEBP_SIMD_FILE_EXTENSION}")
file(GLOB SIMD_FILES
"${CMAKE_CURRENT_LIST_DIR}/../sharpyuv/*${WEBP_SIMD_FILE_EXTENSION}"
"${CMAKE_CURRENT_LIST_DIR}/../src/dsp/*${WEBP_SIMD_FILE_EXTENSION}")
if(WEBP_HAVE_${WEBP_SIMD_FLAG})
# Memorize the file and flags.
foreach(FILE ${SIMD_FILES})

View File

@ -43,16 +43,6 @@ if(WEBP_USE_THREAD)
if(CMAKE_USE_PTHREADS_INIT AND NOT CMAKE_SYSTEM_NAME STREQUAL "QNX")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -pthread")
endif()
check_c_source_compiles(
"
#include <pthread.h>
int main (void) {
int attr = PTHREAD_PRIO_INHERIT;
return attr;
}
"
FLAG_HAVE_PTHREAD_PRIO_INHERIT)
set(HAVE_PTHREAD_PRIO_INHERIT ${FLAG_HAVE_PTHREAD_PRIO_INHERIT})
list(APPEND WEBP_DEP_LIBRARIES Threads::Threads)
endif()
set(WEBP_USE_THREAD ${Threads_FOUND})
@ -84,72 +74,64 @@ endif()
# Find the standard image libraries.
set(WEBP_DEP_IMG_LIBRARIES)
set(WEBP_DEP_IMG_INCLUDE_DIRS)
foreach(I_LIB PNG JPEG TIFF)
# Disable tiff when compiling in static mode as it is failing on Ubuntu.
if(WEBP_LINK_STATIC AND ${I_LIB} STREQUAL "TIFF")
message("TIFF is disabled when statically linking.")
continue()
if(WEBP_FIND_IMG_LIBS)
foreach(I_LIB PNG JPEG TIFF)
# Disable tiff when compiling in static mode as it is failing on Ubuntu.
if(WEBP_LINK_STATIC AND ${I_LIB} STREQUAL "TIFF")
message(STATUS "TIFF is disabled when statically linking.")
continue()
endif()
find_package(${I_LIB})
set(WEBP_HAVE_${I_LIB} ${${I_LIB}_FOUND})
if(${I_LIB}_FOUND)
list(APPEND WEBP_DEP_IMG_LIBRARIES ${${I_LIB}_LIBRARIES})
list(APPEND WEBP_DEP_IMG_INCLUDE_DIRS ${${I_LIB}_INCLUDE_DIR}
${${I_LIB}_INCLUDE_DIRS})
endif()
endforeach()
if(WEBP_DEP_IMG_INCLUDE_DIRS)
list(REMOVE_DUPLICATES WEBP_DEP_IMG_INCLUDE_DIRS)
endif()
find_package(${I_LIB})
set(WEBP_HAVE_${I_LIB} ${${I_LIB}_FOUND})
if(${I_LIB}_FOUND)
list(APPEND WEBP_DEP_IMG_LIBRARIES ${${I_LIB}_LIBRARIES})
list(APPEND WEBP_DEP_IMG_INCLUDE_DIRS ${${I_LIB}_INCLUDE_DIR}
${${I_LIB}_INCLUDE_DIRS})
endif()
endforeach()
if(WEBP_DEP_IMG_INCLUDE_DIRS)
list(REMOVE_DUPLICATES WEBP_DEP_IMG_INCLUDE_DIRS)
endif()
# GIF detection, gifdec isn't part of the imageio lib.
include(CMakePushCheckState)
set(WEBP_DEP_GIF_LIBRARIES)
set(WEBP_DEP_GIF_INCLUDE_DIRS)
find_package(GIF)
set(WEBP_HAVE_GIF ${GIF_FOUND})
if(GIF_FOUND)
# 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
# least cmake 3.7.2). Make sure the library links to avoid incorrect detection
# when cross compiling.
cmake_push_check_state()
set(CMAKE_REQUIRED_LIBRARIES ${GIF_LIBRARIES})
set(CMAKE_REQUIRED_INCLUDES ${GIF_INCLUDE_DIR})
check_c_source_compiles(
"
# GIF detection, gifdec isn't part of the imageio lib.
include(CMakePushCheckState)
set(WEBP_DEP_GIF_LIBRARIES)
set(WEBP_DEP_GIF_INCLUDE_DIRS)
find_package(GIF)
set(WEBP_HAVE_GIF ${GIF_FOUND})
if(GIF_FOUND)
# 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
# least cmake 3.7.2). Make sure the library links to avoid incorrect
# detection when cross compiling.
cmake_push_check_state()
set(CMAKE_REQUIRED_LIBRARIES ${GIF_LIBRARIES})
set(CMAKE_REQUIRED_INCLUDES ${GIF_INCLUDE_DIR})
check_c_source_compiles(
"
#include <gif_lib.h>
int main(void) {
(void)DGifOpenFileHandle;
return 0;
}
"
GIF_COMPILES)
cmake_pop_check_state()
if(GIF_COMPILES)
list(APPEND WEBP_DEP_GIF_LIBRARIES ${GIF_LIBRARIES})
list(APPEND WEBP_DEP_GIF_INCLUDE_DIRS ${GIF_INCLUDE_DIR})
else()
unset(GIF_FOUND)
GIF_COMPILES)
cmake_pop_check_state()
if(GIF_COMPILES)
list(APPEND WEBP_DEP_GIF_LIBRARIES ${GIF_LIBRARIES})
list(APPEND WEBP_DEP_GIF_INCLUDE_DIRS ${GIF_INCLUDE_DIR})
else()
unset(GIF_FOUND)
endif()
endif()
endif()
# Check for specific headers.
include(CheckIncludeFiles)
check_include_files("stdlib.h;stdarg.h;string.h;float.h" STDC_HEADERS)
check_include_files(dlfcn.h HAVE_DLFCN_H)
check_include_files(GLUT/glut.h HAVE_GLUT_GLUT_H)
check_include_files(GL/glut.h HAVE_GL_GLUT_H)
check_include_files(inttypes.h HAVE_INTTYPES_H)
check_include_files(memory.h HAVE_MEMORY_H)
check_include_files(OpenGL/glut.h HAVE_OPENGL_GLUT_H)
check_include_files(shlwapi.h HAVE_SHLWAPI_H)
check_include_files(stdint.h HAVE_STDINT_H)
check_include_files(stdlib.h HAVE_STDLIB_H)
check_include_files(strings.h HAVE_STRINGS_H)
check_include_files(string.h HAVE_STRING_H)
check_include_files(sys/stat.h HAVE_SYS_STAT_H)
check_include_files(sys/types.h HAVE_SYS_TYPES_H)
check_include_files(unistd.h HAVE_UNISTD_H)
check_include_files(wincodec.h HAVE_WINCODEC_H)
check_include_files(windows.h HAVE_WINDOWS_H)

View File

@ -1,5 +1,5 @@
AC_INIT([libwebp], [1.3.0],
[https://bugs.chromium.org/p/webp],,
AC_INIT([libwebp], [1.5.0],
[https://issues.webmproject.org],,
[https://developers.google.com/speed/webp])
AC_CANONICAL_HOST
AC_PREREQ([2.60])
@ -106,6 +106,7 @@ TEST_AND_ADD_CFLAGS([AM_CFLAGS], [-Wall])
TEST_AND_ADD_CFLAGS([AM_CFLAGS], [-Wconstant-conversion])
TEST_AND_ADD_CFLAGS([AM_CFLAGS], [-Wdeclaration-after-statement])
TEST_AND_ADD_CFLAGS([AM_CFLAGS], [-Wextra])
TEST_AND_ADD_CFLAGS([AM_CFLAGS], [-Wextra-semi-stmt])
TEST_AND_ADD_CFLAGS([AM_CFLAGS], [-Wfloat-conversion])
TEST_AND_ADD_CFLAGS([AM_CFLAGS], [-Wformat -Wformat-nonliteral])
TEST_AND_ADD_CFLAGS([AM_CFLAGS], [-Wformat -Wformat-security])
@ -115,6 +116,7 @@ TEST_AND_ADD_CFLAGS([AM_CFLAGS], [-Wold-style-definition])
TEST_AND_ADD_CFLAGS([AM_CFLAGS], [-Wparentheses-equality])
TEST_AND_ADD_CFLAGS([AM_CFLAGS], [-Wshadow])
TEST_AND_ADD_CFLAGS([AM_CFLAGS], [-Wshorten-64-to-32])
TEST_AND_ADD_CFLAGS([AM_CFLAGS], [-Wstrict-prototypes])
TEST_AND_ADD_CFLAGS([AM_CFLAGS], [-Wundef])
TEST_AND_ADD_CFLAGS([AM_CFLAGS], [-Wunreachable-code-aggressive])
TEST_AND_ADD_CFLAGS([AM_CFLAGS], [-Wunreachable-code])
@ -159,6 +161,25 @@ AS_IF([test "$GCC" = "yes" ], [
AC_SUBST([AM_CFLAGS])
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_FLAGS="$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=""])
CFLAGS=$SAVED_CFLAGS])
AC_SUBST([AVX2_FLAGS])])
AC_ARG_ENABLE([sse4.1],
AS_HELP_STRING([--disable-sse4.1],
[Disable detection of SSE4.1 support
@ -464,7 +485,7 @@ AC_ARG_ENABLE([sdl],
@<:@default=auto@:>@]))
AS_IF([test "x$enable_sdl" != "xno"], [
CLEAR_LIBVARS([SDL])
AC_PATH_PROGS([LIBSDL_CONFIG], [sdl-config])
AC_PATH_PROGS([LIBSDL_CONFIG], [sdl2-config])
if test -n "$LIBSDL_CONFIG"; then
SDL_INCLUDES=`$LIBSDL_CONFIG --cflags`
SDL_LIBS="`$LIBSDL_CONFIG --libs`"
@ -474,13 +495,12 @@ AS_IF([test "x$enable_sdl" != "xno"], [
sdl_header="no"
LIBCHECK_PROLOGUE([SDL])
AC_CHECK_HEADER([SDL/SDL.h], [sdl_header="SDL/SDL.h"],
[AC_CHECK_HEADER([SDL.h], [sdl_header="SDL.h"],
[AC_MSG_WARN(SDL library not available - no sdl.h)])])
AC_CHECK_HEADER([SDL2/SDL.h], [sdl_header="SDL2/SDL.h"],
[AC_MSG_WARN(SDL2 library not available - no SDL.h)])
if test x"$sdl_header" != "xno"; then
AC_LANG_PUSH(C)
SDL_SAVED_LIBS="$LIBS"
for lib in "" "-lSDL" "-lSDLmain -lSDL"; do
for lib in "" "-lSDL2" "-lSDL2main -lSDL2"; do
LIBS="$SDL_SAVED_LIBS $lib"
# Perform a full link to ensure SDL_main is resolved if needed.
AC_LINK_IFELSE(
@ -762,7 +782,8 @@ AC_CONFIG_FILES([Makefile src/Makefile man/Makefile \
src/libwebp.pc src/libwebpdecoder.pc \
src/demux/libwebpdemux.pc src/mux/libwebpmux.pc])
dnl fix exports from MinGW builds
AC_CONFIG_COMMANDS_POST([$SED -i 's/-DDLL_EXPORT/-DWEBP_DLL/' config.status])
AC_OUTPUT
AC_MSG_NOTICE([

View File

@ -157,7 +157,7 @@ decoding is not finished yet or VP8_STATUS_OK when decoding is done. Any other
status is an error condition.
The 'idec' object must always be released (even upon an error condition) by
calling: WebPDelete(idec).
calling: WebPIDelete(idec).
To retrieve partially decoded picture samples, one must use the corresponding
method: WebPIDecGetRGB or WebPIDecGetYUVA. It will return the last displayable

View File

@ -96,6 +96,24 @@ make
make install
```
## Building libwebp - Using vcpkg
You can download and install libwebp using the
[vcpkg](https://github.com/Microsoft/vcpkg) dependency manager:
```shell
git clone https://github.com/Microsoft/vcpkg.git
cd vcpkg
./bootstrap-vcpkg.sh
./vcpkg integrate install
./vcpkg install libwebp
```
The libwebp port in vcpkg is kept up to date by Microsoft team members and
community contributors. If the version is out of date, please
[create an issue or pull request](https://github.com/Microsoft/vcpkg) on the
vcpkg repository.
## CMake
With CMake, you can compile libwebp, cwebp, dwebp, gif2webp, img2webp, webpinfo
@ -210,4 +228,4 @@ generated code, but is untested.
## Javascript decoder
Libwebp can be compiled into a JavaScript decoder using Emscripten and CMake.
See the [corresponding documentation](../README.md)
See the [corresponding documentation](../webp_js/README.md)

View File

@ -17,10 +17,11 @@ rubygems will install automatically. The following will apply inline CSS
styling; an external stylesheet is not needed.
```shell
$ kramdown doc/webp-lossless-bitstream-spec.txt --template \
doc/template.html --coderay-css style --coderay-line-numbers ' ' \
--coderay-default-lang c > \
doc/output/webp-lossless-bitstream-spec.html
$ kramdown doc/webp-lossless-bitstream-spec.txt \
--template doc/template.html \
-x syntax-coderay --syntax-highlighter coderay \
--syntax-highlighter-opts "{default_lang: c, line_numbers: , css: style}" \
> doc/output/webp-lossless-bitstream-spec.html
```
Optimally, use kramdown 0.13.7 or newer if syntax highlighting desired.

View File

@ -82,8 +82,8 @@ Options:
green=0xe0 and blue=0xd0
-noalpha ............... discard any transparency information
-lossless .............. encode image losslessly, default=off
-near_lossless <int> ... use near-lossless image
preprocessing (0..100=off), default=100
-near_lossless <int> ... use near-lossless image preprocessing
(0..100=off), default=100
-hint <string> ......... specify image characteristics hint,
one of: photo, picture or graph
@ -295,19 +295,23 @@ etc.
Usage:
```shell
img2webp [file_options] [[frame_options] frame_file]...
img2webp [file_options] [[frame_options] frame_file]... [-o webp_file]
```
File-level options (only used at the start of compression):
```
-min_size ............ minimize size
-loop <int> .......... loop count (default: 0, = infinite loop)
-kmax <int> .......... maximum number of frame between key-frames
(0=only keyframes)
-kmin <int> .......... minimum number of frame between key-frames
(0=disable key-frames altogether)
-mixed ............... use mixed lossy/lossless automatic mode
-near_lossless <int> . use near-lossless image preprocessing
(0..100=off), default=100
-sharp_yuv ........... use sharper (and slower) RGB->YUV conversion
(lossy only)
-loop <int> .......... loop count (default: 0, = infinite loop)
-v ................... verbose mode
-h ................... this help
-version ............. print version number and exit
@ -317,10 +321,13 @@ Per-frame options (only used for subsequent images input):
```
-d <int> ............. frame duration in ms (default: 100)
-lossless ........... use lossless mode (default)
-lossy ... ........... use lossy mode
-lossless ............ use lossless mode (default)
-lossy ............... use lossy mode
-q <float> ........... quality
-m <int> ............. method to use
-m <int> ............. compression method (0=fast, 6=slowest), default=4
-exact, -noexact ..... preserve or alter RGB values in transparent area
(default: -noexact, may cause artifacts
with lossy animations)
```
example: `img2webp -loop 2 in0.png -lossy in1.jpg -d 80 in2.tiff -o out.webp`
@ -347,8 +354,12 @@ Options:
-lossy ................. encode image using lossy compression
-mixed ................. for each frame in the image, pick lossy
or lossless compression heuristically
-near_lossless <int> ... use near-lossless image preprocessing
(0..100=off), default=100
-sharp_yuv ............. use sharper (and slower) RGB->YUV conversion
(lossy only)
-q <float> ............. quality factor (0:small..100:big)
-m <int> ............... compression method (0=fast, 6=slowest)
-m <int> ............... compression method (0=fast, 6=slowest), default=4
-min_size .............. minimize output size (default:off)
lossless compression by default; can be
combined with -q, -m, -lossy or -mixed

View File

@ -20,47 +20,48 @@ WebP Container Specification
Introduction
------------
WebP is an image format that uses either (i) the VP8 key frame encoding
to compress image data in a lossy way, or (ii) the WebP lossless encoding
(and possibly other encodings in the future). These encoding schemes should
make it more efficient than currently used formats. It is optimized for fast
image transfer over the network (e.g., for websites). The WebP format has
feature parity (color profile, metadata, animation, etc.) with other formats as
well. This document describes the structure of a WebP file.
WebP is an image format that uses either (i) the VP8 key frame encoding to
compress image data in a lossy way or (ii) the WebP lossless encoding. These
encoding schemes should make it more efficient than older formats, such as JPEG,
GIF, and PNG. It is optimized for fast image transfer over the network (for
example, for websites). The WebP format has feature parity (color profile,
metadata, animation, etc.) with other formats as well. This document describes
the structure of a WebP file.
The WebP container (i.e., RIFF container for WebP) allows feature support over
and above the basic use case of WebP (i.e., a file containing a single image
encoded as a VP8 key frame). The WebP container provides additional support
for:
The WebP container (that is, the RIFF container for WebP) allows feature support
over and above the basic use case of WebP (that is, a file containing a single
image encoded as a VP8 key frame). The WebP container provides additional
support for the following:
* **Lossless compression.** An image can be losslessly compressed, using the
* Lossless Compression: An image can be losslessly compressed, using the
WebP Lossless Format.
* **Metadata.** An image may have metadata stored in Exif or XMP formats.
* Metadata: An image may have metadata stored in Exchangeable Image File
Format (Exif) or Extensible Metadata Platform (XMP) format.
* **Transparency.** An image may have transparency, i.e., an alpha channel.
* Transparency: An image may have transparency, that is, an alpha channel.
* **Color Profile.** An image may have an embedded ICC profile as described
* Color Profile: An image may have an embedded ICC profile as described
by the [International Color Consortium][iccspec].
* **Animation.** An image may have multiple frames with pauses between them,
* Animation: An image may have multiple frames with pauses between them,
making it an animation.
Terminology & Basics
--------------------
The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD",
"SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and "OPTIONAL" in this
document are to be interpreted as described in BCP 14 [RFC 2119][] [RFC 8174][]
when, and only when, they appear in all capitals, as shown here.
Bit numbering in chunk diagrams starts at `0` for the most significant bit
('MSB 0') as described in [RFC 1166][].
Terminology & Basics
--------------------
A WebP file contains either a still image (i.e., an encoded matrix of pixels)
A WebP file contains either a still image (that is, an encoded matrix of pixels)
or an [animation](#animation). Optionally, it can also contain transparency
information, color profile and metadata. In case we need to refer only to the
matrix of pixels, we will call it the _canvas_ of the image.
information, a color profile and metadata. We refer to the matrix of pixels as
the _canvas_ of the image.
Bit numbering in chunk diagrams starts at `0` for the most significant bit
('MSB 0'), as described in [RFC 1166][].
Below are additional terms used throughout this document:
@ -83,20 +84,19 @@ _uint32_
_FourCC_
: A _FourCC_ (four-character code) is a _uint32_ created by concatenating four
: A four-character code (FourCC) is a _uint32_ created by concatenating four
ASCII characters in little-endian order. This means 'aaaa' (0x61616161) and
'AAAA' (0x41414141) are treated as different _FourCCs_.
_1-based_
: An unsigned integer field storing values offset by `-1`. e.g., Such a field
would store value _25_ as _24_.
: An unsigned integer field storing values offset by `-1`, for example, such a
field would store value _25_ as _24_.
_ChunkHeader('ABCD')_
: This is used to describe the _FourCC_ and _Chunk Size_ header of individual
chunks, where 'ABCD' is the FourCC for the chunk. This element's size is 8
bytes.
: Used to describe the _FourCC_ and _Chunk Size_ header of individual chunks,
where 'ABCD' is the FourCC for the chunk. This element's size is 8 bytes.
RIFF File Format
@ -124,14 +124,14 @@ Chunk FourCC: 32 bits
Chunk Size: 32 bits (_uint32_)
: The size of the chunk in bytes, not including this field, the chunk
identifier or padding.
identifier, or padding.
Chunk Payload: _Chunk Size_ bytes
: The data payload. If _Chunk Size_ is odd, a single padding byte -- that MUST
: The data payload. If _Chunk Size_ is odd, a single padding byte -- which MUST
be `0` to conform with RIFF -- is added.
**Note:** RIFF has a convention that all-uppercase chunk FourCCs are standard
**Note**: RIFF has a convention that all-uppercase chunk FourCCs are standard
chunks that apply to any RIFF file format, while FourCCs specific to a file
format are all lowercase. WebP does not follow this convention.
@ -151,24 +151,24 @@ WebP File Header
'RIFF': 32 bits
: The ASCII characters 'R' 'I' 'F' 'F'.
: The ASCII characters 'R', 'I', 'F', 'F'.
File Size: 32 bits (_uint32_)
: The size of the file in bytes starting at offset 8. The maximum value of
: The size of the file in bytes, starting at offset 8. The maximum value of
this field is 2^32 minus 10 bytes and thus the size of the whole file is at
most 4GiB minus 2 bytes.
most 4 GiB minus 2 bytes.
'WEBP': 32 bits
: The ASCII characters 'W' 'E' 'B' 'P'.
: The ASCII characters 'W', 'E', 'B', 'P'.
A WebP file MUST begin with a RIFF header with the FourCC 'WEBP'. The file size
in the header is the total size of the chunks that follow plus `4` bytes for
the 'WEBP' FourCC. The file SHOULD NOT contain any data after the data
specified by _File Size_. Readers MAY parse such files, ignoring the trailing
data. As the size of any chunk is even, the size given by the RIFF header is
also even. The contents of individual chunks will be described in the following
also even. The contents of individual chunks are described in the following
sections.
@ -188,10 +188,10 @@ Simple WebP (lossy) file format:
| WebP file header (12 bytes) |
| |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
: VP8 chunk :
: 'VP8 ' Chunk :
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
VP8 chunk:
'VP8 ' Chunk:
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
@ -206,21 +206,21 @@ VP8 data: _Chunk Size_ bytes
: VP8 bitstream data.
Note the fourth character in the 'VP8 ' FourCC is an ASCII space (0x20).
Note that the fourth character in the 'VP8 ' FourCC is an ASCII space (0x20).
The VP8 bitstream format specification can be found at [VP8 Data Format and
Decoding Guide][vp8spec]. Note that the VP8 frame header contains the VP8 frame
The VP8 bitstream format specification is described in [VP8 Data Format and
Decoding Guide][rfc 6386]. Note that the VP8 frame header contains the VP8 frame
width and height. That is assumed to be the width and height of the canvas.
The VP8 specification describes how to decode the image into Y'CbCr format. To
convert to RGB, Rec. 601 SHOULD be used. Applications MAY use another
conversion method, but visual results may differ among decoders.
convert to RGB, [Recommendation BT.601][rec601] SHOULD be used. Applications MAY
use another conversion method, but visual results may differ among decoders.
Simple File Format (Lossless)
-----------------------------
**Note:** Older readers may not support files using the lossless format.
**Note**: Older readers may not support files using the lossless format.
This layout SHOULD be used if the image requires _lossless_ encoding (with an
optional transparency channel) and does not require advanced features provided
@ -235,10 +235,10 @@ Simple WebP (lossless) file format:
| WebP file header (12 bytes) |
| |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
: VP8L chunk :
: 'VP8L' Chunk :
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
VP8L chunk:
'VP8L' Chunk:
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
@ -262,21 +262,21 @@ and height of the canvas.
Extended File Format
--------------------
**Note:** Older readers may not support files using the extended format.
**Note**: Older readers may not support files using the extended format.
An extended format file consists of:
* A 'VP8X' chunk with information about features used in the file.
* A 'VP8X' Chunk with information about features used in the file.
* An optional 'ICCP' chunk with color profile.
* An optional 'ICCP' Chunk with a color profile.
* An optional 'ANIM' chunk with animation control data.
* An optional 'ANIM' Chunk with animation control data.
* Image data.
* An optional 'EXIF' chunk with Exif metadata.
* An optional 'EXIF' Chunk with Exif metadata.
* An optional 'XMP ' chunk with XMP metadata.
* An optional 'XMP ' Chunk with XMP metadata.
* An optional list of [unknown chunks](#unknown-chunks).
@ -290,15 +290,18 @@ up of:
For an _animated image_, the _image data_ consists of multiple frames. More
details about frames can be found in the [Animation](#animation) section.
All chunks SHOULD be placed in the same order as listed above. If a chunk
appears in the wrong place, the file is invalid, but readers MAY parse the
file, ignoring the chunks that are out of order.
All chunks necessary for reconstruction and color correction, that is, 'VP8X',
'ICCP', 'ANIM', 'ANMF', 'ALPH', 'VP8 ', and 'VP8L', MUST appear in the order
described earlier. Readers SHOULD fail when chunks necessary for reconstruction
and color correction are out of order.
**Rationale:** Setting the order of chunks should allow quicker file
parsing. For example, if an 'ALPH' chunk does not appear in its required
position, a decoder can choose to stop searching for it. The rule of
ignoring late chunks should make programs that need to do a full search
give the same results as the ones stopping early.
[Metadata](#metadata) and [unknown chunks](#unknown-chunks) MAY appear out of
order.
**Rationale:** The chunks necessary for reconstruction should appear first in
the file to allow a reader to begin decoding an image before receiving all of
the data. An application may benefit from varying the order of metadata and
custom chunks to suit the implementation.
Extended WebP file header:
{:#extended_header}
@ -326,7 +329,7 @@ Reserved (Rsv): 2 bits
ICC profile (I): 1 bit
: Set if the file contains an ICC profile.
: Set if the file contains an 'ICCP' Chunk.
Alpha (L): 1 bit
@ -343,7 +346,7 @@ XMP metadata (X): 1 bit
Animation (A): 1 bit
: Set if this is an animated image. Data in 'ANIM' and 'ANMF' chunks should be
: Set if this is an animated image. Data in 'ANIM' and 'ANMF' Chunks should be
used to control the animation.
Reserved (R): 1 bit
@ -372,9 +375,9 @@ Future specifications may add more fields. Unknown fields MUST be ignored.
#### Animation
An animation is controlled by ANIM and ANMF chunks.
An animation is controlled by 'ANIM' and 'ANMF' Chunks.
ANIM Chunk:
'ANIM' Chunk:
{:#anim_chunk}
For an animated image, this chunk contains the _global parameters_ of the
@ -396,14 +399,14 @@ Background Color: 32 bits (_uint32_)
: The default background color of the canvas in \[Blue, Green, Red, Alpha\]
byte order. This color MAY be used to fill the unused space on the canvas
around the frames, as well as the transparent pixels of the first frame.
Background color is also used when disposal method is `1`.
The background color is also used when the Disposal method is `1`.
**Note**:
**Notes**:
* Background color MAY contain a non-opaque alpha value, even if the _Alpha_
flag in [VP8X chunk](#extended_header) is unset.
* The background color MAY contain a non-opaque alpha value, even if the
_Alpha_ flag in the ['VP8X' Chunk](#extended_header) is unset.
* Viewer applications SHOULD treat the background color value as a hint, and
* Viewer applications SHOULD treat the background color value as a hint and
are not required to use it.
* The canvas is cleared at the start of each loop. The background color MAY be
@ -411,13 +414,14 @@ Background Color: 32 bits (_uint32_)
Loop Count: 16 bits (_uint16_)
: The number of times to loop the animation. `0` means infinitely.
: The number of times to loop the animation. If it is `0`, this means
infinitely.
This chunk MUST appear if the _Animation_ flag in the VP8X chunk is set.
This chunk MUST appear if the _Animation_ flag in the 'VP8X' Chunk is set.
If the _Animation_ flag is not set and this chunk is present, it MUST be
ignored.
ANMF chunk:
'ANMF' Chunk:
For animated images, this chunk contains information about a _single_ frame.
If the _Animation flag_ is not set, then this chunk SHOULD NOT be present.
@ -459,10 +463,10 @@ Frame Height Minus One: 24 bits (_uint24_)
Frame Duration: 24 bits (_uint24_)
: The time to wait before displaying the next frame, in 1 millisecond units.
Note the interpretation of frame duration of 0 (and often <= 10) is
implementation defined. Many tools and browsers assign a minimum duration
similar to GIF.
: The time to wait before displaying the next frame, in 1-millisecond units.
Note that the interpretation of the Frame Duration of 0 (and often <= 10) is
defined by the implementation. Many tools and browsers assign a minimum
duration similar to GIF.
Reserved: 6 bits
@ -473,10 +477,10 @@ Blending method (B): 1 bit
: Indicates how transparent pixels of _the current frame_ are to be blended
with corresponding pixels of the previous canvas:
* `0`: Use alpha blending. After disposing of the previous frame, render the
* `0`: Use alpha-blending. After disposing of the previous frame, render the
current frame on the canvas using [alpha-blending](#alpha-blending). If
the current frame does not have an alpha channel, assume alpha value of
255, effectively replacing the rectangle.
the current frame does not have an alpha channel, assume the alpha value
is 255, effectively replacing the rectangle.
* `1`: Do not blend. After disposing of the previous frame, render the
current frame on the canvas by overwriting the rectangle covered by the
@ -489,20 +493,20 @@ Disposal method (D): 1 bit
* `0`: Do not dispose. Leave the canvas as is.
* `1`: Dispose to background color. Fill the _rectangle_ on the canvas
covered by the _current frame_ with background color specified in the
[ANIM chunk](#anim_chunk).
* `1`: Dispose to the background color. Fill the _rectangle_ on the canvas
covered by the _current frame_ with the background color specified in the
['ANIM' Chunk](#anim_chunk).
**Notes**:
* The frame disposal only applies to the _frame rectangle_, that is, the
rectangle defined by _Frame X_, _Frame Y_, _frame width_ and _frame height_.
It may or may not cover the whole canvas.
rectangle defined by _Frame X_, _Frame Y_, _frame width_, and _frame
height_. It may or may not cover the whole canvas.
{:#alpha-blending}
* **Alpha-blending**:
* Alpha-blending:
Given that each of the R, G, B and A channels is 8-bit, and the RGB
Given that each of the R, G, B, and A channels is 8 bits, and the RGB
channels are _not premultiplied_ by alpha, the formula for blending
'dst' onto 'src' is:
@ -518,10 +522,10 @@ Disposal method (D): 1 bit
* Alpha-blending SHOULD be done in linear color space, by taking into account
the [color profile](#color-profile) of the image. If the color profile is
not present, sRGB is to be assumed. (Note that sRGB also needs to be
linearized due to a gamma of ~2.2).
not present, standard RGB (sRGB) is to be assumed. (Note that sRGB also
needs to be linearized due to a gamma of ~2.2.)
Frame Data: _Chunk Size_ - `16` bytes
Frame Data: _Chunk Size_ bytes - `16`
: Consists of:
@ -531,8 +535,8 @@ Frame Data: _Chunk Size_ - `16` bytes
* An optional list of [unknown chunks](#unknown-chunks).
**Note**: The 'ANMF' payload, _Frame Data_ above, consists of individual
_padded_ chunks as described by the [RIFF file format](#riff-file-format).
**Note**: The 'ANMF' payload, _Frame Data_, consists of individual
_padded_ chunks, as described by the [RIFF file format](#riff-file-format).
#### Alpha
@ -549,18 +553,20 @@ Reserved (Rsv): 2 bits
: MUST be `0`. Readers MUST ignore this field.
Pre-processing (P): 2 bits
Preprocessing (P): 2 bits
: These _informative_ bits are used to signal the pre-processing that has
: These _informative_ bits are used to signal the preprocessing that has
been performed during compression. The decoder can use this information to
e.g. dither the values or smooth the gradients prior to display.
for example, dither the values or smooth the gradients prior to display.
* `0`: No pre-processing.
* `0`: No preprocessing.
* `1`: Level reduction.
Decoders are not required to use this information in any specified way.
Filtering method (F): 2 bits
: The filtering method used:
: The filtering methods used are described as follows:
* `0`: None.
* `1`: Horizontal filter.
@ -584,8 +590,8 @@ made depending on the filtering method:
where `clip(v)` is equal to:
* 0 if v < 0
* 255 if v > 255
* 0 if v < 0,
* 255 if v > 255, or
* v otherwise
The final value is derived by adding the decompressed value `X` to the
@ -594,17 +600,15 @@ into the \[0..255\] one:
`alpha = (predictor + X) % 256`
There are special cases for the left-most and top-most pixel positions:
There are special cases for the left-most and top-most pixel positions. For
example, the top-left value at location (0, 0) uses 0 as the predictor value.
Otherwise:
* The top-left value at location (0, 0) uses 0 as predictor value. Otherwise,
* For horizontal or gradient filtering methods, the left-most pixels at
location (0, y) are predicted using the location (0, y-1) just above.
* For vertical or gradient filtering methods, the top-most pixels at
location (x, 0) are predicted using the location (x-1, 0) on the left.
Decoders are not required to use this information in any specified way.
Compression method (C): 2 bits
: The compression method used:
@ -612,37 +616,37 @@ Compression method (C): 2 bits
* `0`: No compression.
* `1`: Compressed using the WebP lossless format.
Alpha bitstream: _Chunk Size_ - `1` bytes
Alpha bitstream: _Chunk Size_ bytes - `1`
: Encoded alpha bitstream.
This optional chunk contains encoded alpha data for this frame. A frame
containing a 'VP8L' chunk SHOULD NOT contain this chunk.
containing a 'VP8L' Chunk SHOULD NOT contain this chunk.
**Rationale**: The transparency information is already part of the 'VP8L'
chunk.
Chunk.
The alpha channel data is stored as uncompressed raw data (when
The alpha channel data is stored as uncompressed raw data (when the
compression method is '0') or compressed using the lossless format
(when the compression method is '1').
* Raw data: consists of a byte sequence of length width * height,
* Raw data: This consists of a byte sequence of length = width * height,
containing all the 8-bit transparency values in scan order.
* Lossless format compression: the byte sequence is a compressed
image-stream (as described in the [WebP Lossless Bitstream Format]
[webpllspec]) of implicit dimension width x height. That is, this
image-stream does NOT contain any headers describing the image dimension.
* Lossless format compression: The byte sequence is a compressed
image-stream (as described in ["WebP Lossless Bitstream Format"]
[webpllspec]) of implicit dimensions width x height. That is, this
image-stream does NOT contain any headers describing the image dimensions.
**Rationale**: the dimension is already known from other sources,
so storing it again would be redundant and error-prone.
**Rationale**: The dimensions are already known from other sources,
so storing them again would be redundant and prone to error.
Once the image-stream is decoded into ARGB color values, following
the process described in the lossless format specification, the
transparency information must be extracted from the *green* channel
of the ARGB quadruplet.
Once the image-stream is decoded into Alpha, Red, Green, Blue (ARGB) color
values, following the process described in the lossless format
specification, the transparency information must be extracted from the
*green* channel of the ARGB quadruplet.
**Rationale**: the green channel is allowed extra transformation
**Rationale**: The green channel is allowed extra transformation
steps in the specification -- unlike the other channels -- that can
improve compression.
@ -650,13 +654,13 @@ compression method is '0') or compressed using the lossless format
This chunk contains compressed bitstream data for a single frame.
A bitstream chunk may be either (i) a VP8 chunk, using "VP8 " (note the
significant fourth-character space) as its tag _or_ (ii) a VP8L chunk, using
"VP8L" as its tag.
A bitstream chunk may be either (i) a 'VP8 ' Chunk, using 'VP8 ' (note the
significant fourth-character space) as its FourCC, _or_ (ii) a 'VP8L' Chunk,
using 'VP8L' as its FourCC.
The formats of VP8 and VP8L chunks are as described in sections
The formats of 'VP8 ' and 'VP8L' Chunks are as described in sections
[Simple File Format (Lossy)](#simple-file-format-lossy)
and [Simple File Format (Lossless)](#simple-file-format-lossless) respectively.
and [Simple File Format (Lossless)](#simple-file-format-lossless), respectively.
#### Color Profile
@ -683,14 +687,14 @@ If this chunk is not present, sRGB SHOULD be assumed.
#### Metadata
Metadata can be stored in 'EXIF' or 'XMP ' chunks.
Metadata can be stored in 'EXIF' or 'XMP ' Chunks.
There SHOULD be at most one chunk of each type ('EXIF' and 'XMP '). If there
are more such chunks, readers MAY ignore all except the first one.
The chunks are defined as follows:
EXIF chunk:
'EXIF' Chunk:
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
@ -705,7 +709,7 @@ Exif Metadata: _Chunk Size_ bytes
: Image metadata in Exif format.
XMP chunk:
'XMP ' Chunk:
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
@ -720,72 +724,73 @@ XMP Metadata: _Chunk Size_ bytes
: Image metadata in XMP format.
Note the fourth character in the 'XMP ' FourCC is an ASCII space (0x20).
Note that the fourth character in the 'XMP ' FourCC is an ASCII space (0x20).
Additional guidance about handling metadata can be found in the
Metadata Working Group's [Guidelines for Handling Metadata][metadata].
Metadata Working Group's ["Guidelines for Handling Metadata"][metadata].
#### Unknown Chunks
A RIFF chunk (described in [this](#terminology-amp-basics) section) whose _chunk
tag_ is different from any of the chunks described in this document, is
A RIFF chunk (described in the [RIFF File Format](#riff-file-format) section)
whose FourCC is different from any of the chunks described in this document, is
considered an _unknown chunk_.
**Rationale**: Allowing unknown chunks gives a provision for future extension
of the format, and also allows storage of any application-specific data.
of the format and also allows storage of any application-specific data.
A file MAY contain unknown chunks:
* At the end of the file as described in [Extended WebP file
header](#extended_header) section.
* At the end of ANMF chunks as described in the
* at the end of the file, as described in [Extended WebP file
header](#extended_header) section, or
* at the end of 'ANMF' Chunks, as described in the
[Animation](#animation) section.
Readers SHOULD ignore these chunks. Writers SHOULD preserve them in their
original order (unless they specifically intend to modify these chunks).
### Assembling the Canvas From Frames
### Canvas Assembly from Frames
Here we provide an overview of how a reader MUST assemble a canvas in the case
of an animated image.
The process begins with creating a canvas using the dimensions given in the
'VP8X' chunk, `Canvas Width Minus One + 1` pixels wide by `Canvas Height Minus
One + 1` pixels high. The `Loop Count` field from the 'ANIM' chunk controls how
'VP8X' Chunk, `Canvas Width Minus One + 1` pixels wide by `Canvas Height Minus
One + 1` pixels high. The `Loop Count` field from the 'ANIM' Chunk controls how
many times the animation process is repeated. This is `Loop Count - 1` for
non-zero `Loop Count` values or infinitely if `Loop Count` is zero.
nonzero `Loop Count` values or infinite if the `Loop Count` is zero.
At the beginning of each loop iteration the canvas is filled using the
background color from the 'ANIM' chunk or an application defined color.
At the beginning of each loop iteration, the canvas is filled using the
background color from the 'ANIM' Chunk or an application-defined color.
'ANMF' chunks contain individual frames given in display order. Before rendering
'ANMF' Chunks contain individual frames given in display order. Before rendering
each frame, the previous frame's `Disposal method` is applied.
The rendering of the decoded frame begins at the Cartesian coordinates (`2 *
Frame X`, `2 * Frame Y`) using the top-left corner of the canvas as the origin.
Frame X`, `2 * Frame Y`), using the top-left corner of the canvas as the origin.
`Frame Width Minus One + 1` pixels wide by `Frame Height Minus One + 1` pixels
high are rendered onto the canvas using the `Blending method`.
The canvas is displayed for `Frame Duration` milliseconds. This continues until
all frames given by 'ANMF' chunks have been displayed. A new loop iteration is
then begun or the canvas is left in its final state if all iterations have been
all frames given by 'ANMF' Chunks have been displayed. A new loop iteration is
then begun, or the canvas is left in its final state if all iterations have been
completed.
The following pseudocode illustrates the rendering process. The notation
_VP8X.field_ means the field in the 'VP8X' chunk with the same description.
_VP8X.field_ means the field in the 'VP8X' Chunk with the same description.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
assert VP8X.flags.hasAnimation
VP8X.flags.hasAnimation MUST be TRUE
canvas ← new image of size VP8X.canvasWidth x VP8X.canvasHeight with
background color ANIM.background_color.
background color ANIM.background_color or
application-defined color.
loop_count ← ANIM.loopCount
dispose_method ← Dispose to background color
if loop_count == 0:
loop_count = ∞
frame_params ← nil
assert next chunk in image_data is ANMF
next chunk in image_data is ANMF MUST be TRUE
for loop = 0..loop_count - 1
clear canvas to ANIM.background_color or application defined color
clear canvas to ANIM.background_color or application-defined color
until eof or non-ANMF chunk
frame_params.frameX = Frame X
frame_params.frameY = Frame Y
@ -794,22 +799,25 @@ for loop = 0..loop_count - 1
frame_params.frameDuration = Frame Duration
frame_right = frame_params.frameX + frame_params.frameWidth
frame_bottom = frame_params.frameY + frame_params.frameHeight
assert VP8X.canvasWidth >= frame_right
assert VP8X.canvasHeight >= frame_bottom
VP8X.canvasWidth >= frame_right MUST be TRUE
VP8X.canvasHeight >= frame_bottom MUST be TRUE
for subchunk in 'Frame Data':
if subchunk.tag == "ALPH":
assert alpha subchunks not found in 'Frame Data' earlier
alpha subchunks not found in 'Frame Data' earlier MUST be
TRUE
frame_params.alpha = alpha_data
else if subchunk.tag == "VP8 " OR subchunk.tag == "VP8L":
assert bitstream subchunks not found in 'Frame Data' earlier
bitstream subchunks not found in 'Frame Data' earlier MUST
be TRUE
frame_params.bitstream = bitstream_data
apply dispose_method.
render frame with frame_params.alpha and frame_params.bitstream
on canvas with top-left corner at (frame_params.frameX,
frame_params.frameY), using blending method
frame_params.frameY), using Blending method
frame_params.blendingMethod.
canvas contains the decoded image.
Show the contents of the canvas for
frame_params.frameDuration * 1ms.
frame_params.frameDuration * 1 ms.
dispose_method = frame_params.disposeMethod
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@ -817,7 +825,7 @@ for loop = 0..loop_count - 1
Example File Layouts
--------------------
A lossy encoded image with alpha may look as follows:
A lossy-encoded image with alpha may look as follows:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
RIFF/WEBP
@ -826,16 +834,16 @@ RIFF/WEBP
+- VP8 (bitstream)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
A losslessly encoded image may look as follows:
A lossless-encoded image may look as follows:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
RIFF/WEBP
+- VP8X (descriptions of features used)
+- XYZW (unknown chunk)
+- VP8L (lossless bitstream)
+- XYZW (unknown chunk)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
A lossless image with ICC profile and XMP metadata may
A lossless image with an ICC profile and XMP metadata may
look as follows:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@ -859,10 +867,11 @@ RIFF/WEBP
+- EXIF (metadata)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
[vp8spec]: https://datatracker.ietf.org/doc/html/rfc6386
[webpllspec]: https://chromium.googlesource.com/webm/libwebp/+/HEAD/doc/webp-lossless-bitstream-spec.txt
[iccspec]: https://www.color.org/icc_specs2.xalter
[metadata]: https://web.archive.org/web/20180919181934/http://www.metadataworkinggroup.org/pdf/mwg_guidance.pdf
[rec601]: https://www.itu.int/rec/R-REC-BT.601
[rfc 1166]: https://datatracker.ietf.org/doc/html/rfc1166
[rfc 2119]: https://datatracker.ietf.org/doc/html/rfc2119
[rfc 6386]: https://datatracker.ietf.org/doc/html/rfc6386
[rfc 8174]: https://datatracker.ietf.org/doc/html/rfc8174

File diff suppressed because it is too large Load Diff

View File

@ -67,7 +67,7 @@ dwebp_LDADD += ../src/libwebp.la
dwebp_LDADD +=$(PNG_LIBS) $(JPEG_LIBS)
gif2webp_SOURCES = gif2webp.c gifdec.c gifdec.h
gif2webp_CPPFLAGS = $(AM_CPPFLAGS) $(GIF_INCLUDES)
gif2webp_CPPFLAGS = $(AM_CPPFLAGS) $(GIF_INCLUDES) -I$(top_srcdir)
gif2webp_LDADD =
gif2webp_LDADD += libexample_util.la
gif2webp_LDADD += ../imageio/libimageio_util.la
@ -92,7 +92,7 @@ webpmux_LDADD += ../src/mux/libwebpmux.la
webpmux_LDADD += ../src/libwebp.la
img2webp_SOURCES = img2webp.c
img2webp_CPPFLAGS = $(AM_CPPFLAGS)
img2webp_CPPFLAGS = $(AM_CPPFLAGS) -I$(top_srcdir)
img2webp_LDADD =
img2webp_LDADD += libexample_util.la
img2webp_LDADD += ../imageio/libimageio_util.la

View File

@ -16,7 +16,7 @@
#include <assert.h>
#include <limits.h>
#include <stdio.h>
#include <stdlib.h> // for 'strtod'.
#include <stdlib.h>
#include <string.h> // for 'strcmp'.
#include "./anim_util.h"
@ -206,8 +206,9 @@ static void Help(void) {
printf(" -version ............ print version number and exit\n");
}
// Returns 0 on success, 1 if animation files differ, and 2 for any error.
int main(int argc, const char* argv[]) {
int return_code = -1;
int return_code = 2;
int dump_frames = 0;
const char* dump_folder = NULL;
double min_psnr = 0.;
@ -269,18 +270,18 @@ int main(int argc, const char* argv[]) {
}
if (parse_error) {
Help();
FREE_WARGV_AND_RETURN(-1);
FREE_WARGV_AND_RETURN(return_code);
}
}
if (argc < 3) {
Help();
FREE_WARGV_AND_RETURN(-1);
FREE_WARGV_AND_RETURN(return_code);
}
if (!got_input2) {
Help();
FREE_WARGV_AND_RETURN(-1);
FREE_WARGV_AND_RETURN(return_code);
}
if (dump_frames) {
@ -293,7 +294,7 @@ int main(int argc, const char* argv[]) {
if (!ReadAnimatedImage(files[i], &images[i], dump_frames, dump_folder)) {
WFPRINTF(stderr, "Error decoding file: %s\n Aborting.\n",
(const W_CHAR*)files[i]);
return_code = -2;
return_code = 2;
goto End;
} else {
MinimizeAnimationFrames(&images[i], max_diff);
@ -304,7 +305,7 @@ int main(int argc, const char* argv[]) {
premultiply, min_psnr)) {
WFPRINTF(stderr, "\nFiles %s and %s differ.\n", (const W_CHAR*)files[0],
(const W_CHAR*)files[1]);
return_code = -3;
return_code = 1;
} else {
WPRINTF("\nFiles %s and %s are identical.\n", (const W_CHAR*)files[0],
(const W_CHAR*)files[1]);

View File

@ -12,6 +12,7 @@
// Author: Skal (pascal.massimino@gmail.com)
#include <stdio.h>
#include <stdlib.h>
#include <string.h> // for 'strcmp'.
#include "./anim_util.h"
@ -35,6 +36,7 @@ static void Help(void) {
printf(" -version ............ print version number and exit\n");
}
// Returns EXIT_SUCCESS on success, EXIT_FAILURE on failure.
int main(int argc, const char* argv[]) {
int error = 0;
const W_CHAR* dump_folder = TO_W_CHAR(".");
@ -47,7 +49,7 @@ int main(int argc, const char* argv[]) {
if (argc < 2) {
Help();
FREE_WARGV_AND_RETURN(-1);
FREE_WARGV_AND_RETURN(EXIT_FAILURE);
}
for (c = 1; !error && c < argc; ++c) {
@ -73,7 +75,7 @@ int main(int argc, const char* argv[]) {
suffix = TO_W_CHAR("pam");
} else if (!strcmp(argv[c], "-h") || !strcmp(argv[c], "-help")) {
Help();
FREE_WARGV_AND_RETURN(0);
FREE_WARGV_AND_RETURN(EXIT_SUCCESS);
} else if (!strcmp(argv[c], "-version")) {
int dec_version, demux_version;
GetAnimatedImageVersions(&dec_version, &demux_version);
@ -82,7 +84,7 @@ int main(int argc, const char* argv[]) {
(dec_version >> 0) & 0xff,
(demux_version >> 16) & 0xff, (demux_version >> 8) & 0xff,
(demux_version >> 0) & 0xff);
FREE_WARGV_AND_RETURN(0);
FREE_WARGV_AND_RETURN(EXIT_SUCCESS);
} else {
uint32_t i;
AnimatedImage image;
@ -98,7 +100,11 @@ int main(int argc, const char* argv[]) {
for (i = 0; !error && i < image.num_frames; ++i) {
W_CHAR out_file[1024];
WebPDecBuffer buffer;
WebPInitDecBuffer(&buffer);
if (!WebPInitDecBuffer(&buffer)) {
fprintf(stderr, "Cannot init dec buffer\n");
error = 1;
continue;
}
buffer.colorspace = MODE_RGBA;
buffer.is_external_memory = 1;
buffer.width = image.canvas_width;
@ -117,5 +123,5 @@ int main(int argc, const char* argv[]) {
ClearAnimatedImage(&image);
}
}
FREE_WARGV_AND_RETURN(error ? 1 : 0);
FREE_WARGV_AND_RETURN(error ? EXIT_FAILURE : EXIT_SUCCESS);
}

View File

@ -771,6 +771,7 @@ void GetDiffAndPSNR(const uint8_t rgba1[], const uint8_t rgba2[],
*psnr = 99.; // PSNR when images are identical.
} else {
sse /= stride * height;
assert(sse != 0.0);
*psnr = 4.3429448 * log(255. * 255. / sse);
}
}

View File

@ -178,8 +178,14 @@ static void PrintFullLosslessInfo(const WebPAuxStats* const stats,
if (stats->lossless_features & 8) fprintf(stderr, " PALETTE");
fprintf(stderr, "\n");
}
fprintf(stderr, " * Precision Bits: histogram=%d transform=%d cache=%d\n",
stats->histogram_bits, stats->transform_bits, stats->cache_bits);
fprintf(stderr, " * Precision Bits: histogram=%d", stats->histogram_bits);
if (stats->lossless_features & 1) {
fprintf(stderr, " prediction=%d", stats->transform_bits);
}
if (stats->lossless_features & 2) {
fprintf(stderr, " cross-color=%d", stats->cross_color_transform_bits);
}
fprintf(stderr, " cache=%d\n", stats->cache_bits);
if (stats->palette_size > 0) {
fprintf(stderr, " * Palette size: %d\n", stats->palette_size);
}
@ -306,6 +312,7 @@ static int MyWriter(const uint8_t* data, size_t data_size,
// Dumps a picture as a PGM file using the IMC4 layout.
static int DumpPicture(const WebPPicture* const picture, const char* PGM_name) {
int y;
int ok = 0;
const int uv_width = (picture->width + 1) / 2;
const int uv_height = (picture->height + 1) / 2;
const int stride = (picture->width + 1) & ~1;
@ -320,23 +327,26 @@ static int DumpPicture(const WebPPicture* const picture, const char* PGM_name) {
if (f == NULL) return 0;
fprintf(f, "P5\n%d %d\n255\n", stride, height);
for (y = 0; y < picture->height; ++y) {
if (fwrite(src_y, picture->width, 1, f) != 1) return 0;
if (fwrite(src_y, picture->width, 1, f) != 1) goto Error;
if (picture->width & 1) fputc(0, f); // pad
src_y += picture->y_stride;
}
for (y = 0; y < uv_height; ++y) {
if (fwrite(src_u, uv_width, 1, f) != 1) return 0;
if (fwrite(src_v, uv_width, 1, f) != 1) return 0;
if (fwrite(src_u, uv_width, 1, f) != 1) goto Error;
if (fwrite(src_v, uv_width, 1, f) != 1) goto Error;
src_u += picture->uv_stride;
src_v += picture->uv_stride;
}
for (y = 0; y < alpha_height; ++y) {
if (fwrite(src_a, picture->width, 1, f) != 1) return 0;
if (fwrite(src_a, picture->width, 1, f) != 1) goto Error;
if (picture->width & 1) fputc(0, f); // pad
src_a += picture->a_stride;
}
ok = 1;
Error:
fclose(f);
return 1;
return ok;
}
// -----------------------------------------------------------------------------
@ -592,9 +602,8 @@ static void HelpLong(void) {
" green=0xe0 and blue=0xd0\n");
printf(" -noalpha ............... discard any transparency information\n");
printf(" -lossless .............. encode image losslessly, default=off\n");
printf(" -near_lossless <int> ... use near-lossless image\n"
" preprocessing (0..100=off), "
"default=100\n");
printf(" -near_lossless <int> ... use near-lossless image preprocessing\n"
" (0..100=off), default=100\n");
printf(" -hint <string> ......... specify image characteristics hint,\n");
printf(" one of: photo, picture or graph\n");
@ -648,8 +657,9 @@ static const char* const kErrorMessages[VP8_ENC_ERROR_LAST] = {
//------------------------------------------------------------------------------
// Returns EXIT_SUCCESS on success, EXIT_FAILURE on failure.
int main(int argc, const char* argv[]) {
int return_value = -1;
int return_value = EXIT_FAILURE;
const char* in_file = NULL, *out_file = NULL, *dump_file = NULL;
FILE* out = NULL;
int c;
@ -683,22 +693,22 @@ int main(int argc, const char* argv[]) {
!WebPPictureInit(&original_picture) ||
!WebPConfigInit(&config)) {
fprintf(stderr, "Error! Version mismatch!\n");
FREE_WARGV_AND_RETURN(-1);
FREE_WARGV_AND_RETURN(EXIT_FAILURE);
}
if (argc == 1) {
HelpShort();
FREE_WARGV_AND_RETURN(0);
FREE_WARGV_AND_RETURN(EXIT_FAILURE);
}
for (c = 1; c < argc; ++c) {
int parse_error = 0;
if (!strcmp(argv[c], "-h") || !strcmp(argv[c], "-help")) {
HelpShort();
FREE_WARGV_AND_RETURN(0);
FREE_WARGV_AND_RETURN(EXIT_SUCCESS);
} else if (!strcmp(argv[c], "-H") || !strcmp(argv[c], "-longhelp")) {
HelpLong();
FREE_WARGV_AND_RETURN(0);
FREE_WARGV_AND_RETURN(EXIT_SUCCESS);
} else if (!strcmp(argv[c], "-o") && c + 1 < argc) {
out_file = (const char*)GET_WARGV(argv, ++c);
} else if (!strcmp(argv[c], "-d") && c + 1 < argc) {
@ -839,7 +849,7 @@ int main(int argc, const char* argv[]) {
printf("libsharpyuv: %d.%d.%d\n",
(sharpyuv_version >> 24) & 0xff, (sharpyuv_version >> 16) & 0xffff,
sharpyuv_version & 0xff);
FREE_WARGV_AND_RETURN(0);
FREE_WARGV_AND_RETURN(EXIT_SUCCESS);
} else if (!strcmp(argv[c], "-progress")) {
show_progress = 1;
} else if (!strcmp(argv[c], "-quiet")) {
@ -901,7 +911,7 @@ int main(int argc, const char* argv[]) {
if (i == kNumTokens) {
fprintf(stderr, "Error! Unknown metadata type '%.*s'\n",
(int)(token - start), start);
FREE_WARGV_AND_RETURN(-1);
FREE_WARGV_AND_RETURN(EXIT_FAILURE);
}
start = token + 1;
}
@ -920,14 +930,14 @@ int main(int argc, const char* argv[]) {
} else if (argv[c][0] == '-') {
fprintf(stderr, "Error! Unknown option '%s'\n", argv[c]);
HelpLong();
FREE_WARGV_AND_RETURN(-1);
FREE_WARGV_AND_RETURN(EXIT_FAILURE);
} else {
in_file = (const char*)GET_WARGV(argv, c);
}
if (parse_error) {
HelpLong();
FREE_WARGV_AND_RETURN(-1);
FREE_WARGV_AND_RETURN(EXIT_FAILURE);
}
}
if (in_file == NULL) {
@ -1228,7 +1238,7 @@ int main(int argc, const char* argv[]) {
PrintMetadataInfo(&metadata, metadata_written);
}
}
return_value = 0;
return_value = EXIT_SUCCESS;
Error:
WebPMemoryWriterClear(&memory_writer);

View File

@ -177,6 +177,7 @@ static uint8_t* AllocateExternalBuffer(WebPDecoderConfig* config,
return external_buffer;
}
// Returns EXIT_SUCCESS on success, EXIT_FAILURE on failure.
int main(int argc, const char* argv[]) {
int ok = 0;
const char* in_file = NULL;
@ -197,14 +198,14 @@ int main(int argc, const char* argv[]) {
if (!WebPInitDecoderConfig(&config)) {
fprintf(stderr, "Library version mismatch!\n");
FREE_WARGV_AND_RETURN(-1);
FREE_WARGV_AND_RETURN(EXIT_FAILURE);
}
for (c = 1; c < argc; ++c) {
int parse_error = 0;
if (!strcmp(argv[c], "-h") || !strcmp(argv[c], "-help")) {
Help();
FREE_WARGV_AND_RETURN(0);
FREE_WARGV_AND_RETURN(EXIT_SUCCESS);
} else if (!strcmp(argv[c], "-o") && c < argc - 1) {
out_file = (const char*)GET_WARGV(argv, ++c);
} else if (!strcmp(argv[c], "-alpha")) {
@ -227,7 +228,7 @@ int main(int argc, const char* argv[]) {
const int version = WebPGetDecoderVersion();
printf("%d.%d.%d\n",
(version >> 16) & 0xff, (version >> 8) & 0xff, version & 0xff);
FREE_WARGV_AND_RETURN(0);
FREE_WARGV_AND_RETURN(EXIT_SUCCESS);
} else if (!strcmp(argv[c], "-pgm")) {
format = PGM;
} else if (!strcmp(argv[c], "-yuv")) {
@ -293,21 +294,21 @@ int main(int argc, const char* argv[]) {
} else if (argv[c][0] == '-') {
fprintf(stderr, "Unknown option '%s'\n", argv[c]);
Help();
FREE_WARGV_AND_RETURN(-1);
FREE_WARGV_AND_RETURN(EXIT_FAILURE);
} else {
in_file = (const char*)GET_WARGV(argv, c);
}
if (parse_error) {
Help();
FREE_WARGV_AND_RETURN(-1);
FREE_WARGV_AND_RETURN(EXIT_FAILURE);
}
}
if (in_file == NULL) {
fprintf(stderr, "missing input file!!\n");
Help();
FREE_WARGV_AND_RETURN(-1);
FREE_WARGV_AND_RETURN(EXIT_FAILURE);
}
if (quiet) verbose = 0;
@ -316,7 +317,7 @@ int main(int argc, const char* argv[]) {
VP8StatusCode status = VP8_STATUS_OK;
size_t data_size = 0;
if (!LoadWebP(in_file, &data, &data_size, bitstream)) {
FREE_WARGV_AND_RETURN(-1);
FREE_WARGV_AND_RETURN(EXIT_FAILURE);
}
switch (format) {
@ -415,7 +416,7 @@ int main(int argc, const char* argv[]) {
WebPFreeDecBuffer(output_buffer);
WebPFree((void*)external_buffer);
WebPFree((void*)data);
FREE_WARGV_AND_RETURN(ok ? 0 : -1);
FREE_WARGV_AND_RETURN(ok ? EXIT_SUCCESS : EXIT_FAILURE);
}
//------------------------------------------------------------------------------

View File

@ -28,6 +28,7 @@
#endif
#include <gif_lib.h>
#include "sharpyuv/sharpyuv.h"
#include "webp/encode.h"
#include "webp/mux.h"
#include "../examples/example_util.h"
@ -70,8 +71,14 @@ static void Help(void) {
printf(" -lossy ................. encode image using lossy compression\n");
printf(" -mixed ................. for each frame in the image, pick lossy\n"
" or lossless compression heuristically\n");
printf(" -near_lossless <int> ... use near-lossless image preprocessing\n"
" (0..100=off), default=100\n");
printf(" -sharp_yuv ............. use sharper (and slower) RGB->YUV "
"conversion\n"
" (lossy only)\n");
printf(" -q <float> ............. quality factor (0:small..100:big)\n");
printf(" -m <int> ............... compression method (0=fast, 6=slowest)\n");
printf(" -m <int> ............... compression method (0=fast, 6=slowest), "
"default=4\n");
printf(" -min_size .............. minimize output size (default:off)\n"
" lossless compression by default; can be\n"
" combined with -q, -m, -lossy or -mixed\n"
@ -96,6 +103,7 @@ static void Help(void) {
//------------------------------------------------------------------------------
// Returns EXIT_SUCCESS on success, EXIT_FAILURE on failure.
int main(int argc, const char* argv[]) {
int verbose = 0;
int gif_error = GIF_ERROR;
@ -140,7 +148,7 @@ int main(int argc, const char* argv[]) {
!WebPPictureInit(&frame) || !WebPPictureInit(&curr_canvas) ||
!WebPPictureInit(&prev_canvas)) {
fprintf(stderr, "Error! Version mismatch!\n");
FREE_WARGV_AND_RETURN(-1);
FREE_WARGV_AND_RETURN(EXIT_FAILURE);
}
config.lossless = 1; // Use lossless compression by default.
@ -150,14 +158,14 @@ int main(int argc, const char* argv[]) {
if (argc == 1) {
Help();
FREE_WARGV_AND_RETURN(0);
FREE_WARGV_AND_RETURN(EXIT_FAILURE);
}
for (c = 1; c < argc; ++c) {
int parse_error = 0;
if (!strcmp(argv[c], "-h") || !strcmp(argv[c], "-help")) {
Help();
FREE_WARGV_AND_RETURN(0);
FREE_WARGV_AND_RETURN(EXIT_SUCCESS);
} else if (!strcmp(argv[c], "-o") && c < argc - 1) {
out_file = GET_WARGV(argv, ++c);
} else if (!strcmp(argv[c], "-lossy")) {
@ -165,6 +173,10 @@ int main(int argc, const char* argv[]) {
} else if (!strcmp(argv[c], "-mixed")) {
enc_options.allow_mixed = 1;
config.lossless = 0;
} else if (!strcmp(argv[c], "-near_lossless") && c < argc - 1) {
config.near_lossless = ExUtilGetInt(argv[++c], 0, &parse_error);
} else if (!strcmp(argv[c], "-sharp_yuv")) {
config.use_sharp_yuv = 1;
} else if (!strcmp(argv[c], "-loop_compatibility")) {
loop_compatibility = 1;
} else if (!strcmp(argv[c], "-q") && c < argc - 1) {
@ -216,7 +228,7 @@ int main(int argc, const char* argv[]) {
fprintf(stderr, "Error! Unknown metadata type '%.*s'\n",
(int)(token - start), start);
Help();
FREE_WARGV_AND_RETURN(-1);
FREE_WARGV_AND_RETURN(EXIT_FAILURE);
}
start = token + 1;
}
@ -225,11 +237,14 @@ int main(int argc, const char* argv[]) {
} else if (!strcmp(argv[c], "-version")) {
const int enc_version = WebPGetEncoderVersion();
const int mux_version = WebPGetMuxVersion();
const int sharpyuv_version = SharpYuvGetVersion();
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);
FREE_WARGV_AND_RETURN(0);
printf("libsharpyuv: %d.%d.%d\n", (sharpyuv_version >> 24) & 0xff,
(sharpyuv_version >> 16) & 0xffff, sharpyuv_version & 0xff);
FREE_WARGV_AND_RETURN(EXIT_SUCCESS);
} else if (!strcmp(argv[c], "-quiet")) {
quiet = 1;
enc_options.verbose = 0;
@ -242,14 +257,14 @@ int main(int argc, const char* argv[]) {
} else if (argv[c][0] == '-') {
fprintf(stderr, "Error! Unknown option '%s'\n", argv[c]);
Help();
FREE_WARGV_AND_RETURN(-1);
FREE_WARGV_AND_RETURN(EXIT_FAILURE);
} else {
in_file = GET_WARGV(argv, c);
}
if (parse_error) {
Help();
FREE_WARGV_AND_RETURN(-1);
FREE_WARGV_AND_RETURN(EXIT_FAILURE);
}
}
@ -593,7 +608,7 @@ int main(int argc, const char* argv[]) {
#endif
}
FREE_WARGV_AND_RETURN(!ok);
FREE_WARGV_AND_RETURN(ok ? EXIT_SUCCESS : EXIT_FAILURE);
}
#else // !WEBP_HAVE_GIF
@ -601,7 +616,7 @@ int main(int argc, const char* argv[]) {
int main(int argc, const char* argv[]) {
fprintf(stderr, "GIF support not enabled in %s.\n", argv[0]);
(void)argc;
return 0;
return EXIT_FAILURE;
}
#endif

View File

@ -317,7 +317,7 @@ void GIFDisplayError(const GifFileType* const gif, int gif_error) {
#else // !WEBP_HAVE_GIF
static void ErrorGIFNotAvailable() {
static void ErrorGIFNotAvailable(void) {
fprintf(stderr, "GIF support not compiled. Please install the libgif-dev "
"package before building.\n");
}

View File

@ -28,6 +28,7 @@
#include "../imageio/imageio_util.h"
#include "./stopwatch.h"
#include "./unicode.h"
#include "sharpyuv/sharpyuv.h"
#include "webp/encode.h"
#include "webp/mux.h"
@ -35,17 +36,22 @@
static void Help(void) {
printf("Usage:\n\n");
printf(" img2webp [file_options] [[frame_options] frame_file]...\n");
printf("\n");
printf(" img2webp [file_options] [[frame_options] frame_file]...");
printf(" [-o webp_file]\n\n");
printf("File-level options (only used at the start of compression):\n");
printf(" -min_size ............ minimize size\n");
printf(" -loop <int> .......... loop count (default: 0, = infinite loop)\n");
printf(" -kmax <int> .......... maximum number of frame between key-frames\n"
" (0=only keyframes)\n");
printf(" -kmin <int> .......... minimum number of frame between key-frames\n"
" (0=disable key-frames altogether)\n");
printf(" -mixed ............... use mixed lossy/lossless automatic mode\n");
printf(" -near_lossless <int> . use near-lossless image preprocessing\n"
" (0..100=off), default=100\n");
printf(" -sharp_yuv ........... use sharper (and slower) RGB->YUV "
"conversion\n "
"(lossy only)\n");
printf(" -loop <int> .......... loop count (default: 0, = infinite loop)\n");
printf(" -v ................... verbose mode\n");
printf(" -h ................... this help\n");
printf(" -version ............. print version number and exit\n");
@ -53,10 +59,15 @@ static void Help(void) {
printf("Per-frame options (only used for subsequent images input):\n");
printf(" -d <int> ............. frame duration in ms (default: 100)\n");
printf(" -lossless ........... use lossless mode (default)\n");
printf(" -lossy ... ........... use lossy mode\n");
printf(" -lossless ............ use lossless mode (default)\n");
printf(" -lossy ............... use lossy mode\n");
printf(" -q <float> ........... quality\n");
printf(" -m <int> ............. method to use\n");
printf(" -m <int> ............. compression method (0=fast, 6=slowest), "
"default=4\n");
printf(" -exact, -noexact ..... preserve or alter RGB values in transparent "
"area\n"
" (default: -noexact, may cause artifacts\n"
" with lossy animations)\n");
printf("\n");
printf("example: img2webp -loop 2 in0.png -lossy in1.jpg\n"
@ -124,6 +135,7 @@ static int SetLoopCount(int loop_count, WebPData* const webp_data) {
//------------------------------------------------------------------------------
// Returns EXIT_SUCCESS on success, EXIT_FAILURE on failure.
int main(int argc, const char* argv[]) {
const char* output = NULL;
WebPAnimEncoder* enc = NULL;
@ -139,13 +151,14 @@ int main(int argc, const char* argv[]) {
WebPData webp_data;
int c;
int have_input = 0;
int last_input_index = 0;
CommandLineArguments cmd_args;
int ok;
INIT_WARGV(argc, argv);
ok = ExUtilInitCommandLineArguments(argc - 1, argv + 1, &cmd_args);
if (!ok) FREE_WARGV_AND_RETURN(1);
if (!ok) FREE_WARGV_AND_RETURN(EXIT_FAILURE);
argc = cmd_args.argc_;
argv = cmd_args.argv_;
@ -184,18 +197,26 @@ int main(int argc, const char* argv[]) {
} else if (!strcmp(argv[c], "-mixed")) {
anim_config.allow_mixed = 1;
config.lossless = 0;
} else if (!strcmp(argv[c], "-near_lossless") && c + 1 < argc) {
argv[c] = NULL;
config.near_lossless = ExUtilGetInt(argv[++c], 0, &parse_error);
} else if (!strcmp(argv[c], "-sharp_yuv")) {
config.use_sharp_yuv = 1;
} else if (!strcmp(argv[c], "-v")) {
verbose = 1;
} else if (!strcmp(argv[c], "-h") || !strcmp(argv[c], "-help")) {
Help();
FREE_WARGV_AND_RETURN(0);
FREE_WARGV_AND_RETURN(EXIT_SUCCESS);
} else if (!strcmp(argv[c], "-version")) {
const int enc_version = WebPGetEncoderVersion();
const int mux_version = WebPGetMuxVersion();
const int sharpyuv_version = SharpYuvGetVersion();
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);
printf("libsharpyuv: %d.%d.%d\n", (sharpyuv_version >> 24) & 0xff,
(sharpyuv_version >> 16) & 0xffff, sharpyuv_version & 0xff);
goto End;
} else {
continue;
@ -209,6 +230,8 @@ int main(int argc, const char* argv[]) {
}
if (!have_input) {
fprintf(stderr, "No input file(s) for generating animation!\n");
ok = 0;
Help();
goto End;
}
@ -233,6 +256,10 @@ int main(int argc, const char* argv[]) {
fprintf(stderr, "Invalid negative duration (%d)\n", duration);
parse_error = 1;
}
} else if (!strcmp(argv[c], "-exact")) {
config.exact = 1;
} else if (!strcmp(argv[c], "-noexact")) {
config.exact = 0;
} else {
parse_error = 1; // shouldn't be here.
fprintf(stderr, "Unknown option [%s]\n", argv[c]);
@ -253,6 +280,7 @@ int main(int argc, const char* argv[]) {
// read next input image
pic.use_argb = 1;
ok = ReadImage((const char*)GET_WARGV_SHIFTED(argv, c), &pic);
last_input_index = c;
if (!ok) goto End;
if (enc == NULL) {
@ -291,6 +319,13 @@ int main(int argc, const char* argv[]) {
++pic_num;
}
for (c = last_input_index + 1; c < argc; ++c) {
if (argv[c] != NULL) {
fprintf(stderr, "Warning: unused option [%s]!"
" Frame options go before the input frame.\n", argv[c]);
}
}
// add a last fake frame to signal the last duration
ok = ok && WebPAnimEncoderAdd(enc, NULL, timestamp_ms, NULL);
ok = ok && WebPAnimEncoderAssemble(enc, &webp_data);
@ -321,5 +356,5 @@ int main(int argc, const char* argv[]) {
}
WebPDataClear(&webp_data);
ExUtilDeleteCommandLineArguments(&cmd_args);
FREE_WARGV_AND_RETURN(ok ? 0 : 1);
FREE_WARGV_AND_RETURN(ok ? EXIT_SUCCESS : EXIT_FAILURE);
}

View File

@ -18,6 +18,7 @@
#define _POSIX_C_SOURCE 200112L // for setenv
#endif
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@ -430,10 +431,13 @@ static void HandleDisplay(void) {
#endif
}
static void StartDisplay(void) {
static void StartDisplay(const char* filename) {
int width = kParams.canvas_width;
int height = kParams.canvas_height;
int screen_width, screen_height;
const char viewername[] = " - WebP viewer";
// max linux file len + viewername string
char title[4096 + sizeof(viewername)] = "";
// TODO(webp:365) GLUT_DOUBLE results in flickering / old frames to be
// partially displayed with animated webp + alpha.
#if defined(__APPLE__) || defined(_WIN32)
@ -453,8 +457,9 @@ static void StartDisplay(void) {
height = screen_height;
}
}
snprintf(title, sizeof(title), "%s%s", filename, viewername);
glutInitWindowSize(width, height);
glutCreateWindow("WebP viewer");
glutCreateWindow(title);
glutDisplayFunc(HandleDisplay);
glutReshapeFunc(HandleReshape);
glutIdleFunc(NULL);
@ -493,7 +498,7 @@ static void Help(void) {
}
int main(int argc, char* argv[]) {
int c;
int c, file_name_argv_index = 1;
WebPDecoderConfig* const config = &kParams.config;
WebPIterator* const curr = &kParams.curr_frame;
@ -501,7 +506,7 @@ int main(int argc, char* argv[]) {
if (!WebPInitDecoderConfig(config)) {
fprintf(stderr, "Library version mismatch!\n");
FREE_WARGV_AND_RETURN(-1);
FREE_WARGV_AND_RETURN(EXIT_FAILURE);
}
config->options.dithering_strength = 50;
config->options.alpha_dithering_strength = 100;
@ -513,7 +518,7 @@ int main(int argc, char* argv[]) {
int parse_error = 0;
if (!strcmp(argv[c], "-h") || !strcmp(argv[c], "-help")) {
Help();
FREE_WARGV_AND_RETURN(0);
FREE_WARGV_AND_RETURN(EXIT_SUCCESS);
} else if (!strcmp(argv[c], "-noicc")) {
kParams.use_color_profile = 0;
} else if (!strcmp(argv[c], "-nofancy")) {
@ -536,30 +541,34 @@ int main(int argc, char* argv[]) {
(dec_version >> 16) & 0xff, (dec_version >> 8) & 0xff,
dec_version & 0xff, (dmux_version >> 16) & 0xff,
(dmux_version >> 8) & 0xff, dmux_version & 0xff);
FREE_WARGV_AND_RETURN(0);
FREE_WARGV_AND_RETURN(EXIT_SUCCESS);
} else if (!strcmp(argv[c], "-mt")) {
config->options.use_threads = 1;
} else if (!strcmp(argv[c], "--")) {
if (c < argc - 1) kParams.file_name = (const char*)GET_WARGV(argv, ++c);
if (c < argc - 1) {
kParams.file_name = (const char*)GET_WARGV(argv, ++c);
file_name_argv_index = c;
}
break;
} else if (argv[c][0] == '-') {
printf("Unknown option '%s'\n", argv[c]);
Help();
FREE_WARGV_AND_RETURN(-1);
FREE_WARGV_AND_RETURN(EXIT_FAILURE);
} else {
kParams.file_name = (const char*)GET_WARGV(argv, c);
file_name_argv_index = c;
}
if (parse_error) {
Help();
FREE_WARGV_AND_RETURN(-1);
FREE_WARGV_AND_RETURN(EXIT_FAILURE);
}
}
if (kParams.file_name == NULL) {
printf("missing input file!!\n");
Help();
FREE_WARGV_AND_RETURN(0);
FREE_WARGV_AND_RETURN(EXIT_FAILURE);
}
if (!ImgIoUtilReadFile(kParams.file_name,
@ -613,7 +622,7 @@ int main(int argc, char* argv[]) {
// Position iterator to last frame. Next call to HandleDisplay will wrap over.
// We take this into account by bumping up loop_count.
WebPDemuxGetFrame(kParams.dmux, 0, curr);
if (!WebPDemuxGetFrame(kParams.dmux, 0, curr)) goto Error;
if (kParams.loop_count) ++kParams.loop_count;
#if defined(__unix__) || defined(__CYGWIN__)
@ -627,18 +636,18 @@ int main(int argc, char* argv[]) {
#ifdef FREEGLUT
glutSetOption(GLUT_ACTION_ON_WINDOW_CLOSE, GLUT_ACTION_CONTINUE_EXECUTION);
#endif
StartDisplay();
StartDisplay(argv[file_name_argv_index]);
if (kParams.has_animation) glutTimerFunc(0, decode_callback, 0);
glutMainLoop();
// Should only be reached when using FREEGLUT:
ClearParams();
FREE_WARGV_AND_RETURN(0);
FREE_WARGV_AND_RETURN(EXIT_SUCCESS);
Error:
ClearParams();
FREE_WARGV_AND_RETURN(-1);
FREE_WARGV_AND_RETURN(EXIT_FAILURE);
}
#else // !WEBP_HAVE_GL
@ -646,7 +655,7 @@ int main(int argc, char* argv[]) {
int main(int argc, const char* argv[]) {
fprintf(stderr, "OpenGL support not enabled in %s.\n", argv[0]);
(void)argc;
return 0;
return EXIT_FAILURE;
}
#endif

View File

@ -14,6 +14,7 @@
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#ifdef HAVE_CONFIG_H
#include "webp/config.h"
@ -357,12 +358,12 @@ static WebPInfoStatus ParseLossyHeader(const ChunkData* const chunk_data,
}
data += 3;
data_size -= 3;
printf(" Key frame: %s\n"
" Profile: %d\n"
" Display: %s\n"
" Part. 0 length: %d\n",
key_frame ? "Yes" : "No", profile,
display ? "Yes" : "No", partition0_length);
printf(
" Key frame: %s\n"
" Profile: %d\n"
" Display: Yes\n"
" Part. 0 length: %d\n",
key_frame ? "Yes" : "No", profile, partition0_length);
if (key_frame) {
if (!(data[0] == 0x9d && data[1] == 0x01 && data[2] == 0x2a)) {
LOG_ERROR("Invalid lossy bitstream signature.");
@ -1120,6 +1121,7 @@ static void Help(void) {
" -bitstream_info .... Parse bitstream header.\n");
}
// Returns EXIT_SUCCESS on success, EXIT_FAILURE on failure.
int main(int argc, const char* argv[]) {
int c, quiet = 0, show_diag = 0, show_summary = 0;
int parse_bitstream = 0;
@ -1130,7 +1132,7 @@ int main(int argc, const char* argv[]) {
if (argc == 1) {
Help();
FREE_WARGV_AND_RETURN(WEBP_INFO_OK);
FREE_WARGV_AND_RETURN(EXIT_FAILURE);
}
// Parse command-line input.
@ -1138,7 +1140,7 @@ int main(int argc, const char* argv[]) {
if (!strcmp(argv[c], "-h") || !strcmp(argv[c], "-help") ||
!strcmp(argv[c], "-H") || !strcmp(argv[c], "-longhelp")) {
Help();
FREE_WARGV_AND_RETURN(WEBP_INFO_OK);
FREE_WARGV_AND_RETURN(EXIT_SUCCESS);
} else if (!strcmp(argv[c], "-quiet")) {
quiet = 1;
} else if (!strcmp(argv[c], "-diag")) {
@ -1151,7 +1153,7 @@ int main(int argc, const char* argv[]) {
const int version = WebPGetDecoderVersion();
printf("WebP Decoder version: %d.%d.%d\n",
(version >> 16) & 0xff, (version >> 8) & 0xff, version & 0xff);
FREE_WARGV_AND_RETURN(0);
FREE_WARGV_AND_RETURN(EXIT_SUCCESS);
} else { // Assume the remaining are all input files.
break;
}
@ -1159,7 +1161,7 @@ int main(int argc, const char* argv[]) {
if (c == argc) {
Help();
FREE_WARGV_AND_RETURN(WEBP_INFO_INVALID_COMMAND);
FREE_WARGV_AND_RETURN(EXIT_FAILURE);
}
// Process input files one by one.
@ -1182,5 +1184,6 @@ int main(int argc, const char* argv[]) {
webp_info_status = AnalyzeWebP(&webp_info, &webp_data);
WebPDataClear(&webp_data);
}
FREE_WARGV_AND_RETURN(webp_info_status);
FREE_WARGV_AND_RETURN((webp_info_status == WEBP_INFO_OK) ? EXIT_SUCCESS
: EXIT_FAILURE);
}

View File

@ -59,6 +59,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "webp/decode.h"
#include "webp/mux.h"
#include "../examples/example_util.h"
@ -150,16 +151,20 @@ static const char* ErrorString(WebPMuxError err) {
}
#define RETURN_IF_ERROR(ERR_MSG) \
if (err != WEBP_MUX_OK) { \
fprintf(stderr, ERR_MSG); \
return err; \
}
do { \
if (err != WEBP_MUX_OK) { \
fprintf(stderr, ERR_MSG); \
return err; \
} \
} while (0)
#define RETURN_IF_ERROR3(ERR_MSG, FORMAT_STR1, FORMAT_STR2) \
if (err != WEBP_MUX_OK) { \
fprintf(stderr, ERR_MSG, FORMAT_STR1, FORMAT_STR2); \
return err; \
}
do { \
if (err != WEBP_MUX_OK) { \
fprintf(stderr, ERR_MSG, FORMAT_STR1, FORMAT_STR2); \
return err; \
} \
} while (0)
#define ERROR_GOTO1(ERR_MSG, LABEL) \
do { \
@ -605,20 +610,26 @@ static int ValidateCommandLine(const CommandLineArguments* const cmd_args,
#define FEATURETYPE_IS_NIL (config->type_ == NIL_FEATURE)
#define CHECK_NUM_ARGS_AT_LEAST(NUM, LABEL) \
if (argc < i + (NUM)) { \
fprintf(stderr, "ERROR: Too few arguments for '%s'.\n", argv[i]); \
goto LABEL; \
}
do { \
if (argc < i + (NUM)) { \
fprintf(stderr, "ERROR: Too few arguments for '%s'.\n", argv[i]); \
goto LABEL; \
} \
} while (0)
#define CHECK_NUM_ARGS_AT_MOST(NUM, LABEL) \
if (argc > i + (NUM)) { \
fprintf(stderr, "ERROR: Too many arguments for '%s'.\n", argv[i]); \
goto LABEL; \
}
do { \
if (argc > i + (NUM)) { \
fprintf(stderr, "ERROR: Too many arguments for '%s'.\n", argv[i]); \
goto LABEL; \
} \
} while (0)
#define CHECK_NUM_ARGS_EXACTLY(NUM, LABEL) \
CHECK_NUM_ARGS_AT_LEAST(NUM, LABEL); \
CHECK_NUM_ARGS_AT_MOST(NUM, LABEL);
do { \
CHECK_NUM_ARGS_AT_LEAST(NUM, LABEL); \
CHECK_NUM_ARGS_AT_MOST(NUM, LABEL); \
} while (0)
// Parses command-line arguments to fill up config object. Also performs some
// semantic checks. unicode_argv contains wchar_t arguments or is null.
@ -1215,6 +1226,7 @@ static int Process(const Config* config) {
//------------------------------------------------------------------------------
// Main.
// Returns EXIT_SUCCESS on success, EXIT_FAILURE on failure.
int main(int argc, const char* argv[]) {
Config config;
int ok;
@ -1228,7 +1240,7 @@ int main(int argc, const char* argv[]) {
PrintHelp();
}
DeleteConfig(&config);
FREE_WARGV_AND_RETURN(!ok);
FREE_WARGV_AND_RETURN(ok ? EXIT_SUCCESS : EXIT_FAILURE);
}
//------------------------------------------------------------------------------

View File

@ -7,6 +7,7 @@ noinst_HEADERS += ../src/webp/types.h
libwebpextras_la_SOURCES =
libwebpextras_la_SOURCES += extras.c extras.h quality_estimate.c
libwebpextras_la_SOURCES += sharpyuv_risk_table.c sharpyuv_risk_table.h
libwebpextras_la_CPPFLAGS = $(AM_CPPFLAGS)
libwebpextras_la_LDFLAGS = -lm

View File

@ -11,14 +11,20 @@
//
#include "extras/extras.h"
#include "webp/format_constants.h"
#include "src/dsp/dsp.h"
#include <assert.h>
#include <limits.h>
#include <string.h>
#include "extras/sharpyuv_risk_table.h"
#include "sharpyuv/sharpyuv.h"
#include "src/dsp/dsp.h"
#include "src/utils/utils.h"
#include "webp/format_constants.h"
#include "webp/types.h"
#define XTRA_MAJ_VERSION 1
#define XTRA_MIN_VERSION 3
#define XTRA_MIN_VERSION 5
#define XTRA_REV_VERSION 0
//------------------------------------------------------------------------------
@ -160,3 +166,159 @@ int WebPUnmultiplyARGB(WebPPicture* pic) {
}
//------------------------------------------------------------------------------
// 420 risk metric
#define YUV_FIX 16 // fixed-point precision for RGB->YUV
static const int kYuvHalf = 1 << (YUV_FIX - 1);
// Maps a value in [0, (256 << YUV_FIX) - 1] to [0,
// precomputed_scores_table_sampling - 1]. It is important that the extremal
// values are preserved and 1:1 mapped:
// ConvertValue(0) = 0
// ConvertValue((256 << 16) - 1) = rgb_sampling_size - 1
static int SharpYuvConvertValueToSampledIdx(int v, int rgb_sampling_size) {
v = (v + kYuvHalf) >> YUV_FIX;
v = (v < 0) ? 0 : (v > 255) ? 255 : v;
return (v * (rgb_sampling_size - 1)) / 255;
}
#undef YUV_FIX
// For each pixel, computes the index to look up that color in a precomputed
// risk score table where the YUV space is subsampled to a size of
// precomputed_scores_table_sampling^3 (see sharpyuv_risk_table.h)
static int SharpYuvConvertToYuvSharpnessIndex(
int r, int g, int b, const SharpYuvConversionMatrix* matrix,
int precomputed_scores_table_sampling) {
const int y = SharpYuvConvertValueToSampledIdx(
matrix->rgb_to_y[0] * r + matrix->rgb_to_y[1] * g +
matrix->rgb_to_y[2] * b + matrix->rgb_to_y[3],
precomputed_scores_table_sampling);
const int u = SharpYuvConvertValueToSampledIdx(
matrix->rgb_to_u[0] * r + matrix->rgb_to_u[1] * g +
matrix->rgb_to_u[2] * b + matrix->rgb_to_u[3],
precomputed_scores_table_sampling);
const int v = SharpYuvConvertValueToSampledIdx(
matrix->rgb_to_v[0] * r + matrix->rgb_to_v[1] * g +
matrix->rgb_to_v[2] * b + matrix->rgb_to_v[3],
precomputed_scores_table_sampling);
return y + u * precomputed_scores_table_sampling +
v * precomputed_scores_table_sampling *
precomputed_scores_table_sampling;
}
static void SharpYuvRowToYuvSharpnessIndex(
const uint8_t* r_ptr, const uint8_t* g_ptr, const uint8_t* b_ptr,
int rgb_step, int rgb_bit_depth, int width, uint16_t* dst,
const SharpYuvConversionMatrix* matrix,
int precomputed_scores_table_sampling) {
int i;
assert(rgb_bit_depth == 8);
(void)rgb_bit_depth; // Unused for now.
for (i = 0; i < width;
++i, r_ptr += rgb_step, g_ptr += rgb_step, b_ptr += rgb_step) {
dst[i] =
SharpYuvConvertToYuvSharpnessIndex(r_ptr[0], g_ptr[0], b_ptr[0], matrix,
precomputed_scores_table_sampling);
}
}
#define SAFE_ALLOC(W, H, T) ((T*)WebPSafeMalloc((uint64_t)(W) * (H), sizeof(T)))
static int DoEstimateRisk(const uint8_t* r_ptr, const uint8_t* g_ptr,
const uint8_t* b_ptr, int rgb_step, int rgb_stride,
int rgb_bit_depth, int width, int height,
const SharpYuvOptions* options,
const uint8_t precomputed_scores_table[],
int precomputed_scores_table_sampling,
float* score_out) {
const int sampling3 = precomputed_scores_table_sampling *
precomputed_scores_table_sampling *
precomputed_scores_table_sampling;
const int kNoiseLevel = 4;
double total_score = 0;
double count = 0;
// Rows of indices in
uint16_t* row1 = SAFE_ALLOC(width, 1, uint16_t);
uint16_t* row2 = SAFE_ALLOC(width, 1, uint16_t);
uint16_t* tmp;
int i, j;
if (row1 == NULL || row2 == NULL) {
WebPFree(row1);
WebPFree(row2);
return 0;
}
// Convert the first row ahead.
SharpYuvRowToYuvSharpnessIndex(r_ptr, g_ptr, b_ptr, rgb_step, rgb_bit_depth,
width, row2, options->yuv_matrix,
precomputed_scores_table_sampling);
for (j = 1; j < height; ++j) {
r_ptr += rgb_stride;
g_ptr += rgb_stride;
b_ptr += rgb_stride;
// Swap row 1 and row 2.
tmp = row1;
row1 = row2;
row2 = tmp;
// Convert the row below.
SharpYuvRowToYuvSharpnessIndex(r_ptr, g_ptr, b_ptr, rgb_step, rgb_bit_depth,
width, row2, options->yuv_matrix,
precomputed_scores_table_sampling);
for (i = 0; i < width - 1; ++i) {
const int idx0 = row1[i + 0];
const int idx1 = row1[i + 1];
const int idx2 = row2[i + 0];
const int score = precomputed_scores_table[idx0 + sampling3 * idx1] +
precomputed_scores_table[idx0 + sampling3 * idx2] +
precomputed_scores_table[idx1 + sampling3 * idx2];
if (score > kNoiseLevel) {
total_score += score;
count += 1.0;
}
}
}
if (count > 0.) total_score /= count;
// If less than 1% of pixels were evaluated -> below noise level.
if (100. * count / (width * height) < 1.) total_score = 0.;
// Rescale to [0:100]
total_score = (total_score > 25.) ? 100. : total_score * 100. / 25.;
WebPFree(row1);
WebPFree(row2);
*score_out = (float)total_score;
return 1;
}
#undef SAFE_ALLOC
int SharpYuvEstimate420Risk(const void* r_ptr, const void* g_ptr,
const void* b_ptr, int rgb_step, int rgb_stride,
int rgb_bit_depth, int width, int height,
const SharpYuvOptions* options, float* score) {
if (width < 1 || height < 1 || width == INT_MAX || height == INT_MAX ||
r_ptr == NULL || g_ptr == NULL || b_ptr == NULL || options == NULL ||
score == NULL) {
return 0;
}
if (rgb_bit_depth != 8) {
return 0;
}
if (width <= 4 || height <= 4) {
*score = 0.0f; // too small, no real risk.
return 1;
}
return DoEstimateRisk(
(const uint8_t*)r_ptr, (const uint8_t*)g_ptr, (const uint8_t*)b_ptr,
rgb_step, rgb_stride, rgb_bit_depth, width, height, options,
kSharpYuvPrecomputedRisk, kSharpYuvPrecomputedRiskYuvSampling, score);
}
//------------------------------------------------------------------------------

View File

@ -17,9 +17,10 @@
extern "C" {
#endif
#include "sharpyuv/sharpyuv.h"
#include "webp/encode.h"
#define WEBP_EXTRAS_ABI_VERSION 0x0002 // MAJOR(8b) + MINOR(8b)
#define WEBP_EXTRAS_ABI_VERSION 0x0003 // MAJOR(8b) + MINOR(8b)
//------------------------------------------------------------------------------
@ -70,6 +71,38 @@ WEBP_EXTERN int VP8EstimateQuality(const uint8_t* const data, size_t size);
//------------------------------------------------------------------------------
// Computes a score between 0 and 100 which represents the risk of having visual
// quality loss from converting an RGB image to YUV420.
// A low score, typically < 40, means there is a low risk of artifacts from
// chroma subsampling and a simple averaging algorithm can be used instead of
// the more expensive SharpYuvConvert function.
// A medium score, typically >= 40 and < 70, means that simple chroma
// subsampling will produce artifacts and it may be advisable to use the more
// costly SharpYuvConvert for YUV420 conversion.
// A high score, typically >= 70, means there is a very high risk of artifacts
// from chroma subsampling even with SharpYuvConvert, and best results might be
// achieved by using YUV444.
// If not using SharpYuvConvert, a threshold of about 50 can be used to decide
// between (simple averaging) 420 and 444.
// r_ptr, g_ptr, b_ptr: pointers to the source r, g and b channels. Should point
// to uint8_t buffers if rgb_bit_depth is 8, or uint16_t buffers otherwise.
// rgb_step: distance in bytes between two horizontally adjacent pixels on the
// r, g and b channels. If rgb_bit_depth is > 8, it should be a
// multiple of 2.
// rgb_stride: distance in bytes between two vertically adjacent pixels on the
// r, g, and b channels. If rgb_bit_depth is > 8, it should be a
// multiple of 2.
// rgb_bit_depth: number of bits for each r/g/b value. Only a value of 8 is
// currently supported.
// width, height: width and height of the image in pixels
// Returns 0 on failure.
WEBP_EXTERN int SharpYuvEstimate420Risk(
const void* r_ptr, const void* g_ptr, const void* b_ptr, int rgb_step,
int rgb_stride, int rgb_bit_depth, int width, int height,
const SharpYuvOptions* options, float* score);
//------------------------------------------------------------------------------
#ifdef __cplusplus
} // extern "C"
#endif

View File

@ -227,10 +227,11 @@ static void Help(void) {
WebPGetEnabledInputFileFormats());
}
// Returns EXIT_SUCCESS on success, EXIT_FAILURE on failure.
int main(int argc, const char* argv[]) {
WebPPicture pic1, pic2;
size_t size1 = 0, size2 = 0;
int ret = 1;
int ret = EXIT_FAILURE;
float disto[5];
int type = 0;
int c;
@ -246,7 +247,7 @@ int main(int argc, const char* argv[]) {
if (!WebPPictureInit(&pic1) || !WebPPictureInit(&pic2)) {
fprintf(stderr, "Can't init pictures\n");
FREE_WARGV_AND_RETURN(1);
FREE_WARGV_AND_RETURN(EXIT_FAILURE);
}
for (c = 1; c < argc; ++c) {
@ -262,7 +263,7 @@ int main(int argc, const char* argv[]) {
use_gray = 1;
} else if (!strcmp(argv[c], "-h")) {
help = 1;
ret = 0;
ret = EXIT_SUCCESS;
} else if (!strcmp(argv[c], "-o")) {
if (++c == argc) {
fprintf(stderr, "missing file name after %s option.\n", argv[c - 1]);
@ -337,7 +338,8 @@ int main(int argc, const char* argv[]) {
fprintf(stderr, "Error during lossless encoding.\n");
goto End;
}
ret = ImgIoUtilWriteFile(output, data, data_size) ? 0 : 1;
ret = ImgIoUtilWriteFile(output, data, data_size) ? EXIT_SUCCESS
: EXIT_FAILURE;
WebPFree(data);
if (ret) goto End;
#else
@ -345,9 +347,10 @@ int main(int argc, const char* argv[]) {
(void)data_size;
fprintf(stderr, "Cannot save the difference map. Please recompile "
"without the WEBP_REDUCE_CSP flag.\n");
goto End;
#endif // WEBP_REDUCE_CSP
}
ret = 0;
ret = EXIT_SUCCESS;
End:
WebPPictureFree(&pic1);

6210
extras/sharpyuv_risk_table.c Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,27 @@
// Copyright 2023 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.
// -----------------------------------------------------------------------------
//
// Precomputed data for 420 risk estimation.
#ifndef WEBP_EXTRAS_SHARPYUV_RISK_TABLE_H_
#define WEBP_EXTRAS_SHARPYUV_RISK_TABLE_H_
#include "src/webp/types.h"
extern const int kSharpYuvPrecomputedRiskYuvSampling;
// Table of precomputed risk scores when chroma subsampling images with two
// given colors.
// Since precomputing values for all possible YUV colors would create a huge
// table, the YUV space (i.e. [0, 255]^3) is reduced to
// [0, kSharpYuvPrecomputedRiskYuvSampling-1]^3
// where 255 maps to kSharpYuvPrecomputedRiskYuvSampling-1.
// Table size: kSharpYuvPrecomputedRiskYuvSampling^6 bytes or 114 KiB
extern const uint8_t kSharpYuvPrecomputedRisk[];
#endif // WEBP_EXTRAS_SHARPYUV_RISK_TABLE_H_

View File

@ -15,6 +15,7 @@
// Author: James Zern (jzern@google.com)
#include <stdio.h>
#include <stdlib.h>
#ifdef HAVE_CONFIG_H
#include "webp/config.h"
@ -30,7 +31,7 @@
#if defined(WEBP_HAVE_JUST_SDL_H)
#include <SDL.h>
#else
#include <SDL/SDL.h>
#include <SDL2/SDL.h>
#endif
static void ProcessEvents(void) {
@ -49,19 +50,26 @@ static void ProcessEvents(void) {
}
}
// Returns EXIT_SUCCESS on success, EXIT_FAILURE on failure.
int main(int argc, char* argv[]) {
int c;
int ok = 0;
INIT_WARGV(argc, argv);
if (argc == 1) {
fprintf(stderr, "Usage: %s [-h] image.webp [more_files.webp...]\n",
argv[0]);
goto Error;
}
for (c = 1; c < argc; ++c) {
const char* file = NULL;
const uint8_t* webp = NULL;
size_t webp_size = 0;
if (!strcmp(argv[c], "-h")) {
printf("Usage: %s [-h] image.webp [more_files.webp...]\n", argv[0]);
FREE_WARGV_AND_RETURN(0);
FREE_WARGV_AND_RETURN(EXIT_SUCCESS);
} else {
file = (const char*)GET_WARGV(argv, c);
}
@ -87,7 +95,7 @@ int main(int argc, char* argv[]) {
Error:
SDL_Quit();
FREE_WARGV_AND_RETURN(ok ? 0 : 1);
FREE_WARGV_AND_RETURN(ok ? EXIT_SUCCESS : EXIT_FAILURE);
}
#else // !WEBP_HAVE_SDL

View File

@ -15,6 +15,7 @@
#include "imageio/imageio_util.h"
#include "../examples/unicode.h"
// Returns EXIT_SUCCESS on success, EXIT_FAILURE on failure.
int main(int argc, const char* argv[]) {
int c;
int quiet = 0;
@ -27,7 +28,7 @@ int main(int argc, const char* argv[]) {
quiet = 1;
} else if (!strcmp(argv[c], "-help") || !strcmp(argv[c], "-h")) {
printf("webp_quality [-h][-quiet] webp_files...\n");
FREE_WARGV_AND_RETURN(0);
FREE_WARGV_AND_RETURN(EXIT_SUCCESS);
} else {
const char* const filename = (const char*)GET_WARGV(argv, c);
const uint8_t* data = NULL;
@ -50,5 +51,5 @@ int main(int argc, const char* argv[]) {
free((void*)data);
}
}
FREE_WARGV_AND_RETURN(ok ? 0 : 1);
FREE_WARGV_AND_RETURN(ok ? EXIT_SUCCESS : EXIT_FAILURE);
}

View File

@ -20,88 +20,75 @@
#include "webp_to_sdl.h"
#include <stdio.h>
#include "src/webp/decode.h"
#if defined(WEBP_HAVE_JUST_SDL_H)
#include <SDL.h>
#else
#include <SDL/SDL.h>
#include <SDL2/SDL.h>
#endif
static int init_ok = 0;
int WebPToSDL(const char* data, unsigned int data_size) {
int ok = 0;
VP8StatusCode status;
WebPDecoderConfig config;
WebPBitstreamFeatures* const input = &config.input;
WebPDecBuffer* const output = &config.output;
SDL_Surface* screen = NULL;
SDL_Surface* surface = NULL;
if (!WebPInitDecoderConfig(&config)) {
fprintf(stderr, "Library version mismatch!\n");
return 0;
}
WebPBitstreamFeatures input;
uint8_t* output = NULL;
SDL_Window* window = NULL;
SDL_Renderer* renderer = NULL;
SDL_Texture* texture = NULL;
int width, height;
if (!init_ok) {
SDL_Init(SDL_INIT_VIDEO);
init_ok = 1;
}
status = WebPGetFeatures((uint8_t*)data, (size_t)data_size, &config.input);
status = WebPGetFeatures((uint8_t*)data, (size_t)data_size, &input);
if (status != VP8_STATUS_OK) goto Error;
width = input.width;
height = input.height;
screen = SDL_SetVideoMode(input->width, input->height, 32, SDL_SWSURFACE);
if (screen == NULL) {
fprintf(stderr, "Unable to set video mode (32bpp %dx%d)!\n",
input->width, input->height);
SDL_CreateWindowAndRenderer(width, height, 0, &window, &renderer);
if (window == NULL || renderer == NULL) {
fprintf(stderr, "Unable to create window or renderer!\n");
goto Error;
}
SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY,
"linear"); // make the scaled rendering look smoother.
SDL_RenderSetLogicalSize(renderer, width, height);
surface = SDL_CreateRGBSurface(SDL_SWSURFACE,
input->width, input->height, 32,
0x000000ffu, // R mask
0x0000ff00u, // G mask
0x00ff0000u, // B mask
0xff000000u); // A mask
if (surface == NULL) {
fprintf(stderr, "Unable to create %dx%d RGBA surface!\n",
input->width, input->height);
texture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_ABGR8888,
SDL_TEXTUREACCESS_STREAMING, width, height);
if (texture == NULL) {
fprintf(stderr, "Unable to create %dx%d RGBA texture!\n", width, height);
goto Error;
}
if (SDL_MUSTLOCK(surface)) SDL_LockSurface(surface);
#if SDL_BYTEORDER == SDL_BIG_ENDIAN
output->colorspace = MODE_BGRA;
output = WebPDecodeBGRA((const uint8_t*)data, (size_t)data_size, &width,
&height);
#else
output->colorspace = MODE_RGBA;
output = WebPDecodeRGBA((const uint8_t*)data, (size_t)data_size, &width,
&height);
#endif
output->width = surface->w;
output->height = surface->h;
output->u.RGBA.rgba = surface->pixels;
output->u.RGBA.stride = surface->pitch;
output->u.RGBA.size = surface->pitch * surface->h;
output->is_external_memory = 1;
status = WebPDecode((const uint8_t*)data, (size_t)data_size, &config);
if (status != VP8_STATUS_OK) {
if (output == NULL) {
fprintf(stderr, "Error decoding image (%d)\n", status);
goto Error;
}
if (SDL_MUSTLOCK(surface)) SDL_UnlockSurface(surface);
if (SDL_BlitSurface(surface, NULL, screen, NULL) ||
SDL_Flip(screen)) {
goto Error;
}
SDL_UpdateTexture(texture, NULL, output, width * sizeof(uint32_t));
SDL_RenderClear(renderer);
SDL_RenderCopy(renderer, texture, NULL, NULL);
SDL_RenderPresent(renderer);
ok = 1;
Error:
SDL_FreeSurface(surface);
SDL_FreeSurface(screen);
WebPFreeDecBuffer(output);
// We should call SDL_DestroyWindow(window) but that makes .js fail.
SDL_DestroyRenderer(renderer);
SDL_DestroyTexture(texture);
WebPFree(output);
return ok;
}

View File

@ -260,14 +260,20 @@ int WebPWritePAM(FILE* fout, const WebPDecBuffer* const buffer) {
// Save 16b mode (RGBA4444, RGB565, ...) for debugging purpose.
int WebPWrite16bAsPGM(FILE* fout, const WebPDecBuffer* const buffer) {
const uint32_t width = buffer->width;
const uint32_t height = buffer->height;
const uint8_t* rgba = buffer->u.RGBA.rgba;
const int stride = buffer->u.RGBA.stride;
uint32_t width, height;
uint8_t* rgba;
int stride;
const uint32_t bytes_per_px = 2;
uint32_t y;
if (fout == NULL || buffer == NULL || rgba == NULL) return 0;
if (fout == NULL || buffer == NULL) return 0;
width = buffer->width;
height = buffer->height;
rgba = buffer->u.RGBA.rgba;
stride = buffer->u.RGBA.stride;
if (rgba == NULL) return 0;
fprintf(fout, "P5\n%u %u\n255\n", width * bytes_per_px, height);
for (y = 0; y < height; ++y) {
@ -295,22 +301,29 @@ static void PutLE32(uint8_t* const dst, uint32_t value) {
#define BMP_HEADER_SIZE 54
#define BMP_HEADER_ALPHA_EXTRA_SIZE 16 // for alpha info
int WebPWriteBMP(FILE* fout, const WebPDecBuffer* const buffer) {
const int has_alpha = WebPIsAlphaMode(buffer->colorspace);
const int header_size =
BMP_HEADER_SIZE + (has_alpha ? BMP_HEADER_ALPHA_EXTRA_SIZE : 0);
const uint32_t width = buffer->width;
const uint32_t height = buffer->height;
const uint8_t* rgba = buffer->u.RGBA.rgba;
const int stride = buffer->u.RGBA.stride;
const uint32_t bytes_per_px = has_alpha ? 4 : 3;
int has_alpha, header_size;
uint32_t width, height;
uint8_t* rgba;
int stride;
uint32_t y;
const uint32_t line_size = bytes_per_px * width;
const uint32_t bmp_stride = (line_size + 3) & ~3; // pad to 4
const uint32_t image_size = bmp_stride * height;
const uint32_t total_size = image_size + header_size;
uint32_t bytes_per_px, line_size, image_size, bmp_stride, total_size;
uint8_t bmp_header[BMP_HEADER_SIZE + BMP_HEADER_ALPHA_EXTRA_SIZE] = { 0 };
if (fout == NULL || buffer == NULL || rgba == NULL) return 0;
if (fout == NULL || buffer == NULL) return 0;
has_alpha = WebPIsAlphaMode(buffer->colorspace);
header_size = BMP_HEADER_SIZE + (has_alpha ? BMP_HEADER_ALPHA_EXTRA_SIZE : 0);
width = buffer->width;
height = buffer->height;
rgba = buffer->u.RGBA.rgba;
stride = buffer->u.RGBA.stride;
bytes_per_px = has_alpha ? 4 : 3;
line_size = bytes_per_px * width;
bmp_stride = (line_size + 3) & ~3; // pad to 4
image_size = bmp_stride * height;
total_size = image_size + header_size;
if (rgba == NULL) return 0;
// bitmap file header
PutLE16(bmp_header + 0, 0x4d42); // signature 'BM'
@ -372,17 +385,14 @@ int WebPWriteBMP(FILE* fout, const WebPDecBuffer* const buffer) {
#define TIFF_HEADER_SIZE (EXTRA_DATA_OFFSET + EXTRA_DATA_SIZE)
int WebPWriteTIFF(FILE* fout, const WebPDecBuffer* const buffer) {
const int has_alpha = WebPIsAlphaMode(buffer->colorspace);
const uint32_t width = buffer->width;
const uint32_t height = buffer->height;
const uint8_t* rgba = buffer->u.RGBA.rgba;
const int stride = buffer->u.RGBA.stride;
const uint8_t bytes_per_px = has_alpha ? 4 : 3;
const uint8_t assoc_alpha =
WebPIsPremultipliedMode(buffer->colorspace) ? 1 : 2;
int has_alpha;
uint32_t width, height;
uint8_t* rgba;
int stride;
uint8_t bytes_per_px = 0;
const uint8_t assoc_alpha = 0;
// For non-alpha case, we omit tag 0x152 (ExtraSamples).
const uint8_t num_ifd_entries = has_alpha ? NUM_IFD_ENTRIES
: NUM_IFD_ENTRIES - 1;
const uint8_t num_ifd_entries = 0;
uint8_t tiff_header[TIFF_HEADER_SIZE] = {
0x49, 0x49, 0x2a, 0x00, // little endian signature
8, 0, 0, 0, // offset to the unique IFD that follows
@ -416,7 +426,20 @@ int WebPWriteTIFF(FILE* fout, const WebPDecBuffer* const buffer) {
};
uint32_t y;
if (fout == NULL || buffer == NULL || rgba == NULL) return 0;
if (fout == NULL || buffer == NULL) return 0;
has_alpha = WebPIsAlphaMode(buffer->colorspace);
width = buffer->width;
height = buffer->height;
rgba = buffer->u.RGBA.rgba;
stride = buffer->u.RGBA.stride;
if (rgba == NULL) return 0;
// Update bytes_per_px, num_ifd_entries and assoc_alpha.
tiff_header[38] = tiff_header[102] = bytes_per_px = has_alpha ? 4 : 3;
tiff_header[8] = has_alpha ? NUM_IFD_ENTRIES : NUM_IFD_ENTRIES - 1;
tiff_header[186] = WebPIsPremultipliedMode(buffer->colorspace) ? 1 : 2;
// Fill placeholders in IFD:
PutLE32(tiff_header + 10 + 8, width);

View File

@ -89,6 +89,11 @@ int ImgIoUtilReadFile(const char* const file_name,
}
fseek(in, 0, SEEK_END);
file_size = ftell(in);
if (file_size == (size_t)-1) {
fclose(in);
WFPRINTF(stderr, "error getting size of '%s'\n", (const W_CHAR*)file_name);
return 0;
}
fseek(in, 0, SEEK_SET);
// we allocate one extra byte for the \0 terminator
file_data = (uint8_t*)WebPMalloc(file_size + 1);

View File

@ -206,8 +206,18 @@ struct my_error_mgr {
static void my_error_exit(j_common_ptr dinfo) {
struct my_error_mgr* myerr = (struct my_error_mgr*)dinfo->err;
// The following code is disabled in fuzzing mode because:
// - the logs can be flooded due to invalid JPEG files
// - msg_code is wrongfully seen as uninitialized by msan when the libjpeg
// dependency is not built with sanitizers enabled
#ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
const int msg_code = myerr->pub.msg_code;
fprintf(stderr, "libjpeg error: ");
dinfo->err->output_message(dinfo);
if (msg_code == JERR_INPUT_EOF || msg_code == JERR_FILE_READ) {
fprintf(stderr, "`jpegtran -copy all` MAY be able to process this file.\n");
}
#endif
longjmp(myerr->setjmp_buffer, 1);
}

View File

@ -139,6 +139,8 @@ static const struct {
{ "Raw profile type xmp", ProcessRawProfile, METADATA_OFFSET(xmp) },
// Exiftool puts exif data in APP1 chunk, too.
{ "Raw profile type APP1", ProcessRawProfile, METADATA_OFFSET(exif) },
// ImageMagick uses lowercase app1.
{ "Raw profile type app1", ProcessRawProfile, METADATA_OFFSET(exif) },
// XMP Specification Part 3, Section 3 #PNG
{ "XML:com.adobe.xmp", MetadataCopy, METADATA_OFFSET(xmp) },
{ NULL, NULL, 0 },
@ -159,6 +161,20 @@ static int ExtractMetadataFromPNG(png_structp png,
png_textp text = NULL;
const png_uint_32 num = png_get_text(png, info, &text, NULL);
png_uint_32 i;
#ifdef PNG_eXIf_SUPPORTED
// Look for an 'eXIf' tag. Preference is given to this tag as it's newer
// than the TextualData tags.
{
png_bytep exif;
png_uint_32 len;
if (png_get_eXIf_1(png, info, &len, &exif) == PNG_INFO_eXIf) {
if (!MetadataCopy((const char*)exif, len, &metadata->exif)) return 0;
}
}
#endif // PNG_eXIf_SUPPORTED
// Look for EXIF / XMP metadata.
for (i = 0; i < num; ++i, ++text) {
int j;
@ -192,6 +208,7 @@ static int ExtractMetadataFromPNG(png_structp png,
}
}
}
#ifdef PNG_iCCP_SUPPORTED
// Look for an ICC profile.
{
png_charp name;
@ -208,6 +225,7 @@ static int ExtractMetadataFromPNG(png_structp png,
if (!MetadataCopy((const char*)profile, len, &metadata->iccp)) return 0;
}
}
#endif // PNG_iCCP_SUPPORTED
}
return 1;
}
@ -235,7 +253,7 @@ int ReadPNG(const uint8_t* const data, size_t data_size,
volatile png_infop end_info = NULL;
PNGReadContext context = { NULL, 0, 0 };
int color_type, bit_depth, interlaced;
int has_alpha;
int num_channels;
int num_passes;
int p;
volatile int ok = 0;
@ -293,9 +311,6 @@ int ReadPNG(const uint8_t* const data, size_t data_size,
}
if (png_get_valid(png, info, PNG_INFO_tRNS)) {
png_set_tRNS_to_alpha(png);
has_alpha = 1;
} else {
has_alpha = !!(color_type & PNG_COLOR_MASK_ALPHA);
}
// Apply gamma correction if needed.
@ -310,13 +325,16 @@ int ReadPNG(const uint8_t* const data, size_t data_size,
if (!keep_alpha) {
png_set_strip_alpha(png);
has_alpha = 0;
}
num_passes = png_set_interlace_handling(png);
png_read_update_info(png, info);
stride = (int64_t)(has_alpha ? 4 : 3) * width * sizeof(*rgb);
num_channels = png_get_channels(png, info);
if (num_channels != 3 && num_channels != 4) {
goto Error;
}
stride = (int64_t)num_channels * width * sizeof(*rgb);
if (stride != (int)stride ||
!ImgIoUtilCheckSizeArgumentsOverflow(stride, height)) {
goto Error;
@ -341,8 +359,8 @@ int ReadPNG(const uint8_t* const data, size_t data_size,
pic->width = (int)width;
pic->height = (int)height;
ok = has_alpha ? WebPPictureImportRGBA(pic, rgb, (int)stride)
: WebPPictureImportRGB(pic, rgb, (int)stride);
ok = (num_channels == 4) ? WebPPictureImportRGBA(pic, rgb, (int)stride)
: WebPPictureImportRGB(pic, rgb, (int)stride);
if (!ok) {
goto Error;

View File

@ -41,6 +41,7 @@ readonly TARGETDIR="${TOPDIR}/WebP.framework"
readonly DECTARGETDIR="${TOPDIR}/WebPDecoder.framework"
readonly MUXTARGETDIR="${TOPDIR}/WebPMux.framework"
readonly DEMUXTARGETDIR="${TOPDIR}/WebPDemux.framework"
readonly SHARPYUVTARGETDIR="${TOPDIR}/SharpYuv.framework"
readonly DEVELOPER=$(xcode-select --print-path)
readonly PLATFORMSROOT="${DEVELOPER}/Platforms"
readonly LIPO=$(xcrun -sdk iphoneos${SDK} -find lipo)
@ -52,7 +53,7 @@ DEMUXLIBLIST=''
if [[ -z "${SDK}" ]]; then
echo "iOS SDK not available"
exit 1
elif [[ ${SDK%%.*} -gt 8 ]]; then
elif [[ ${SDK%%.*} -gt 8 && "${XCODE%%.*}" -lt 16 ]]; then
EXTRA_CFLAGS="-fembed-bitcode"
elif [[ ${SDK%%.*} -le 6 ]]; then
echo "You need iOS SDK version 6.0 or above"
@ -63,7 +64,8 @@ echo "Xcode Version: ${XCODE}"
echo "iOS SDK Version: ${SDK}"
if [[ -e "${BUILDDIR}" || -e "${TARGETDIR}" || -e "${DECTARGETDIR}" \
|| -e "${MUXTARGETDIR}" || -e "${DEMUXTARGETDIR}" ]]; then
|| -e "${MUXTARGETDIR}" || -e "${DEMUXTARGETDIR}" \
|| -e "${SHARPYUVTARGETDIR}" ]]; then
cat << EOF
WARNING: The following directories will be deleted:
WARNING: ${BUILDDIR}
@ -71,14 +73,16 @@ WARNING: ${TARGETDIR}
WARNING: ${DECTARGETDIR}
WARNING: ${MUXTARGETDIR}
WARNING: ${DEMUXTARGETDIR}
WARNING: ${SHARPYUVTARGETDIR}
WARNING: The build will continue in 5 seconds...
EOF
sleep 5
fi
rm -rf ${BUILDDIR} ${TARGETDIR} ${DECTARGETDIR} \
${MUXTARGETDIR} ${DEMUXTARGETDIR}
${MUXTARGETDIR} ${DEMUXTARGETDIR} ${SHARPYUVTARGETDIR}
mkdir -p ${BUILDDIR} ${TARGETDIR}/Headers/ ${DECTARGETDIR}/Headers/ \
${MUXTARGETDIR}/Headers/ ${DEMUXTARGETDIR}/Headers/
${MUXTARGETDIR}/Headers/ ${DEMUXTARGETDIR}/Headers/ \
${SHARPYUVTARGETDIR}/Headers/
if [[ ! -e ${SRCDIR}/configure ]]; then
if ! (cd ${SRCDIR} && sh autogen.sh); then
@ -134,13 +138,14 @@ for PLATFORM in ${PLATFORMS}; do
set +x
# Build only the libraries, skip the examples.
make V=0 -C sharpyuv
make V=0 -C sharpyuv install
make V=0 -C src install
LIBLIST+=" ${ROOTDIR}/lib/libwebp.a"
DECLIBLIST+=" ${ROOTDIR}/lib/libwebpdecoder.a"
MUXLIBLIST+=" ${ROOTDIR}/lib/libwebpmux.a"
DEMUXLIBLIST+=" ${ROOTDIR}/lib/libwebpdemux.a"
SHARPYUVLIBLIST+=" ${ROOTDIR}/lib/libsharpyuv.a"
make clean
@ -165,4 +170,9 @@ cp -a ${SRCDIR}/src/webp/{decode,types,mux_types,demux}.h \
${DEMUXTARGETDIR}/Headers/
${LIPO} -create ${DEMUXLIBLIST} -output ${DEMUXTARGETDIR}/WebPDemux
echo "SHARPYUVLIBLIST = ${SHARPYUVLIBLIST}"
cp -a ${SRCDIR}/sharpyuv/{sharpyuv,sharpyuv_csp}.h \
${SHARPYUVTARGETDIR}/Headers/
${LIPO} -create ${SHARPYUVLIBLIST} -output ${SHARPYUVTARGETDIR}/SharpYuv
echo "SUCCESS"

View File

@ -37,13 +37,13 @@ else
endif
# SDL flags: use sdl-config if it exists
SDL_CONFIG = $(shell sdl-config --version 2> /dev/null)
SDL_CONFIG = $(shell sdl2-config --version 2> /dev/null)
ifneq ($(SDL_CONFIG),)
SDL_LIBS = $(shell sdl-config --libs)
SDL_FLAGS = $(shell sdl-config --cflags)
SDL_LIBS = $(shell sdl2-config --libs)
SDL_FLAGS = $(shell sdl2-config --cflags)
else
# use best-guess
SDL_LIBS = -lSDL
SDL_LIBS = -lSDL2
SDL_FLAGS =
endif
@ -276,6 +276,7 @@ UTILS_DEC_OBJS = \
src/utils/color_cache_utils.o \
src/utils/filters_utils.o \
src/utils/huffman_utils.o \
src/utils/palette.o \
src/utils/quant_levels_dec_utils.o \
src/utils/random_utils.o \
src/utils/rescaler_utils.o \
@ -290,6 +291,7 @@ UTILS_ENC_OBJS = \
EXTRA_OBJS = \
extras/extras.o \
extras/quality_estimate.o \
extras/sharpyuv_risk_table.o \
LIBWEBPDECODER_OBJS = $(DEC_OBJS) $(DSP_DEC_OBJS) $(UTILS_DEC_OBJS)
LIBWEBP_OBJS = $(LIBWEBPDECODER_OBJS) $(ENC_OBJS) \
@ -343,6 +345,7 @@ HDRS = \
src/utils/filters_utils.h \
src/utils/huffman_utils.h \
src/utils/huffman_encode_utils.h \
src/utils/palette.h \
src/utils/quant_levels_utils.h \
src/utils/quant_levels_dec_utils.h \
src/utils/random_utils.h \

View File

@ -1,5 +1,5 @@
.\" Hey, EMACS: -*- nroff -*-
.TH CWEBP 1 "March 17, 2022"
.TH CWEBP 1 "September 17, 2024"
.SH NAME
cwebp \- compress an image file to a WebP file
.SH SYNOPSIS
@ -135,7 +135,9 @@ are used, \fB\-size\fP value will prevail.
Set a maximum number of passes to use during the dichotomy used by
options \fB\-size\fP or \fB\-psnr\fP. Maximum value is 10, default is 1.
If options \fB\-size\fP or \fB\-psnr\fP were used, but \fB\-pass\fP wasn't
specified, a default value of '6' passes will be used.
specified, a default value of '6' passes will be used. If \fB\-pass\fP is
specified, but neither \fB-size\fP nor \fB-psnr\fP are, a target PSNR of 40dB
will be used.
.TP
.BI \-qrange " int int
Specifies the permissible interval for the quality factor. This is particularly
@ -178,8 +180,8 @@ Disable strong filtering (if filtering is being used thanks to the
\fB\-f\fP option) and use simple filtering instead.
.TP
.B \-sharp_yuv
Use more accurate and sharper RGB->YUV conversion if needed. Note that this
process is slower than the default 'fast' RGB->YUV conversion.
Use more accurate and sharper RGB->YUV conversion. Note that this process is
slower than the default 'fast' RGB->YUV conversion.
.TP
.BI \-sns " int
Specify the amplitude of the spatial noise shaping. Spatial noise shaping
@ -202,7 +204,8 @@ In the VP8 format, the so\-called control partition has a limit of 512k and
is used to store the following information: whether the macroblock is skipped,
which segment it belongs to, whether it is coded as intra 4x4 or intra 16x16
mode, and finally the prediction modes to use for each of the sub\-blocks.
For a very large image, 512k only leaves room to few bits per 16x16 macroblock.
For a very large image, 512k only leaves room for a few bits per 16x16
macroblock.
The absolute minimum is 4 bits per macroblock. Skip, segment, and mode
information can use up almost all these 4 bits (although the case is unlikely),
which is problematic for very large images. The partition_limit factor controls
@ -211,7 +214,8 @@ useful in case the 512k limit is reached and the following message is displayed:
\fIError code: 6 (PARTITION0_OVERFLOW: Partition #0 is too big to fit 512k)\fP.
If using \fB\-partition_limit\fP is not enough to meet the 512k constraint, one
should use less segments in order to save more header bits per macroblock.
See the \fB\-segments\fP option.
See the \fB\-segments\fP option. Note the \fB-m\fP and \fB-q\fP options also
influence the encoder's decisions and ability to hit this limit.
.SS LOGGING OPTIONS
These options control the level of output:
@ -295,12 +299,12 @@ Note: each input format may not support all combinations.
.B \-noasm
Disable all assembly optimizations.
.SH BUGS
Please report all bugs to the issue tracker:
https://bugs.chromium.org/p/webp
.br
Patches welcome! See this page to get started:
https://www.webmproject.org/code/contribute/submitting\-patches/
.SH EXIT STATUS
If there were no problems during execution, \fBcwebp\fP exits with the value of
the C constant \fBEXIT_SUCCESS\fP. This is usually zero.
.PP
If an error occurs, \fBcwebp\fP exits with the value of the C constant
\fBEXIT_FAILURE\fP. This is usually one.
.SH EXAMPLES
cwebp \-q 50 -lossless picture.png \-o picture_lossless.webp
@ -320,6 +324,13 @@ https://chromium.googlesource.com/webm/libwebp
This manual page was written by Pascal Massimino <pascal.massimino@gmail.com>,
for the Debian project (and may be used by others).
.SH REPORTING BUGS
Please report all bugs to the issue tracker:
https://issues.webmproject.org
.br
Patches welcome! See this page to get started:
https://www.webmproject.org/code/contribute/submitting\-patches/
.SH SEE ALSO
.BR dwebp (1),
.BR gif2webp (1)

View File

@ -1,5 +1,5 @@
.\" Hey, EMACS: -*- nroff -*-
.TH DWEBP 1 "November 17, 2021"
.TH DWEBP 1 "July 18, 2024"
.SH NAME
dwebp \- decompress a WebP file to an image file
.SH SYNOPSIS
@ -108,12 +108,12 @@ Print extra information (decoding time in particular).
.B \-noasm
Disable all assembly optimizations.
.SH BUGS
Please report all bugs to the issue tracker:
https://bugs.chromium.org/p/webp
.br
Patches welcome! See this page to get started:
https://www.webmproject.org/code/contribute/submitting\-patches/
.SH EXIT STATUS
If there were no problems during execution, \fBdwebp\fP exits with the value of
the C constant \fBEXIT_SUCCESS\fP. This is usually zero.
.PP
If an error occurs, \fBdwebp\fP exits with the value of the C constant
\fBEXIT_FAILURE\fP. This is usually one.
.SH EXAMPLES
dwebp picture.webp \-o output.png
@ -133,6 +133,13 @@ https://chromium.googlesource.com/webm/libwebp
This manual page was written by Pascal Massimino <pascal.massimino@gmail.com>,
for the Debian project (and may be used by others).
.SH REPORTING BUGS
Please report all bugs to the issue tracker:
https://issues.webmproject.org
.br
Patches welcome! See this page to get started:
https://www.webmproject.org/code/contribute/submitting\-patches/
.SH SEE ALSO
.BR cwebp (1),
.BR gif2webp (1),

View File

@ -1,5 +1,5 @@
.\" Hey, EMACS: -*- nroff -*-
.TH GIF2WEBP 1 "November 17, 2021"
.TH GIF2WEBP 1 "November 4, 2024"
.SH NAME
gif2webp \- Convert a GIF image to WebP
.SH SYNOPSIS
@ -39,6 +39,18 @@ Encode the image using lossy compression.
Mixed compression mode: optimize compression of the image by picking either
lossy or lossless compression for each frame heuristically.
.TP
.BI \-near_lossless " int
Specify the level of near\-lossless image preprocessing. This option adjusts
pixel values to help compressibility, but has minimal impact on the visual
quality. It triggers lossless compression mode automatically. The range is 0
(maximum preprocessing) to 100 (no preprocessing, the default). The typical
value is around 60. Note that lossy with \fB\-q 100\fP can at times yield
better results.
.TP
.B \-sharp_yuv
Use more accurate and sharper RGB->YUV conversion. Note that this process is
slower than the default 'fast' RGB->YUV conversion.
.TP
.BI \-q " float
Specify the compression factor for RGB channels between 0 and 100. The default
is 75.
@ -126,12 +138,12 @@ Print extra information.
.B \-quiet
Do not print anything.
.SH BUGS
Please report all bugs to the issue tracker:
https://bugs.chromium.org/p/webp
.br
Patches welcome! See this page to get started:
https://www.webmproject.org/code/contribute/submitting\-patches/
.SH EXIT STATUS
If there were no problems during execution, \fBgif2webp\fP exits with the value
of the C constant \fBEXIT_SUCCESS\fP. This is usually zero.
.PP
If an error occurs, \fBgif2webp\fP exits with the value of the C constant
\fBEXIT_FAILURE\fP. This is usually one.
.SH EXAMPLES
gif2webp picture.gif \-o picture.webp
@ -155,6 +167,13 @@ https://chromium.googlesource.com/webm/libwebp
This manual page was written by Urvang Joshi <urvang@google.com>, for the
Debian project (and may be used by others).
.SH REPORTING BUGS
Please report all bugs to the issue tracker:
https://issues.webmproject.org
.br
Patches welcome! See this page to get started:
https://www.webmproject.org/code/contribute/submitting\-patches/
.SH SEE ALSO
.BR cwebp (1),
.BR dwebp (1),

View File

@ -1,10 +1,10 @@
.\" Hey, EMACS: -*- nroff -*-
.TH IMG2WEBP 1 "January 5, 2022"
.TH IMG2WEBP 1 "November 26, 2024"
.SH NAME
img2webp \- create animated WebP file from a sequence of input images.
.SH SYNOPSIS
.B img2webp
[file_options] [[frame_options] frame_file]...
[file_options] [[frame_options] frame_file]... [\-o webp_file]
.br
.B img2webp argument_file_name
.br
@ -44,6 +44,18 @@ Mixed compression mode: optimize compression of the image by picking either
lossy or lossless compression for each frame heuristically. This global
option disables the local option \fB-lossy\fP and \fB-lossless\fP .
.TP
.BI \-near_lossless " int
Specify the level of near\-lossless image preprocessing. This option adjusts
pixel values to help compressibility, but has minimal impact on the visual
quality. It triggers lossless compression mode automatically. The range is 0
(maximum preprocessing) to 100 (no preprocessing, the default). The typical
value is around 60. Note that lossy with \fB\-q 100\fP can at times yield
better results.
.TP
.B \-sharp_yuv
Use more accurate and sharper RGB->YUV conversion. Note that this process is
slower than the default 'fast' RGB->YUV conversion.
.TP
.BI \-loop " int
Specifies the number of times the animation should loop. Using '0'
means 'loop indefinitely'.
@ -76,18 +88,27 @@ Specify the compression factor between 0 and 100. The default is 75.
Specify the compression method to use. This parameter controls the
trade off between encoding speed and the compressed file size and quality.
Possible values range from 0 to 6. Default value is 4.
When higher values are used, the encoder will spend more time inspecting
additional encoding possibilities and decide on the quality gain.
Lower value can result in faster processing time at the expense of
larger file size and lower compression quality.
.TP
.B \-exact, \-noexact
Preserve or alter RGB values in transparent area. The default is
\fB-noexact\fP, to help compressibility. Note \fB\-noexact\fP may cause
artifacts in frames compressed with \fB\-lossy\fP.
.SH EXIT STATUS
If there were no problems during execution, \fBimg2webp\fP exits with the value
of the C constant \fBEXIT_SUCCESS\fP. This is usually zero.
.PP
If an error occurs, \fBimg2webp\fP exits with the value of the C constant
\fBEXIT_FAILURE\fP. This is usually one.
.SH EXAMPLE
img2webp -loop 2 in0.png -lossy in1.jpg -d 80 in2.tiff -o out.webp
.br
.SH BUGS
Please report all bugs to the issue tracker:
https://bugs.chromium.org/p/webp
.br
Patches welcome! See this page to get started:
https://www.webmproject.org/code/contribute/submitting\-patches/
.SH AUTHORS
\fBimg2webp\fP is a part of libwebp and was written by the WebP team.
.br
@ -97,6 +118,13 @@ https://chromium.googlesource.com/webm/libwebp
This manual page was written by Pascal Massimino <pascal.massimino@gmail.com>,
for the Debian project (and may be used by others).
.SH REPORTING BUGS
Please report all bugs to the issue tracker:
https://issues.webmproject.org
.br
Patches welcome! See this page to get started:
https://www.webmproject.org/code/contribute/submitting\-patches/
.SH SEE ALSO
.BR webpmux (1),
.BR gif2webp (1)

View File

@ -1,5 +1,5 @@
.\" Hey, EMACS: -*- nroff -*-
.TH VWEBP 1 "November 17, 2021"
.TH VWEBP 1 "July 18, 2024"
.SH NAME
vwebp \- decompress a WebP file and display it in a window
.SH SYNOPSIS
@ -72,12 +72,12 @@ Disable blending and disposal process, for debugging purposes.
.B 'q' / 'Q' / ESC
Quit.
.SH BUGS
Please report all bugs to the issue tracker:
https://bugs.chromium.org/p/webp
.br
Patches welcome! See this page to get started:
https://www.webmproject.org/code/contribute/submitting\-patches/
.SH EXIT STATUS
If there were no problems during execution, \fBvwebp\fP exits with the value of
the C constant \fBEXIT_SUCCESS\fP. This is usually zero.
.PP
If an error occurs, \fBvwebp\fP exits with the value of the C constant
\fBEXIT_FAILURE\fP. This is usually one.
.SH EXAMPLES
vwebp picture.webp
@ -94,6 +94,13 @@ https://chromium.googlesource.com/webm/libwebp
.PP
This manual page was written for the Debian project (and may be used by others).
.SH REPORTING BUGS
Please report all bugs to the issue tracker:
https://issues.webmproject.org
.br
Patches welcome! See this page to get started:
https://www.webmproject.org/code/contribute/submitting\-patches/
.SH SEE ALSO
.BR dwebp (1)
.br

View File

@ -1,5 +1,5 @@
.\" Hey, EMACS: -*- nroff -*-
.TH WEBPINFO 1 "November 17, 2021"
.TH WEBPINFO 1 "July 18, 2024"
.SH NAME
webpinfo \- print out the chunk level structure of WebP files
along with basic integrity checks.
@ -47,12 +47,12 @@ Detailed usage instructions.
Input files in WebP format. Input files must come last, following
options (if any). There can be multiple input files.
.SH BUGS
Please report all bugs to the issue tracker:
https://bugs.chromium.org/p/webp
.br
Patches welcome! See this page to get started:
https://www.webmproject.org/code/contribute/submitting\-patches/
.SH EXIT STATUS
If there were no problems during execution, \fBwebpinfo\fP exits with the value
of the C constant \fBEXIT_SUCCESS\fP. This is usually zero.
.PP
If an error occurs, \fBwebpinfo\fP exits with the value of the C constant
\fBEXIT_FAILURE\fP. This is usually one.
.SH EXAMPLES
.br
@ -73,6 +73,13 @@ https://chromium.googlesource.com/webm/libwebp
This manual page was written by Hui Su <huisu@google.com>,
for the Debian project (and may be used by others).
.SH REPORTING BUGS
Please report all bugs to the issue tracker:
https://issues.webmproject.org
.br
Patches welcome! See this page to get started:
https://www.webmproject.org/code/contribute/submitting\-patches/
.SH SEE ALSO
.BR webpmux (1)
.br

View File

@ -1,5 +1,5 @@
.\" Hey, EMACS: -*- nroff -*-
.TH WEBPMUX 1 "November 17, 2021"
.TH WEBPMUX 1 "July 18, 2024"
.SH NAME
webpmux \- create animated WebP files from non\-animated WebP images, extract
frames from animated WebP images, and manage XMP/EXIF metadata and ICC profile.
@ -186,12 +186,12 @@ Output file in WebP format.
.TP
The nature of EXIF, XMP and ICC data is not checked and is assumed to be valid.
.SH BUGS
Please report all bugs to the issue tracker:
https://bugs.chromium.org/p/webp
.br
Patches welcome! See this page to get started:
https://www.webmproject.org/code/contribute/submitting\-patches/
.SH EXIT STATUS
If there were no problems during execution, \fBwebpmux\fP exits with the value
of the C constant \fBEXIT_SUCCESS\fP. This is usually zero.
.PP
If an error occurs, \fBwebpmux\fP exits with the value of the C constant
\fBEXIT_FAILURE\fP. This is usually one.
.SH EXAMPLES
.P
@ -262,6 +262,13 @@ https://chromium.googlesource.com/webm/libwebp
This manual page was written by Vikas Arora <vikaas.arora@gmail.com>,
for the Debian project (and may be used by others).
.SH REPORTING BUGS
Please report all bugs to the issue tracker:
https://issues.webmproject.org
.br
Patches welcome! See this page to get started:
https://www.webmproject.org/code/contribute/submitting\-patches/
.SH SEE ALSO
.BR cwebp (1),
.BR dwebp (1),

View File

@ -33,7 +33,7 @@ libsharpyuv_la_SOURCES += sharpyuv_gamma.c sharpyuv_gamma.h
libsharpyuv_la_SOURCES += sharpyuv.c sharpyuv.h
libsharpyuv_la_CPPFLAGS = $(AM_CPPFLAGS)
libsharpyuv_la_LDFLAGS = -no-undefined -version-info 0:0:0 -lm
libsharpyuv_la_LDFLAGS = -no-undefined -version-info 1:1:1 -lm
libsharpyuv_la_LIBADD =
libsharpyuv_la_LIBADD += libsharpyuv_sse2.la
libsharpyuv_la_LIBADD += libsharpyuv_neon.la

View File

@ -6,8 +6,8 @@
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
VS_VERSION_INFO VERSIONINFO
FILEVERSION 0,0,2,0
PRODUCTVERSION 0,0,2,0
FILEVERSION 0,0,4,1
PRODUCTVERSION 0,0,4,1
FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
FILEFLAGS 0x1L
@ -24,12 +24,12 @@ BEGIN
BEGIN
VALUE "CompanyName", "Google, Inc."
VALUE "FileDescription", "libsharpyuv DLL"
VALUE "FileVersion", "0.2.0"
VALUE "FileVersion", "0.4.1"
VALUE "InternalName", "libsharpyuv.dll"
VALUE "LegalCopyright", "Copyright (C) 2022"
VALUE "LegalCopyright", "Copyright (C) 2024"
VALUE "OriginalFilename", "libsharpyuv.dll"
VALUE "ProductName", "SharpYuv Library"
VALUE "ProductVersion", "0.2.0"
VALUE "ProductVersion", "0.4.1"
END
END
BLOCK "VarFileInfo"

View File

@ -75,41 +75,48 @@ static int RGBToGray(int64_t r, int64_t g, int64_t b) {
}
static uint32_t ScaleDown(uint16_t a, uint16_t b, uint16_t c, uint16_t d,
int rgb_bit_depth) {
int rgb_bit_depth,
SharpYuvTransferFunctionType transfer_type) {
const int bit_depth = rgb_bit_depth + GetPrecisionShift(rgb_bit_depth);
const uint32_t A = SharpYuvGammaToLinear(a, bit_depth);
const uint32_t B = SharpYuvGammaToLinear(b, bit_depth);
const uint32_t C = SharpYuvGammaToLinear(c, bit_depth);
const uint32_t D = SharpYuvGammaToLinear(d, bit_depth);
return SharpYuvLinearToGamma((A + B + C + D + 2) >> 2, bit_depth);
const uint32_t A = SharpYuvGammaToLinear(a, bit_depth, transfer_type);
const uint32_t B = SharpYuvGammaToLinear(b, bit_depth, transfer_type);
const uint32_t C = SharpYuvGammaToLinear(c, bit_depth, transfer_type);
const uint32_t D = SharpYuvGammaToLinear(d, bit_depth, transfer_type);
return SharpYuvLinearToGamma((A + B + C + D + 2) >> 2, bit_depth,
transfer_type);
}
static WEBP_INLINE void UpdateW(const fixed_y_t* src, fixed_y_t* dst, int w,
int rgb_bit_depth) {
int rgb_bit_depth,
SharpYuvTransferFunctionType transfer_type) {
const int bit_depth = rgb_bit_depth + GetPrecisionShift(rgb_bit_depth);
int i;
for (i = 0; i < w; ++i) {
const uint32_t R = SharpYuvGammaToLinear(src[0 * w + i], bit_depth);
const uint32_t G = SharpYuvGammaToLinear(src[1 * w + i], bit_depth);
const uint32_t B = SharpYuvGammaToLinear(src[2 * w + i], bit_depth);
int i = 0;
do {
const uint32_t R =
SharpYuvGammaToLinear(src[0 * w + i], bit_depth, transfer_type);
const uint32_t G =
SharpYuvGammaToLinear(src[1 * w + i], bit_depth, transfer_type);
const uint32_t B =
SharpYuvGammaToLinear(src[2 * w + i], bit_depth, transfer_type);
const uint32_t Y = RGBToGray(R, G, B);
dst[i] = (fixed_y_t)SharpYuvLinearToGamma(Y, bit_depth);
}
dst[i] = (fixed_y_t)SharpYuvLinearToGamma(Y, bit_depth, transfer_type);
} while (++i < w);
}
static void UpdateChroma(const fixed_y_t* src1, const fixed_y_t* src2,
fixed_t* dst, int uv_w, int rgb_bit_depth) {
int i;
for (i = 0; i < uv_w; ++i) {
fixed_t* dst, int uv_w, int rgb_bit_depth,
SharpYuvTransferFunctionType transfer_type) {
int i = 0;
do {
const int r =
ScaleDown(src1[0 * uv_w + 0], src1[0 * uv_w + 1], src2[0 * uv_w + 0],
src2[0 * uv_w + 1], rgb_bit_depth);
src2[0 * uv_w + 1], rgb_bit_depth, transfer_type);
const int g =
ScaleDown(src1[2 * uv_w + 0], src1[2 * uv_w + 1], src2[2 * uv_w + 0],
src2[2 * uv_w + 1], rgb_bit_depth);
src2[2 * uv_w + 1], rgb_bit_depth, transfer_type);
const int b =
ScaleDown(src1[4 * uv_w + 0], src1[4 * uv_w + 1], src2[4 * uv_w + 0],
src2[4 * uv_w + 1], rgb_bit_depth);
src2[4 * uv_w + 1], rgb_bit_depth, transfer_type);
const int W = RGBToGray(r, g, b);
dst[0 * uv_w] = (fixed_t)(r - W);
dst[1 * uv_w] = (fixed_t)(g - W);
@ -117,15 +124,15 @@ static void UpdateChroma(const fixed_y_t* src1, const fixed_y_t* src2,
dst += 1;
src1 += 2;
src2 += 2;
}
} while (++i < uv_w);
}
static void StoreGray(const fixed_y_t* rgb, fixed_y_t* y, int w) {
int i;
int i = 0;
assert(w > 0);
for (i = 0; i < w; ++i) {
do {
y[i] = RGBToGray(rgb[0 * w + i], rgb[1 * w + i], rgb[2 * w + i]);
}
} while (++i < w);
}
//------------------------------------------------------------------------------
@ -151,9 +158,9 @@ static void ImportOneRow(const uint8_t* const r_ptr,
// Convert the rgb_step from a number of bytes to a number of uint8_t or
// uint16_t values depending the bit depth.
const int step = (rgb_bit_depth > 8) ? rgb_step / 2 : rgb_step;
int i;
int i = 0;
const int w = (pic_width + 1) & ~1;
for (i = 0; i < pic_width; ++i) {
do {
const int off = i * step;
const int shift = GetPrecisionShift(rgb_bit_depth);
if (rgb_bit_depth == 8) {
@ -165,7 +172,7 @@ static void ImportOneRow(const uint8_t* const r_ptr,
dst[i + 1 * w] = Shift(((uint16_t*)g_ptr)[off], shift);
dst[i + 2 * w] = Shift(((uint16_t*)b_ptr)[off], shift);
}
}
} while (++i < pic_width);
if (pic_width & 1) { // replicate rightmost pixel
dst[pic_width + 0 * w] = dst[pic_width + 0 * w - 1];
dst[pic_width + 1 * w] = dst[pic_width + 1 * w - 1];
@ -233,8 +240,11 @@ static int ConvertWRGBToYUV(const fixed_y_t* best_y, const fixed_t* best_uv,
const int sfix = GetPrecisionShift(rgb_bit_depth);
const int yuv_max = (1 << yuv_bit_depth) - 1;
for (best_uv = best_uv_base, j = 0; j < height; ++j) {
for (i = 0; i < width; ++i) {
best_uv = best_uv_base;
j = 0;
do {
i = 0;
do {
const int off = (i >> 1);
const int W = best_y[i];
const int r = best_uv[off + 0 * uv_w] + W;
@ -246,19 +256,22 @@ static int ConvertWRGBToYUV(const fixed_y_t* best_y, const fixed_t* best_uv,
} else {
((uint16_t*)y_ptr)[i] = clip(y, yuv_max);
}
}
} while (++i < width);
best_y += w;
best_uv += (j & 1) * 3 * uv_w;
y_ptr += y_stride;
}
for (best_uv = best_uv_base, j = 0; j < uv_h; ++j) {
for (i = 0; i < uv_w; ++i) {
const int off = i;
} while (++j < height);
best_uv = best_uv_base;
j = 0;
do {
i = 0;
do {
// Note r, g and b values here are off by W, but a constant offset on all
// 3 components doesn't change the value of u and v with a YCbCr matrix.
const int r = best_uv[off + 0 * uv_w];
const int g = best_uv[off + 1 * uv_w];
const int b = best_uv[off + 2 * uv_w];
const int r = best_uv[i + 0 * uv_w];
const int g = best_uv[i + 1 * uv_w];
const int b = best_uv[i + 2 * uv_w];
const int u = RGBToYUVComponent(r, g, b, yuv_matrix->rgb_to_u, sfix);
const int v = RGBToYUVComponent(r, g, b, yuv_matrix->rgb_to_v, sfix);
if (yuv_bit_depth <= 8) {
@ -268,11 +281,11 @@ static int ConvertWRGBToYUV(const fixed_y_t* best_y, const fixed_t* best_uv,
((uint16_t*)u_ptr)[i] = clip(u, yuv_max);
((uint16_t*)v_ptr)[i] = clip(v, yuv_max);
}
}
} while (++i < uv_w);
best_uv += 3 * uv_w;
u_ptr += u_stride;
v_ptr += v_stride;
}
} while (++j < uv_h);
return 1;
}
@ -285,7 +298,7 @@ static void* SafeMalloc(uint64_t nmemb, size_t size) {
return malloc((size_t)total_size);
}
#define SAFE_ALLOC(W, H, T) ((T*)SafeMalloc((W) * (H), sizeof(T)))
#define SAFE_ALLOC(W, H, T) ((T*)SafeMalloc((uint64_t)(W) * (H), sizeof(T)))
static int DoSharpArgbToYuv(const uint8_t* r_ptr, const uint8_t* g_ptr,
const uint8_t* b_ptr, int rgb_step, int rgb_stride,
@ -293,12 +306,14 @@ static int DoSharpArgbToYuv(const uint8_t* r_ptr, const uint8_t* g_ptr,
uint8_t* u_ptr, int u_stride, uint8_t* v_ptr,
int v_stride, int yuv_bit_depth, int width,
int height,
const SharpYuvConversionMatrix* yuv_matrix) {
const SharpYuvConversionMatrix* yuv_matrix,
SharpYuvTransferFunctionType transfer_type) {
// we expand the right/bottom border if needed
const int w = (width + 1) & ~1;
const int h = (height + 1) & ~1;
const int uv_w = w >> 1;
const int uv_h = h >> 1;
const int y_bit_depth = rgb_bit_depth + GetPrecisionShift(rgb_bit_depth);
uint64_t prev_diff_y_sum = ~0;
int j, iter;
@ -346,9 +361,9 @@ static int DoSharpArgbToYuv(const uint8_t* r_ptr, const uint8_t* g_ptr,
StoreGray(src1, best_y + 0, w);
StoreGray(src2, best_y + w, w);
UpdateW(src1, target_y, w, rgb_bit_depth);
UpdateW(src2, target_y + w, w, rgb_bit_depth);
UpdateChroma(src1, src2, target_uv, uv_w, rgb_bit_depth);
UpdateW(src1, target_y, w, rgb_bit_depth, transfer_type);
UpdateW(src2, target_y + w, w, rgb_bit_depth, transfer_type);
UpdateChroma(src1, src2, target_uv, uv_w, rgb_bit_depth, transfer_type);
memcpy(best_uv, target_uv, 3 * uv_w * sizeof(*best_uv));
best_y += 2 * w;
best_uv += 3 * uv_w;
@ -369,7 +384,8 @@ static int DoSharpArgbToYuv(const uint8_t* r_ptr, const uint8_t* g_ptr,
best_uv = best_uv_base;
target_y = target_y_base;
target_uv = target_uv_base;
for (j = 0; j < h; j += 2) {
j = 0;
do {
fixed_y_t* const src1 = tmp_buffer + 0 * w;
fixed_y_t* const src2 = tmp_buffer + 3 * w;
{
@ -380,21 +396,21 @@ static int DoSharpArgbToYuv(const uint8_t* r_ptr, const uint8_t* g_ptr,
cur_uv = next_uv;
}
UpdateW(src1, best_rgb_y + 0 * w, w, rgb_bit_depth);
UpdateW(src2, best_rgb_y + 1 * w, w, rgb_bit_depth);
UpdateChroma(src1, src2, best_rgb_uv, uv_w, rgb_bit_depth);
UpdateW(src1, best_rgb_y + 0 * w, w, rgb_bit_depth, transfer_type);
UpdateW(src2, best_rgb_y + 1 * w, w, rgb_bit_depth, transfer_type);
UpdateChroma(src1, src2, best_rgb_uv, uv_w, rgb_bit_depth, transfer_type);
// update two rows of Y and one row of RGB
diff_y_sum +=
SharpYuvUpdateY(target_y, best_rgb_y, best_y, 2 * w,
rgb_bit_depth + GetPrecisionShift(rgb_bit_depth));
SharpYuvUpdateY(target_y, best_rgb_y, best_y, 2 * w, y_bit_depth);
SharpYuvUpdateRGB(target_uv, best_rgb_uv, best_uv, 3 * uv_w);
best_y += 2 * w;
best_uv += 3 * uv_w;
target_y += 2 * w;
target_uv += 3 * uv_w;
}
j += 2;
} while (j < h);
// test exit condition
if (iter > 0) {
if (diff_y_sum < diff_y_threshold) break;
@ -418,6 +434,7 @@ static int DoSharpArgbToYuv(const uint8_t* r_ptr, const uint8_t* g_ptr,
free(tmp_buffer);
return ok;
}
#undef SAFE_ALLOC
#if defined(WEBP_USE_THREAD) && !defined(_WIN32)
@ -440,6 +457,7 @@ static int DoSharpArgbToYuv(const uint8_t* r_ptr, const uint8_t* g_ptr,
// By default SharpYuvConvert calls it with SharpYuvGetCPUInfo. If needed,
// users can declare it as extern and call it with an alternate VP8CPUInfo
// function.
extern VP8CPUInfo SharpYuvGetCPUInfo;
SHARPYUV_EXTERN void SharpYuvInit(VP8CPUInfo cpu_info_func);
void SharpYuvInit(VP8CPUInfo cpu_info_func) {
static volatile VP8CPUInfo sharpyuv_last_cpuinfo_used =
@ -461,12 +479,42 @@ void SharpYuvInit(VP8CPUInfo cpu_info_func) {
UNLOCK_ACCESS_AND_RETURN;
}
int SharpYuvConvert(const void* r_ptr, const void* g_ptr,
const void* b_ptr, int rgb_step, int rgb_stride,
int rgb_bit_depth, void* y_ptr, int y_stride,
void* u_ptr, int u_stride, void* v_ptr,
int v_stride, int yuv_bit_depth, int width,
int SharpYuvConvert(const void* r_ptr, const void* g_ptr, const void* b_ptr,
int rgb_step, int rgb_stride, int rgb_bit_depth,
void* y_ptr, int y_stride, void* u_ptr, int u_stride,
void* v_ptr, int v_stride, int yuv_bit_depth, int width,
int height, const SharpYuvConversionMatrix* yuv_matrix) {
SharpYuvOptions options;
options.yuv_matrix = yuv_matrix;
options.transfer_type = kSharpYuvTransferFunctionSrgb;
return SharpYuvConvertWithOptions(
r_ptr, g_ptr, b_ptr, rgb_step, rgb_stride, rgb_bit_depth, y_ptr, y_stride,
u_ptr, u_stride, v_ptr, v_stride, yuv_bit_depth, width, height, &options);
}
int SharpYuvOptionsInitInternal(const SharpYuvConversionMatrix* yuv_matrix,
SharpYuvOptions* options, int version) {
const int major = (version >> 24);
const int minor = (version >> 16) & 0xff;
if (options == NULL || yuv_matrix == NULL ||
(major == SHARPYUV_VERSION_MAJOR && major == 0 &&
minor != SHARPYUV_VERSION_MINOR) ||
(major != SHARPYUV_VERSION_MAJOR)) {
return 0;
}
options->yuv_matrix = yuv_matrix;
options->transfer_type = kSharpYuvTransferFunctionSrgb;
return 1;
}
int SharpYuvConvertWithOptions(const void* r_ptr, const void* g_ptr,
const void* b_ptr, int rgb_step, int rgb_stride,
int rgb_bit_depth, void* y_ptr, int y_stride,
void* u_ptr, int u_stride, void* v_ptr,
int v_stride, int yuv_bit_depth, int width,
int height, const SharpYuvOptions* options) {
const SharpYuvConversionMatrix* yuv_matrix = options->yuv_matrix;
SharpYuvTransferFunctionType transfer_type = options->transfer_type;
SharpYuvConversionMatrix scaled_matrix;
const int rgb_max = (1 << rgb_bit_depth) - 1;
const int rgb_round = 1 << (rgb_bit_depth - 1);
@ -485,7 +533,7 @@ int SharpYuvConvert(const void* r_ptr, const void* g_ptr,
if (yuv_bit_depth != 8 && yuv_bit_depth != 10 && yuv_bit_depth != 12) {
return 0;
}
if (rgb_bit_depth > 8 && (rgb_step % 2 != 0 || rgb_stride %2 != 0)) {
if (rgb_bit_depth > 8 && (rgb_step % 2 != 0 || rgb_stride % 2 != 0)) {
// Step/stride should be even for uint16_t buffers.
return 0;
}
@ -517,10 +565,11 @@ int SharpYuvConvert(const void* r_ptr, const void* g_ptr,
scaled_matrix.rgb_to_u[3] = Shift(yuv_matrix->rgb_to_u[3], sfix);
scaled_matrix.rgb_to_v[3] = Shift(yuv_matrix->rgb_to_v[3], sfix);
return DoSharpArgbToYuv(r_ptr, g_ptr, b_ptr, rgb_step, rgb_stride,
rgb_bit_depth, y_ptr, y_stride, u_ptr, u_stride,
v_ptr, v_stride, yuv_bit_depth, width, height,
&scaled_matrix);
return DoSharpArgbToYuv(
(const uint8_t*)r_ptr, (const uint8_t*)g_ptr, (const uint8_t*)b_ptr,
rgb_step, rgb_stride, rgb_bit_depth, (uint8_t*)y_ptr, y_stride,
(uint8_t*)u_ptr, u_stride, (uint8_t*)v_ptr, v_stride, yuv_bit_depth,
width, height, &scaled_matrix, transfer_type);
}
//------------------------------------------------------------------------------

View File

@ -22,22 +22,37 @@ extern "C" {
#else
// This explicitly marks library functions and allows for changing the
// signature for e.g., Windows DLL builds.
#if defined(__GNUC__) && __GNUC__ >= 4
#if defined(_WIN32) && defined(WEBP_DLL)
#define SHARPYUV_EXTERN __declspec(dllexport)
#elif defined(__GNUC__) && __GNUC__ >= 4
#define SHARPYUV_EXTERN extern __attribute__((visibility("default")))
#else
#if defined(_MSC_VER) && defined(WEBP_DLL)
#define SHARPYUV_EXTERN __declspec(dllexport)
#else
#define SHARPYUV_EXTERN extern
#endif /* _MSC_VER && WEBP_DLL */
#endif /* __GNUC__ >= 4 */
#endif /* defined(_WIN32) && defined(WEBP_DLL) */
#endif /* WEBP_EXTERN */
#endif /* SHARPYUV_EXTERN */
#ifndef SHARPYUV_INLINE
#ifdef WEBP_INLINE
#define SHARPYUV_INLINE WEBP_INLINE
#else
#ifndef _MSC_VER
#if defined(__cplusplus) || !defined(__STRICT_ANSI__) || \
(defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L)
#define SHARPYUV_INLINE inline
#else
#define SHARPYUV_INLINE
#endif
#else
#define SHARPYUV_INLINE __forceinline
#endif /* _MSC_VER */
#endif /* WEBP_INLINE */
#endif /* SHARPYUV_INLINE */
// SharpYUV API version following the convention from semver.org
#define SHARPYUV_VERSION_MAJOR 0
#define SHARPYUV_VERSION_MINOR 2
#define SHARPYUV_VERSION_PATCH 0
#define SHARPYUV_VERSION_MINOR 4
#define SHARPYUV_VERSION_PATCH 1
// Version as a uint32_t. The major number is the high 8 bits.
// The minor number is the middle 8 bits. The patch number is the low 16 bits.
#define SHARPYUV_MAKE_VERSION(MAJOR, MINOR, PATCH) \
@ -51,16 +66,50 @@ extern "C" {
SHARPYUV_EXTERN int SharpYuvGetVersion(void);
// RGB to YUV conversion matrix, in 16 bit fixed point.
// y = rgb_to_y[0] * r + rgb_to_y[1] * g + rgb_to_y[2] * b + rgb_to_y[3]
// u = rgb_to_u[0] * r + rgb_to_u[1] * g + rgb_to_u[2] * b + rgb_to_u[3]
// v = rgb_to_v[0] * r + rgb_to_v[1] * g + rgb_to_v[2] * b + rgb_to_v[3]
// Then y, u and v values are divided by 1<<16 and rounded.
// y_ = rgb_to_y[0] * r + rgb_to_y[1] * g + rgb_to_y[2] * b + rgb_to_y[3]
// u_ = rgb_to_u[0] * r + rgb_to_u[1] * g + rgb_to_u[2] * b + rgb_to_u[3]
// v_ = rgb_to_v[0] * r + rgb_to_v[1] * g + rgb_to_v[2] * b + rgb_to_v[3]
// Then the values are divided by 1<<16 and rounded.
// y = (y_ + (1 << 15)) >> 16
// u = (u_ + (1 << 15)) >> 16
// v = (v_ + (1 << 15)) >> 16
//
// Typically, the offset values rgb_to_y[3], rgb_to_u[3] and rgb_to_v[3] depend
// on the input's bit depth, e.g., rgb_to_u[3] = 1 << (rgb_bit_depth - 1 + 16).
// See also sharpyuv_csp.h to get a predefined matrix or generate a matrix.
typedef struct {
int rgb_to_y[4];
int rgb_to_u[4];
int rgb_to_v[4];
} SharpYuvConversionMatrix;
typedef struct SharpYuvOptions SharpYuvOptions;
// Enums for transfer functions, as defined in H.273,
// https://www.itu.int/rec/T-REC-H.273-202107-I/en
typedef enum SharpYuvTransferFunctionType {
// 0 is reserved
kSharpYuvTransferFunctionBt709 = 1,
// 2 is unspecified
// 3 is reserved
kSharpYuvTransferFunctionBt470M = 4,
kSharpYuvTransferFunctionBt470Bg = 5,
kSharpYuvTransferFunctionBt601 = 6,
kSharpYuvTransferFunctionSmpte240 = 7,
kSharpYuvTransferFunctionLinear = 8,
kSharpYuvTransferFunctionLog100 = 9,
kSharpYuvTransferFunctionLog100_Sqrt10 = 10,
kSharpYuvTransferFunctionIec61966 = 11,
kSharpYuvTransferFunctionBt1361 = 12,
kSharpYuvTransferFunctionSrgb = 13,
kSharpYuvTransferFunctionBt2020_10Bit = 14,
kSharpYuvTransferFunctionBt2020_12Bit = 15,
kSharpYuvTransferFunctionSmpte2084 = 16, // PQ
kSharpYuvTransferFunctionSmpte428 = 17,
kSharpYuvTransferFunctionHlg = 18,
kSharpYuvTransferFunctionNum
} SharpYuvTransferFunctionType;
// Converts RGB to YUV420 using a downsampling algorithm that minimizes
// artefacts caused by chroma subsampling.
// This is slower than standard downsampling (averaging of 4 UV values).
@ -85,6 +134,10 @@ typedef struct {
// adjacent pixels on the y, u and v channels. If yuv_bit_depth > 8, they
// should be multiples of 2.
// width, height: width and height of the image in pixels
// yuv_matrix: RGB to YUV conversion matrix. The matrix values typically
// depend on the input's rgb_bit_depth.
// This function calls SharpYuvConvertWithOptions with a default transfer
// function of kSharpYuvTransferFunctionSrgb.
SHARPYUV_EXTERN int SharpYuvConvert(const void* r_ptr, const void* g_ptr,
const void* b_ptr, int rgb_step,
int rgb_stride, int rgb_bit_depth,
@ -93,6 +146,31 @@ SHARPYUV_EXTERN int SharpYuvConvert(const void* r_ptr, const void* g_ptr,
int yuv_bit_depth, int width, int height,
const SharpYuvConversionMatrix* yuv_matrix);
struct SharpYuvOptions {
// This matrix cannot be NULL and can be initialized by
// SharpYuvComputeConversionMatrix.
const SharpYuvConversionMatrix* yuv_matrix;
SharpYuvTransferFunctionType transfer_type;
};
// Internal, version-checked, entry point
SHARPYUV_EXTERN int SharpYuvOptionsInitInternal(const SharpYuvConversionMatrix*,
SharpYuvOptions*, int);
// Should always be called, to initialize a fresh SharpYuvOptions
// structure before modification. SharpYuvOptionsInit() must have succeeded
// before using the 'options' object.
static SHARPYUV_INLINE int SharpYuvOptionsInit(
const SharpYuvConversionMatrix* yuv_matrix, SharpYuvOptions* options) {
return SharpYuvOptionsInitInternal(yuv_matrix, options, SHARPYUV_VERSION);
}
SHARPYUV_EXTERN int SharpYuvConvertWithOptions(
const void* r_ptr, const void* g_ptr, const void* b_ptr, int rgb_step,
int rgb_stride, int rgb_bit_depth, void* y_ptr, int y_stride, void* u_ptr,
int u_stride, void* v_ptr, int v_stride, int yuv_bit_depth, int width,
int height, const SharpYuvOptions* options);
// TODO(b/194336375): Add YUV444 to YUV420 conversion. Maybe also add 422
// support (it's rarely used in practice, especially for images).

View File

@ -22,16 +22,16 @@ void SharpYuvComputeConversionMatrix(const SharpYuvColorSpace* yuv_color_space,
const float kr = yuv_color_space->kr;
const float kb = yuv_color_space->kb;
const float kg = 1.0f - kr - kb;
const float cr = 0.5f / (1.0f - kb);
const float cb = 0.5f / (1.0f - kr);
const float cb = 0.5f / (1.0f - kb);
const float cr = 0.5f / (1.0f - kr);
const int shift = yuv_color_space->bit_depth - 8;
const float denom = (float)((1 << yuv_color_space->bit_depth) - 1);
float scale_y = 1.0f;
float add_y = 0.0f;
float scale_u = cr;
float scale_v = cb;
float scale_u = cb;
float scale_v = cr;
float add_uv = (float)(128 << shift);
assert(yuv_color_space->bit_depth >= 8);
@ -59,31 +59,35 @@ void SharpYuvComputeConversionMatrix(const SharpYuvColorSpace* yuv_color_space,
}
// Matrices are in YUV_FIX fixed point precision.
// WebP's matrix, similar but not identical to kRec601LimitedMatrix.
// WebP's matrix, similar but not identical to kRec601LimitedMatrix
// Derived using the following formulas:
// Y = 0.2569 * R + 0.5044 * G + 0.0979 * B + 16
// U = -0.1483 * R - 0.2911 * G + 0.4394 * B + 128
// V = 0.4394 * R - 0.3679 * G - 0.0715 * B + 128
static const SharpYuvConversionMatrix kWebpMatrix = {
{16839, 33059, 6420, 16 << 16},
{-9719, -19081, 28800, 128 << 16},
{28800, -24116, -4684, 128 << 16},
};
// Kr=0.2990f Kb=0.1140f bits=8 range=kSharpYuvRangeLimited
// Kr=0.2990f Kb=0.1140f bit_depth=8 range=kSharpYuvRangeLimited
static const SharpYuvConversionMatrix kRec601LimitedMatrix = {
{16829, 33039, 6416, 16 << 16},
{-9714, -19071, 28784, 128 << 16},
{28784, -24103, -4681, 128 << 16},
};
// Kr=0.2990f Kb=0.1140f bits=8 range=kSharpYuvRangeFull
// Kr=0.2990f Kb=0.1140f bit_depth=8 range=kSharpYuvRangeFull
static const SharpYuvConversionMatrix kRec601FullMatrix = {
{19595, 38470, 7471, 0},
{-11058, -21710, 32768, 128 << 16},
{32768, -27439, -5329, 128 << 16},
};
// Kr=0.2126f Kb=0.0722f bits=8 range=kSharpYuvRangeLimited
// Kr=0.2126f Kb=0.0722f bit_depth=8 range=kSharpYuvRangeLimited
static const SharpYuvConversionMatrix kRec709LimitedMatrix = {
{11966, 40254, 4064, 16 << 16},
{-6596, -22189, 28784, 128 << 16},
{28784, -26145, -2639, 128 << 16},
};
// Kr=0.2126f Kb=0.0722f bits=8 range=kSharpYuvRangeFull
// Kr=0.2126f Kb=0.0722f bit_depth=8 range=kSharpYuvRangeFull
static const SharpYuvConversionMatrix kRec709FullMatrix = {
{13933, 46871, 4732, 0},
{-7509, -25259, 32768, 128 << 16},

View File

@ -41,10 +41,15 @@ SHARPYUV_EXTERN void SharpYuvComputeConversionMatrix(
// Enums for precomputed conversion matrices.
typedef enum {
// WebP's matrix, similar but not identical to kSharpYuvMatrixRec601Limited
kSharpYuvMatrixWebp = 0,
// Kr=0.2990f Kb=0.1140f bit_depth=8 range=kSharpYuvRangeLimited
kSharpYuvMatrixRec601Limited,
// Kr=0.2990f Kb=0.1140f bit_depth=8 range=kSharpYuvRangeFull
kSharpYuvMatrixRec601Full,
// Kr=0.2126f Kb=0.0722f bit_depth=8 range=kSharpYuvRangeLimited
kSharpYuvMatrixRec709Limited,
// Kr=0.2126f Kb=0.0722f bit_depth=8 range=kSharpYuvRangeFull
kSharpYuvMatrixRec709Full,
kSharpYuvMatrixNum
} SharpYuvMatrixType;

View File

@ -17,6 +17,7 @@
#include <stdlib.h>
#include "sharpyuv/sharpyuv_cpu.h"
#include "src/webp/types.h"
//-----------------------------------------------------------------------------
@ -69,9 +70,9 @@ uint64_t (*SharpYuvUpdateY)(const uint16_t* src, const uint16_t* ref,
void (*SharpYuvUpdateRGB)(const int16_t* src, const int16_t* ref, int16_t* dst,
int len);
void (*SharpYuvFilterRow)(const int16_t* A, const int16_t* B, int len,
const uint16_t* best_y, uint16_t* out,
int bit_depth);
const uint16_t* best_y, uint16_t* out, int bit_depth);
extern VP8CPUInfo SharpYuvGetCPUInfo;
extern void InitSharpYuvSSE2(void);
extern void InitSharpYuvNEON(void);

View File

@ -12,6 +12,7 @@
#include "sharpyuv/sharpyuv_gamma.h"
#include <assert.h>
#include <float.h>
#include <math.h>
#include "src/webp/types.h"
@ -97,7 +98,7 @@ static WEBP_INLINE uint32_t FixedPointInterpolation(int v, uint32_t* tab,
return result;
}
uint32_t SharpYuvGammaToLinear(uint16_t v, int bit_depth) {
static uint32_t ToLinearSrgb(uint16_t v, int bit_depth) {
const int shift = GAMMA_TO_LINEAR_TAB_BITS - bit_depth;
if (shift > 0) {
return kGammaToLinearTabS[v << shift];
@ -105,9 +106,314 @@ uint32_t SharpYuvGammaToLinear(uint16_t v, int bit_depth) {
return FixedPointInterpolation(v, kGammaToLinearTabS, -shift, 0);
}
uint16_t SharpYuvLinearToGamma(uint32_t value, int bit_depth) {
static uint16_t FromLinearSrgb(uint32_t value, int bit_depth) {
return FixedPointInterpolation(
value, kLinearToGammaTabS,
(GAMMA_TO_LINEAR_BITS - LINEAR_TO_GAMMA_TAB_BITS),
bit_depth - GAMMA_TO_LINEAR_BITS);
}
////////////////////////////////////////////////////////////////////////////////
#define CLAMP(x, low, high) \
(((x) < (low)) ? (low) : (((high) < (x)) ? (high) : (x)))
#define MIN(a, b) (((a) < (b)) ? (a) : (b))
#define MAX(a, b) (((a) > (b)) ? (a) : (b))
static WEBP_INLINE float Roundf(float x) {
if (x < 0)
return (float)ceil((double)(x - 0.5f));
else
return (float)floor((double)(x + 0.5f));
}
static WEBP_INLINE float Powf(float base, float exp) {
return (float)pow((double)base, (double)exp);
}
static WEBP_INLINE float Log10f(float x) { return (float)log10((double)x); }
static float ToLinear709(float gamma) {
if (gamma < 0.f) {
return 0.f;
} else if (gamma < 4.5f * 0.018053968510807f) {
return gamma / 4.5f;
} else if (gamma < 1.f) {
return Powf((gamma + 0.09929682680944f) / 1.09929682680944f, 1.f / 0.45f);
}
return 1.f;
}
static float FromLinear709(float linear) {
if (linear < 0.f) {
return 0.f;
} else if (linear < 0.018053968510807f) {
return linear * 4.5f;
} else if (linear < 1.f) {
return 1.09929682680944f * Powf(linear, 0.45f) - 0.09929682680944f;
}
return 1.f;
}
static float ToLinear470M(float gamma) {
return Powf(CLAMP(gamma, 0.f, 1.f), 2.2f);
}
static float FromLinear470M(float linear) {
return Powf(CLAMP(linear, 0.f, 1.f), 1.f / 2.2f);
}
static float ToLinear470Bg(float gamma) {
return Powf(CLAMP(gamma, 0.f, 1.f), 2.8f);
}
static float FromLinear470Bg(float linear) {
return Powf(CLAMP(linear, 0.f, 1.f), 1.f / 2.8f);
}
static float ToLinearSmpte240(float gamma) {
if (gamma < 0.f) {
return 0.f;
} else if (gamma < 4.f * 0.022821585529445f) {
return gamma / 4.f;
} else if (gamma < 1.f) {
return Powf((gamma + 0.111572195921731f) / 1.111572195921731f, 1.f / 0.45f);
}
return 1.f;
}
static float FromLinearSmpte240(float linear) {
if (linear < 0.f) {
return 0.f;
} else if (linear < 0.022821585529445f) {
return linear * 4.f;
} else if (linear < 1.f) {
return 1.111572195921731f * Powf(linear, 0.45f) - 0.111572195921731f;
}
return 1.f;
}
static float ToLinearLog100(float gamma) {
// The function is non-bijective so choose the middle of [0, 0.01].
const float mid_interval = 0.01f / 2.f;
return (gamma <= 0.0f) ? mid_interval
: Powf(10.0f, 2.f * (MIN(gamma, 1.f) - 1.0f));
}
static float FromLinearLog100(float linear) {
return (linear < 0.01f) ? 0.0f : 1.0f + Log10f(MIN(linear, 1.f)) / 2.0f;
}
static float ToLinearLog100Sqrt10(float gamma) {
// The function is non-bijective so choose the middle of [0, 0.00316227766f[.
const float mid_interval = 0.00316227766f / 2.f;
return (gamma <= 0.0f) ? mid_interval
: Powf(10.0f, 2.5f * (MIN(gamma, 1.f) - 1.0f));
}
static float FromLinearLog100Sqrt10(float linear) {
return (linear < 0.00316227766f) ? 0.0f
: 1.0f + Log10f(MIN(linear, 1.f)) / 2.5f;
}
static float ToLinearIec61966(float gamma) {
if (gamma <= -4.5f * 0.018053968510807f) {
return Powf((-gamma + 0.09929682680944f) / -1.09929682680944f, 1.f / 0.45f);
} else if (gamma < 4.5f * 0.018053968510807f) {
return gamma / 4.5f;
}
return Powf((gamma + 0.09929682680944f) / 1.09929682680944f, 1.f / 0.45f);
}
static float FromLinearIec61966(float linear) {
if (linear <= -0.018053968510807f) {
return -1.09929682680944f * Powf(-linear, 0.45f) + 0.09929682680944f;
} else if (linear < 0.018053968510807f) {
return linear * 4.5f;
}
return 1.09929682680944f * Powf(linear, 0.45f) - 0.09929682680944f;
}
static float ToLinearBt1361(float gamma) {
if (gamma < -0.25f) {
return -0.25f;
} else if (gamma < 0.f) {
return Powf((gamma - 0.02482420670236f) / -0.27482420670236f, 1.f / 0.45f) /
-4.f;
} else if (gamma < 4.5f * 0.018053968510807f) {
return gamma / 4.5f;
} else if (gamma < 1.f) {
return Powf((gamma + 0.09929682680944f) / 1.09929682680944f, 1.f / 0.45f);
}
return 1.f;
}
static float FromLinearBt1361(float linear) {
if (linear < -0.25f) {
return -0.25f;
} else if (linear < 0.f) {
return -0.27482420670236f * Powf(-4.f * linear, 0.45f) + 0.02482420670236f;
} else if (linear < 0.018053968510807f) {
return linear * 4.5f;
} else if (linear < 1.f) {
return 1.09929682680944f * Powf(linear, 0.45f) - 0.09929682680944f;
}
return 1.f;
}
static float ToLinearPq(float gamma) {
if (gamma > 0.f) {
const float pow_gamma = Powf(gamma, 32.f / 2523.f);
const float num = MAX(pow_gamma - 107.f / 128.f, 0.0f);
const float den = MAX(2413.f / 128.f - 2392.f / 128.f * pow_gamma, FLT_MIN);
return Powf(num / den, 4096.f / 653.f);
}
return 0.f;
}
static float FromLinearPq(float linear) {
if (linear > 0.f) {
const float pow_linear = Powf(linear, 653.f / 4096.f);
const float num = 107.f / 128.f + 2413.f / 128.f * pow_linear;
const float den = 1.0f + 2392.f / 128.f * pow_linear;
return Powf(num / den, 2523.f / 32.f);
}
return 0.f;
}
static float ToLinearSmpte428(float gamma) {
return Powf(MAX(gamma, 0.f), 2.6f) / 0.91655527974030934f;
}
static float FromLinearSmpte428(float linear) {
return Powf(0.91655527974030934f * MAX(linear, 0.f), 1.f / 2.6f);
}
// Conversion in BT.2100 requires RGB info. Simplify to gamma correction here.
static float ToLinearHlg(float gamma) {
if (gamma < 0.f) {
return 0.f;
} else if (gamma <= 0.5f) {
return Powf((gamma * gamma) * (1.f / 3.f), 1.2f);
}
return Powf((expf((gamma - 0.55991073f) / 0.17883277f) + 0.28466892f) / 12.0f,
1.2f);
}
static float FromLinearHlg(float linear) {
linear = Powf(linear, 1.f / 1.2f);
if (linear < 0.f) {
return 0.f;
} else if (linear <= (1.f / 12.f)) {
return sqrtf(3.f * linear);
}
return 0.17883277f * logf(12.f * linear - 0.28466892f) + 0.55991073f;
}
uint32_t SharpYuvGammaToLinear(uint16_t v, int bit_depth,
SharpYuvTransferFunctionType transfer_type) {
float v_float, linear;
if (transfer_type == kSharpYuvTransferFunctionSrgb) {
return ToLinearSrgb(v, bit_depth);
}
v_float = (float)v / ((1 << bit_depth) - 1);
switch (transfer_type) {
case kSharpYuvTransferFunctionBt709:
case kSharpYuvTransferFunctionBt601:
case kSharpYuvTransferFunctionBt2020_10Bit:
case kSharpYuvTransferFunctionBt2020_12Bit:
linear = ToLinear709(v_float);
break;
case kSharpYuvTransferFunctionBt470M:
linear = ToLinear470M(v_float);
break;
case kSharpYuvTransferFunctionBt470Bg:
linear = ToLinear470Bg(v_float);
break;
case kSharpYuvTransferFunctionSmpte240:
linear = ToLinearSmpte240(v_float);
break;
case kSharpYuvTransferFunctionLinear:
return v;
case kSharpYuvTransferFunctionLog100:
linear = ToLinearLog100(v_float);
break;
case kSharpYuvTransferFunctionLog100_Sqrt10:
linear = ToLinearLog100Sqrt10(v_float);
break;
case kSharpYuvTransferFunctionIec61966:
linear = ToLinearIec61966(v_float);
break;
case kSharpYuvTransferFunctionBt1361:
linear = ToLinearBt1361(v_float);
break;
case kSharpYuvTransferFunctionSmpte2084:
linear = ToLinearPq(v_float);
break;
case kSharpYuvTransferFunctionSmpte428:
linear = ToLinearSmpte428(v_float);
break;
case kSharpYuvTransferFunctionHlg:
linear = ToLinearHlg(v_float);
break;
default:
assert(0);
linear = 0;
break;
}
return (uint32_t)Roundf(linear * ((1 << 16) - 1));
}
uint16_t SharpYuvLinearToGamma(uint32_t v, int bit_depth,
SharpYuvTransferFunctionType transfer_type) {
float v_float, linear;
if (transfer_type == kSharpYuvTransferFunctionSrgb) {
return FromLinearSrgb(v, bit_depth);
}
v_float = (float)v / ((1 << 16) - 1);
switch (transfer_type) {
case kSharpYuvTransferFunctionBt709:
case kSharpYuvTransferFunctionBt601:
case kSharpYuvTransferFunctionBt2020_10Bit:
case kSharpYuvTransferFunctionBt2020_12Bit:
linear = FromLinear709(v_float);
break;
case kSharpYuvTransferFunctionBt470M:
linear = FromLinear470M(v_float);
break;
case kSharpYuvTransferFunctionBt470Bg:
linear = FromLinear470Bg(v_float);
break;
case kSharpYuvTransferFunctionSmpte240:
linear = FromLinearSmpte240(v_float);
break;
case kSharpYuvTransferFunctionLinear:
return v;
case kSharpYuvTransferFunctionLog100:
linear = FromLinearLog100(v_float);
break;
case kSharpYuvTransferFunctionLog100_Sqrt10:
linear = FromLinearLog100Sqrt10(v_float);
break;
case kSharpYuvTransferFunctionIec61966:
linear = FromLinearIec61966(v_float);
break;
case kSharpYuvTransferFunctionBt1361:
linear = FromLinearBt1361(v_float);
break;
case kSharpYuvTransferFunctionSmpte2084:
linear = FromLinearPq(v_float);
break;
case kSharpYuvTransferFunctionSmpte428:
linear = FromLinearSmpte428(v_float);
break;
case kSharpYuvTransferFunctionHlg:
linear = FromLinearHlg(v_float);
break;
default:
assert(0);
linear = 0;
break;
}
return (uint16_t)Roundf(linear * ((1 << bit_depth) - 1));
}

View File

@ -12,6 +12,7 @@
#ifndef WEBP_SHARPYUV_SHARPYUV_GAMMA_H_
#define WEBP_SHARPYUV_SHARPYUV_GAMMA_H_
#include "sharpyuv/sharpyuv.h"
#include "src/webp/types.h"
#ifdef __cplusplus
@ -22,11 +23,13 @@ extern "C" {
// SharpYuvGammaToLinear or SharpYuvLinearToGamma.
void SharpYuvInitGammaTables(void);
// Converts a gamma color value on 'bit_depth' bits to a 16 bit linear value.
uint32_t SharpYuvGammaToLinear(uint16_t v, int bit_depth);
// Converts a 'bit_depth'-bit gamma color value to a 16-bit linear value.
uint32_t SharpYuvGammaToLinear(uint16_t v, int bit_depth,
SharpYuvTransferFunctionType transfer_type);
// Converts a 16 bit linear color value to a gamma value on 'bit_depth' bits.
uint16_t SharpYuvLinearToGamma(uint32_t value, int bit_depth);
// Converts a 16-bit linear color value to a 'bit_depth'-bit gamma value.
uint16_t SharpYuvLinearToGamma(uint32_t value, int bit_depth,
SharpYuvTransferFunctionType transfer_type);
#ifdef __cplusplus
} // extern "C"

View File

@ -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
# not have unresolved symbols. Some platforms (Windows among them) require all
# symbols in shared libraries to be resolved at library creation.
libwebp_la_LDFLAGS = -no-undefined -version-info 8:6:1
libwebp_la_LDFLAGS = -no-undefined -version-info 8:10:1
libwebpincludedir = $(includedir)/webp
pkgconfig_DATA = libwebp.pc
@ -48,7 +48,7 @@ if BUILD_LIBWEBPDECODER
libwebpdecoder_la_LIBADD += dsp/libwebpdspdecode.la
libwebpdecoder_la_LIBADD += utils/libwebputilsdecode.la
libwebpdecoder_la_LDFLAGS = -no-undefined -version-info 4:6:1
libwebpdecoder_la_LDFLAGS = -no-undefined -version-info 4:10:1
pkgconfig_DATA += libwebpdecoder.pc
endif

View File

@ -13,18 +13,20 @@
#include <stdlib.h>
#include "src/dec/alphai_dec.h"
#include "src/dec/vp8_dec.h"
#include "src/dec/vp8i_dec.h"
#include "src/dec/vp8li_dec.h"
#include "src/dsp/dsp.h"
#include "src/utils/quant_levels_dec_utils.h"
#include "src/utils/utils.h"
#include "src/webp/format_constants.h"
#include "src/webp/types.h"
//------------------------------------------------------------------------------
// ALPHDecoder object.
// Allocates a new alpha decoder instance.
static ALPHDecoder* ALPHNew(void) {
WEBP_NODISCARD static ALPHDecoder* ALPHNew(void) {
ALPHDecoder* const dec = (ALPHDecoder*)WebPSafeCalloc(1ULL, sizeof(*dec));
return dec;
}
@ -45,9 +47,9 @@ static void ALPHDelete(ALPHDecoder* const dec) {
// header for alpha data stored using lossless compression.
// Returns false in case of error in alpha header (data too short, invalid
// compression method or filter, error in lossless header data etc).
static int ALPHInit(ALPHDecoder* const dec, const uint8_t* data,
size_t data_size, const VP8Io* const src_io,
uint8_t* output) {
WEBP_NODISCARD static int ALPHInit(ALPHDecoder* const dec, const uint8_t* data,
size_t data_size, const VP8Io* const src_io,
uint8_t* output) {
int ok = 0;
const uint8_t* const alpha_data = data + ALPHA_HEADER_LEN;
const size_t alpha_data_size = data_size - ALPHA_HEADER_LEN;
@ -79,7 +81,9 @@ static int ALPHInit(ALPHDecoder* const dec, const uint8_t* data,
}
// Copy the necessary parameters from src_io to io
VP8InitIo(io);
if (!VP8InitIo(io)) {
return 0;
}
WebPInitCustomIo(NULL, io);
io->opaque = dec;
io->width = src_io->width;
@ -107,7 +111,8 @@ static int ALPHInit(ALPHDecoder* const dec, const uint8_t* data,
// starting from row number 'row'. It assumes that rows up to (row - 1) have
// already been decoded.
// Returns false in case of bitstream error.
static int ALPHDecode(VP8Decoder* const dec, int row, int num_rows) {
WEBP_NODISCARD static int ALPHDecode(VP8Decoder* const dec, int row,
int num_rows) {
ALPHDecoder* const alph_dec = dec->alph_dec_;
const int width = alph_dec->width_;
const int height = alph_dec->io_.crop_bottom;
@ -117,21 +122,12 @@ static int ALPHDecode(VP8Decoder* const dec, int row, int num_rows) {
const uint8_t* deltas = dec->alpha_data_ + ALPHA_HEADER_LEN + row * width;
uint8_t* dst = dec->alpha_plane_ + row * width;
assert(deltas <= &dec->alpha_data_[dec->alpha_data_size_]);
if (alph_dec->filter_ != WEBP_FILTER_NONE) {
assert(WebPUnfilters[alph_dec->filter_] != NULL);
for (y = 0; y < num_rows; ++y) {
WebPUnfilters[alph_dec->filter_](prev_line, deltas, dst, width);
prev_line = dst;
dst += width;
deltas += width;
}
} else {
for (y = 0; y < num_rows; ++y) {
memcpy(dst, deltas, width * sizeof(*dst));
prev_line = dst;
dst += width;
deltas += width;
}
assert(WebPUnfilters[alph_dec->filter_] != NULL);
for (y = 0; y < num_rows; ++y) {
WebPUnfilters[alph_dec->filter_](prev_line, deltas, dst, width);
prev_line = dst;
dst += width;
deltas += width;
}
dec->alpha_prev_line_ = prev_line;
} else { // alph_dec->method_ == ALPHA_LOSSLESS_COMPRESSION
@ -147,7 +143,8 @@ static int ALPHDecode(VP8Decoder* const dec, int row, int num_rows) {
return 1;
}
static int AllocateAlphaPlane(VP8Decoder* const dec, const VP8Io* const io) {
WEBP_NODISCARD static int AllocateAlphaPlane(VP8Decoder* const dec,
const VP8Io* const io) {
const int stride = io->width;
const int height = io->crop_bottom;
const uint64_t alpha_size = (uint64_t)stride * height;
@ -155,7 +152,8 @@ static int AllocateAlphaPlane(VP8Decoder* const dec, const VP8Io* const io) {
dec->alpha_plane_mem_ =
(uint8_t*)WebPSafeMalloc(alpha_size, sizeof(*dec->alpha_plane_));
if (dec->alpha_plane_mem_ == NULL) {
return 0;
return VP8SetError(dec, VP8_STATUS_OUT_OF_MEMORY,
"Alpha decoder initialization failed.");
}
dec->alpha_plane_ = dec->alpha_plane_mem_;
dec->alpha_prev_line_ = NULL;
@ -174,9 +172,9 @@ void WebPDeallocateAlphaMemory(VP8Decoder* const dec) {
//------------------------------------------------------------------------------
// Main entry point.
const uint8_t* VP8DecompressAlphaRows(VP8Decoder* const dec,
const VP8Io* const io,
int row, int num_rows) {
WEBP_NODISCARD const uint8_t* VP8DecompressAlphaRows(VP8Decoder* const dec,
const VP8Io* const io,
int row, int num_rows) {
const int width = io->width;
const int height = io->crop_bottom;
@ -189,10 +187,19 @@ const uint8_t* VP8DecompressAlphaRows(VP8Decoder* const dec,
if (!dec->is_alpha_decoded_) {
if (dec->alph_dec_ == NULL) { // Initialize decoder.
dec->alph_dec_ = ALPHNew();
if (dec->alph_dec_ == NULL) return NULL;
if (dec->alph_dec_ == NULL) {
VP8SetError(dec, VP8_STATUS_OUT_OF_MEMORY,
"Alpha decoder initialization failed.");
return NULL;
}
if (!AllocateAlphaPlane(dec, io)) goto Error;
if (!ALPHInit(dec->alph_dec_, dec->alpha_data_, dec->alpha_data_size_,
io, dec->alpha_plane_)) {
VP8LDecoder* const vp8l_dec = dec->alph_dec_->vp8l_dec_;
VP8SetError(dec,
(vp8l_dec == NULL) ? VP8_STATUS_OUT_OF_MEMORY
: vp8l_dec->status_,
"Alpha decoder initialization failed.");
goto Error;
}
// if we allowed use of alpha dithering, check whether it's needed at all

View File

@ -26,10 +26,9 @@ static const uint8_t kModeBpp[MODE_LAST] = {
4, 4, 4, 2, // pre-multiplied modes
1, 1 };
// Check that webp_csp_mode is within the bounds of WEBP_CSP_MODE.
// Convert to an integer to handle both the unsigned/signed enum cases
// without the need for casting to remove type limit warnings.
static int IsValidColorspace(int webp_csp_mode) {
int IsValidColorspace(int webp_csp_mode) {
return (webp_csp_mode >= MODE_RGB && webp_csp_mode < MODE_LAST);
}
@ -75,7 +74,7 @@ static VP8StatusCode CheckDecBuffer(const WebPDecBuffer* const buffer) {
const WebPRGBABuffer* const buf = &buffer->u.RGBA;
const int stride = abs(buf->stride);
const uint64_t size =
MIN_BUFFER_SIZE(width * kModeBpp[mode], height, stride);
MIN_BUFFER_SIZE((uint64_t)width * kModeBpp[mode], height, stride);
ok &= (size <= buf->size);
ok &= (stride >= width * kModeBpp[mode]);
ok &= (buf->rgba != NULL);

View File

@ -51,4 +51,7 @@ enum { MB_FEATURE_TREE_PROBS = 3,
NUM_PROBAS = 11
};
// Check that webp_csp_mode is within the bounds of WEBP_CSP_MODE.
int IsValidColorspace(int webp_csp_mode);
#endif // WEBP_DEC_COMMON_DEC_H_

View File

@ -17,8 +17,10 @@
#include "src/dec/alphai_dec.h"
#include "src/dec/webpi_dec.h"
#include "src/dec/vp8_dec.h"
#include "src/dec/vp8i_dec.h"
#include "src/utils/utils.h"
#include "src/webp/decode.h"
// In append mode, buffer allocations increase as multiples of this value.
// Needs to be a power of 2.
@ -161,8 +163,9 @@ static void DoRemap(WebPIDecoder* const idec, ptrdiff_t offset) {
// Appends data to the end of MemBuffer->buf_. It expands the allocated memory
// size if required and also updates VP8BitReader's if new memory is allocated.
static int AppendToMemBuffer(WebPIDecoder* const idec,
const uint8_t* const data, size_t data_size) {
WEBP_NODISCARD static int AppendToMemBuffer(WebPIDecoder* const idec,
const uint8_t* const data,
size_t data_size) {
VP8Decoder* const dec = (VP8Decoder*)idec->dec_;
MemBuffer* const mem = &idec->mem_;
const int need_compressed_alpha = NeedCompressedAlpha(idec);
@ -203,8 +206,9 @@ static int AppendToMemBuffer(WebPIDecoder* const idec,
return 1;
}
static int RemapMemBuffer(WebPIDecoder* const idec,
const uint8_t* const data, size_t data_size) {
WEBP_NODISCARD static int RemapMemBuffer(WebPIDecoder* const idec,
const uint8_t* const data,
size_t data_size) {
MemBuffer* const mem = &idec->mem_;
const uint8_t* const old_buf = mem->buf_;
const uint8_t* const old_start =
@ -237,7 +241,8 @@ static void ClearMemBuffer(MemBuffer* const mem) {
}
}
static int CheckMemBufferMode(MemBuffer* const mem, MemBufferMode expected) {
WEBP_NODISCARD static int CheckMemBufferMode(MemBuffer* const mem,
MemBufferMode expected) {
if (mem->mode_ == MEM_MODE_NONE) {
mem->mode_ = expected; // switch to the expected mode
} else if (mem->mode_ != expected) {
@ -248,7 +253,7 @@ static int CheckMemBufferMode(MemBuffer* const mem, MemBufferMode expected) {
}
// To be called last.
static VP8StatusCode FinishDecoding(WebPIDecoder* const idec) {
WEBP_NODISCARD static VP8StatusCode FinishDecoding(WebPIDecoder* const idec) {
const WebPDecoderOptions* const options = idec->params_.options;
WebPDecBuffer* const output = idec->params_.output;
@ -258,8 +263,10 @@ static VP8StatusCode FinishDecoding(WebPIDecoder* const idec) {
if (status != VP8_STATUS_OK) return status;
}
if (idec->final_output_ != NULL) {
WebPCopyDecBufferPixels(output, idec->final_output_); // do the slow-copy
const VP8StatusCode status = WebPCopyDecBufferPixels(
output, idec->final_output_); // do the slow-copy
WebPFreeDecBuffer(&idec->output_);
if (status != VP8_STATUS_OK) return status;
*output = *idec->final_output_;
idec->final_output_ = NULL;
}
@ -288,7 +295,7 @@ static void RestoreContext(const MBContext* context, VP8Decoder* const dec,
static VP8StatusCode IDecError(WebPIDecoder* const idec, VP8StatusCode error) {
if (idec->state_ == STATE_VP8_DATA) {
// Synchronize the thread, clean-up and check for errors.
VP8ExitCritical((VP8Decoder*)idec->dec_, &idec->io_);
(void)VP8ExitCritical((VP8Decoder*)idec->dec_, &idec->io_);
}
idec->state_ = STATE_ERROR;
return error;
@ -329,6 +336,7 @@ static VP8StatusCode DecodeWebPHeaders(WebPIDecoder* const idec) {
if (dec == NULL) {
return VP8_STATUS_OUT_OF_MEMORY;
}
dec->incremental_ = 1;
idec->dec_ = dec;
dec->alpha_data_ = headers.alpha_data;
dec->alpha_data_size_ = headers.alpha_data_size;
@ -601,8 +609,9 @@ static VP8StatusCode IDecode(WebPIDecoder* idec) {
//------------------------------------------------------------------------------
// Internal constructor
static WebPIDecoder* NewDecoder(WebPDecBuffer* const output_buffer,
const WebPBitstreamFeatures* const features) {
WEBP_NODISCARD static WebPIDecoder* NewDecoder(
WebPDecBuffer* const output_buffer,
const WebPBitstreamFeatures* const features) {
WebPIDecoder* idec = (WebPIDecoder*)WebPSafeCalloc(1ULL, sizeof(*idec));
if (idec == NULL) {
return NULL;
@ -614,8 +623,10 @@ static WebPIDecoder* NewDecoder(WebPDecBuffer* const output_buffer,
idec->last_mb_y_ = -1;
InitMemBuffer(&idec->mem_);
WebPInitDecBuffer(&idec->output_);
VP8InitIo(&idec->io_);
if (!WebPInitDecBuffer(&idec->output_) || !VP8InitIo(&idec->io_)) {
WebPSafeFree(idec);
return NULL;
}
WebPResetDecParams(&idec->params_);
if (output_buffer == NULL || WebPAvoidSlowMemory(output_buffer, features)) {
@ -674,7 +685,8 @@ void WebPIDelete(WebPIDecoder* idec) {
if (!idec->is_lossless_) {
if (idec->state_ == STATE_VP8_DATA) {
// Synchronize the thread, clean-up and check for errors.
VP8ExitCritical((VP8Decoder*)idec->dec_, &idec->io_);
// TODO(vrabaud) do we care about the return result?
(void)VP8ExitCritical((VP8Decoder*)idec->dec_, &idec->io_);
}
VP8Delete((VP8Decoder*)idec->dec_);
} else {
@ -851,8 +863,8 @@ const WebPDecBuffer* WebPIDecodedArea(const WebPIDecoder* idec,
return src;
}
uint8_t* WebPIDecGetRGB(const WebPIDecoder* idec, int* last_y,
int* width, int* height, int* stride) {
WEBP_NODISCARD uint8_t* WebPIDecGetRGB(const WebPIDecoder* idec, int* last_y,
int* width, int* height, int* stride) {
const WebPDecBuffer* const src = GetOutputBuffer(idec);
if (src == NULL) return NULL;
if (src->colorspace >= MODE_YUV) {
@ -867,10 +879,10 @@ uint8_t* WebPIDecGetRGB(const WebPIDecoder* idec, int* last_y,
return src->u.RGBA.rgba;
}
uint8_t* WebPIDecGetYUVA(const WebPIDecoder* idec, int* last_y,
uint8_t** u, uint8_t** v, uint8_t** a,
int* width, int* height,
int* stride, int* uv_stride, int* a_stride) {
WEBP_NODISCARD uint8_t* WebPIDecGetYUVA(const WebPIDecoder* idec, int* last_y,
uint8_t** u, uint8_t** v, uint8_t** a,
int* width, int* height, int* stride,
int* uv_stride, int* a_stride) {
const WebPDecBuffer* const src = GetOutputBuffer(idec);
if (src == NULL) return NULL;
if (src->colorspace < MODE_YUV) {

View File

@ -12,7 +12,9 @@
// Author: Skal (pascal.massimino@gmail.com)
#include <assert.h>
#include <stddef.h>
#include <stdlib.h>
#include "src/dec/vp8i_dec.h"
#include "src/dec/webpi_dec.h"
#include "src/dsp/dsp.h"
@ -25,9 +27,9 @@
static int EmitYUV(const VP8Io* const io, WebPDecParams* const p) {
WebPDecBuffer* output = p->output;
const WebPYUVABuffer* const buf = &output->u.YUVA;
uint8_t* const y_dst = buf->y + (size_t)io->mb_y * buf->y_stride;
uint8_t* const u_dst = buf->u + (size_t)(io->mb_y >> 1) * buf->u_stride;
uint8_t* const v_dst = buf->v + (size_t)(io->mb_y >> 1) * buf->v_stride;
uint8_t* const y_dst = buf->y + (ptrdiff_t)io->mb_y * buf->y_stride;
uint8_t* const u_dst = buf->u + (ptrdiff_t)(io->mb_y >> 1) * buf->u_stride;
uint8_t* const v_dst = buf->v + (ptrdiff_t)(io->mb_y >> 1) * buf->v_stride;
const int mb_w = io->mb_w;
const int mb_h = io->mb_h;
const int uv_w = (mb_w + 1) / 2;
@ -42,7 +44,7 @@ static int EmitYUV(const VP8Io* const io, WebPDecParams* const p) {
static int EmitSampledRGB(const VP8Io* const io, WebPDecParams* const p) {
WebPDecBuffer* const output = p->output;
WebPRGBABuffer* const buf = &output->u.RGBA;
uint8_t* const dst = buf->rgba + (size_t)io->mb_y * buf->stride;
uint8_t* const dst = buf->rgba + (ptrdiff_t)io->mb_y * buf->stride;
WebPSamplerProcessPlane(io->y, io->y_stride,
io->u, io->v, io->uv_stride,
dst, buf->stride, io->mb_w, io->mb_h,
@ -57,7 +59,7 @@ static int EmitSampledRGB(const VP8Io* const io, WebPDecParams* const p) {
static int EmitFancyRGB(const VP8Io* const io, WebPDecParams* const p) {
int num_lines_out = io->mb_h; // a priori guess
const WebPRGBABuffer* const buf = &p->output->u.RGBA;
uint8_t* dst = buf->rgba + (size_t)io->mb_y * buf->stride;
uint8_t* dst = buf->rgba + (ptrdiff_t)io->mb_y * buf->stride;
WebPUpsampleLinePairFunc upsample = WebPUpsamplers[p->output->colorspace];
const uint8_t* cur_y = io->y;
const uint8_t* cur_u = io->u;
@ -128,7 +130,7 @@ static int EmitAlphaYUV(const VP8Io* const io, WebPDecParams* const p,
const WebPYUVABuffer* const buf = &p->output->u.YUVA;
const int mb_w = io->mb_w;
const int mb_h = io->mb_h;
uint8_t* dst = buf->a + (size_t)io->mb_y * buf->a_stride;
uint8_t* dst = buf->a + (ptrdiff_t)io->mb_y * buf->a_stride;
int j;
(void)expected_num_lines_out;
assert(expected_num_lines_out == mb_h);
@ -181,8 +183,8 @@ static int EmitAlphaRGB(const VP8Io* const io, WebPDecParams* const p,
(colorspace == MODE_ARGB || colorspace == MODE_Argb);
const WebPRGBABuffer* const buf = &p->output->u.RGBA;
int num_rows;
const size_t start_y = GetAlphaSourceRow(io, &alpha, &num_rows);
uint8_t* const base_rgba = buf->rgba + start_y * buf->stride;
const int start_y = GetAlphaSourceRow(io, &alpha, &num_rows);
uint8_t* const base_rgba = buf->rgba + (ptrdiff_t)start_y * buf->stride;
uint8_t* const dst = base_rgba + (alpha_first ? 0 : 3);
const int has_alpha = WebPDispatchAlpha(alpha, io->width, mb_w,
num_rows, dst, buf->stride);
@ -205,8 +207,8 @@ static int EmitAlphaRGBA4444(const VP8Io* const io, WebPDecParams* const p,
const WEBP_CSP_MODE colorspace = p->output->colorspace;
const WebPRGBABuffer* const buf = &p->output->u.RGBA;
int num_rows;
const size_t start_y = GetAlphaSourceRow(io, &alpha, &num_rows);
uint8_t* const base_rgba = buf->rgba + start_y * buf->stride;
const int start_y = GetAlphaSourceRow(io, &alpha, &num_rows);
uint8_t* const base_rgba = buf->rgba + (ptrdiff_t)start_y * buf->stride;
#if (WEBP_SWAP_16BIT_CSP == 1)
uint8_t* alpha_dst = base_rgba;
#else
@ -271,9 +273,9 @@ static int EmitRescaledYUV(const VP8Io* const io, WebPDecParams* const p) {
static int EmitRescaledAlphaYUV(const VP8Io* const io, WebPDecParams* const p,
int expected_num_lines_out) {
const WebPYUVABuffer* const buf = &p->output->u.YUVA;
uint8_t* const dst_a = buf->a + (size_t)p->last_y * buf->a_stride;
uint8_t* const dst_a = buf->a + (ptrdiff_t)p->last_y * buf->a_stride;
if (io->a != NULL) {
uint8_t* const dst_y = buf->y + (size_t)p->last_y * buf->y_stride;
uint8_t* const dst_y = buf->y + (ptrdiff_t)p->last_y * buf->y_stride;
const int num_lines_out = Rescale(io->a, io->width, io->mb_h, p->scaler_a);
assert(expected_num_lines_out == num_lines_out);
if (num_lines_out > 0) { // unmultiply the Y
@ -362,7 +364,7 @@ static int ExportRGB(WebPDecParams* const p, int y_pos) {
const WebPYUV444Converter convert =
WebPYUV444Converters[p->output->colorspace];
const WebPRGBABuffer* const buf = &p->output->u.RGBA;
uint8_t* dst = buf->rgba + (size_t)y_pos * buf->stride;
uint8_t* dst = buf->rgba + (ptrdiff_t)y_pos * buf->stride;
int num_lines_out = 0;
// For RGB rescaling, because of the YUV420, current scan position
// U/V can be +1/-1 line from the Y one. Hence the double test.
@ -389,14 +391,14 @@ static int EmitRescaledRGB(const VP8Io* const io, WebPDecParams* const p) {
while (j < mb_h) {
const int y_lines_in =
WebPRescalerImport(p->scaler_y, mb_h - j,
io->y + (size_t)j * io->y_stride, io->y_stride);
io->y + (ptrdiff_t)j * io->y_stride, io->y_stride);
j += y_lines_in;
if (WebPRescaleNeededLines(p->scaler_u, uv_mb_h - uv_j)) {
const int u_lines_in = WebPRescalerImport(
p->scaler_u, uv_mb_h - uv_j, io->u + (size_t)uv_j * io->uv_stride,
p->scaler_u, uv_mb_h - uv_j, io->u + (ptrdiff_t)uv_j * io->uv_stride,
io->uv_stride);
const int v_lines_in = WebPRescalerImport(
p->scaler_v, uv_mb_h - uv_j, io->v + (size_t)uv_j * io->uv_stride,
p->scaler_v, uv_mb_h - uv_j, io->v + (ptrdiff_t)uv_j * io->uv_stride,
io->uv_stride);
(void)v_lines_in; // remove a gcc warning
assert(u_lines_in == v_lines_in);
@ -409,7 +411,7 @@ static int EmitRescaledRGB(const VP8Io* const io, WebPDecParams* const p) {
static int ExportAlpha(WebPDecParams* const p, int y_pos, int max_lines_out) {
const WebPRGBABuffer* const buf = &p->output->u.RGBA;
uint8_t* const base_rgba = buf->rgba + (size_t)y_pos * buf->stride;
uint8_t* const base_rgba = buf->rgba + (ptrdiff_t)y_pos * buf->stride;
const WEBP_CSP_MODE colorspace = p->output->colorspace;
const int alpha_first =
(colorspace == MODE_ARGB || colorspace == MODE_Argb);
@ -437,7 +439,7 @@ static int ExportAlpha(WebPDecParams* const p, int y_pos, int max_lines_out) {
static int ExportAlphaRGBA4444(WebPDecParams* const p, int y_pos,
int max_lines_out) {
const WebPRGBABuffer* const buf = &p->output->u.RGBA;
uint8_t* const base_rgba = buf->rgba + (size_t)y_pos * buf->stride;
uint8_t* const base_rgba = buf->rgba + (ptrdiff_t)y_pos * buf->stride;
#if (WEBP_SWAP_16BIT_CSP == 1)
uint8_t* alpha_dst = base_rgba;
#else
@ -476,7 +478,7 @@ static int EmitRescaledAlphaRGB(const VP8Io* const io, WebPDecParams* const p,
int lines_left = expected_num_out_lines;
const int y_end = p->last_y + lines_left;
while (lines_left > 0) {
const int64_t row_offset = (int64_t)scaler->src_y - io->mb_y;
const int64_t row_offset = (ptrdiff_t)scaler->src_y - io->mb_y;
WebPRescalerImport(scaler, io->mb_h + io->mb_y - scaler->src_y,
io->a + row_offset * io->width, io->width);
lines_left -= p->emit_alpha_row(p, y_end - lines_left, lines_left);

View File

@ -12,10 +12,12 @@
// Author: Skal (pascal.massimino@gmail.com)
#include "src/dec/vp8i_dec.h"
#include "src/dsp/cpu.h"
#include "src/utils/bit_reader_inl_utils.h"
#if !defined(USE_GENERIC_TREE)
#if !defined(__arm__) && !defined(_M_ARM) && !defined(__aarch64__)
#if !defined(__arm__) && !defined(_M_ARM) && !WEBP_AARCH64 && \
!defined(__wasm__)
// using a table is ~1-2% slower on ARM. Prefer the coded-tree approach then.
#define USE_GENERIC_TREE 1 // ALTERNATE_CODE
#else

View File

@ -86,6 +86,8 @@ void VP8Delete(VP8Decoder* const dec) {
int VP8SetError(VP8Decoder* const dec,
VP8StatusCode error, const char* const msg) {
// VP8_STATUS_SUSPENDED is only meaningful in incremental decoding.
assert(dec->incremental_ || error != VP8_STATUS_SUSPENDED);
// The oldest error reported takes precedence over the new one.
if (dec->status_ == VP8_STATUS_OK) {
dec->status_ = error;
@ -190,12 +192,12 @@ static int ParseSegmentHeader(VP8BitReader* br,
}
// Paragraph 9.5
// This function returns VP8_STATUS_SUSPENDED if we don't have all the
// necessary data in 'buf'.
// This case is not necessarily an error (for incremental decoding).
// Still, no bitreader is ever initialized to make it possible to read
// unavailable memory.
// If we don't even have the partitions' sizes, than VP8_STATUS_NOT_ENOUGH_DATA
// If we don't have all the necessary data in 'buf', this function returns
// VP8_STATUS_SUSPENDED in incremental decoding, VP8_STATUS_NOT_ENOUGH_DATA
// otherwise.
// In incremental decoding, this case is not necessarily an error. Still, no
// bitreader is ever initialized to make it possible to read unavailable memory.
// If we don't even have the partitions' sizes, then VP8_STATUS_NOT_ENOUGH_DATA
// is returned, and this is an unrecoverable error.
// If the partitions were positioned ok, VP8_STATUS_OK is returned.
static VP8StatusCode ParsePartitions(VP8Decoder* const dec,
@ -225,8 +227,10 @@ static VP8StatusCode ParsePartitions(VP8Decoder* const dec,
sz += 3;
}
VP8InitBitReader(dec->parts_ + last_part, part_start, size_left);
return (part_start < buf_end) ? VP8_STATUS_OK :
VP8_STATUS_SUSPENDED; // Init is ok, but there's not enough data
if (part_start < buf_end) return VP8_STATUS_OK;
return dec->incremental_
? VP8_STATUS_SUSPENDED // Init is ok, but there's not enough data
: VP8_STATUS_NOT_ENOUGH_DATA;
}
// Paragraph 9.4
@ -494,6 +498,8 @@ static int GetCoeffsAlt(VP8BitReader* const br,
return 16;
}
extern VP8CPUInfo VP8GetCPUInfo;
WEBP_DSP_INIT_FUNC(InitGetCoeffs) {
if (VP8GetCPUInfo != NULL && VP8GetCPUInfo(kSlowSSSE3)) {
GetCoeffs = GetCoeffsAlt;

View File

@ -15,6 +15,7 @@
#define WEBP_DEC_VP8_DEC_H_
#include "src/webp/decode.h"
#include "src/webp/types.h"
#ifdef __cplusplus
extern "C" {
@ -108,16 +109,14 @@ struct VP8Io {
};
// Internal, version-checked, entry point
int VP8InitIoInternal(VP8Io* const, int);
WEBP_NODISCARD int VP8InitIoInternal(VP8Io* const, int);
// Set the custom IO function pointers and user-data. The setter for IO hooks
// should be called before initiating incremental decoding. Returns true if
// WebPIDecoder object is successfully modified, false otherwise.
int WebPISetIOHooks(WebPIDecoder* const idec,
VP8IoPutHook put,
VP8IoSetupHook setup,
VP8IoTeardownHook teardown,
void* user_data);
WEBP_NODISCARD int WebPISetIOHooks(WebPIDecoder* const idec, VP8IoPutHook put,
VP8IoSetupHook setup,
VP8IoTeardownHook teardown, void* user_data);
// Main decoding object. This is an opaque structure.
typedef struct VP8Decoder VP8Decoder;
@ -128,17 +127,17 @@ VP8Decoder* VP8New(void);
// Must be called to make sure 'io' is initialized properly.
// Returns false in case of version mismatch. Upon such failure, no other
// decoding function should be called (VP8Decode, VP8GetHeaders, ...)
static WEBP_INLINE int VP8InitIo(VP8Io* const io) {
WEBP_NODISCARD static WEBP_INLINE int VP8InitIo(VP8Io* const io) {
return VP8InitIoInternal(io, WEBP_DECODER_ABI_VERSION);
}
// Decode the VP8 frame header. Returns true if ok.
// Note: 'io->data' must be pointing to the start of the VP8 frame header.
int VP8GetHeaders(VP8Decoder* const dec, VP8Io* const io);
WEBP_NODISCARD int VP8GetHeaders(VP8Decoder* const dec, VP8Io* const io);
// Decode a picture. Will call VP8GetHeaders() if it wasn't done already.
// Returns false in case of error.
int VP8Decode(VP8Decoder* const dec, VP8Io* const io);
WEBP_NODISCARD int VP8Decode(VP8Decoder* const dec, VP8Io* const io);
// Return current status of the decoder:
VP8StatusCode VP8Status(VP8Decoder* const dec);

View File

@ -21,6 +21,7 @@
#include "src/utils/random_utils.h"
#include "src/utils/thread_utils.h"
#include "src/dsp/dsp.h"
#include "src/webp/types.h"
#ifdef __cplusplus
extern "C" {
@ -31,7 +32,7 @@ extern "C" {
// version numbers
#define DEC_MAJ_VERSION 1
#define DEC_MIN_VERSION 3
#define DEC_MIN_VERSION 5
#define DEC_REV_VERSION 0
// YUV-cache parameters. Cache is 32-bytes wide (= one cacheline).
@ -186,6 +187,7 @@ struct VP8Decoder {
// Main data source
VP8BitReader br_;
int incremental_; // if true, incremental decoding is expected
// headers
VP8FrameHeader frm_hdr_;
@ -281,7 +283,7 @@ int VP8ParseIntraModeRow(VP8BitReader* const br, VP8Decoder* const dec);
void VP8ParseQuant(VP8Decoder* const dec);
// in frame.c
int VP8InitFrame(VP8Decoder* const dec, VP8Io* const io);
WEBP_NODISCARD int VP8InitFrame(VP8Decoder* const dec, VP8Io* const io);
// Call io->setup() and finish setting up scan parameters.
// After this call returns, one must always call VP8ExitCritical() with the
// same parameters. Both functions should be used in pair. Returns VP8_STATUS_OK
@ -289,7 +291,7 @@ int VP8InitFrame(VP8Decoder* const dec, VP8Io* const io);
VP8StatusCode VP8EnterCritical(VP8Decoder* const dec, VP8Io* const io);
// Must always be called in pair with VP8EnterCritical().
// Returns false in case of error.
int VP8ExitCritical(VP8Decoder* const dec, VP8Io* const io);
WEBP_NODISCARD int VP8ExitCritical(VP8Decoder* const dec, VP8Io* const io);
// Return the multi-threading method to use (0=off), depending
// on options and bitstream size. Only for lossy decoding.
int VP8GetThreadMethod(const WebPDecoderOptions* const options,
@ -299,11 +301,12 @@ int VP8GetThreadMethod(const WebPDecoderOptions* const options,
void VP8InitDithering(const WebPDecoderOptions* const options,
VP8Decoder* const dec);
// Process the last decoded row (filtering + output).
int VP8ProcessRow(VP8Decoder* const dec, VP8Io* const io);
WEBP_NODISCARD int VP8ProcessRow(VP8Decoder* const dec, VP8Io* const io);
// To be called at the start of a new scanline, to initialize predictors.
void VP8InitScanline(VP8Decoder* const dec);
// Decode one macroblock. Returns false if there is not enough data.
int VP8DecodeMB(VP8Decoder* const dec, VP8BitReader* const token_br);
WEBP_NODISCARD int VP8DecodeMB(VP8Decoder* const dec,
VP8BitReader* const token_br);
// in alpha.c
const uint8_t* VP8DecompressAlphaRows(VP8Decoder* const dec,

View File

@ -12,6 +12,8 @@
// Authors: Vikas Arora (vikaas.arora@gmail.com)
// Jyrki Alakuijala (jyrki@google.com)
#include <assert.h>
#include <stddef.h>
#include <stdlib.h>
#include "src/dec/alphai_dec.h"
@ -19,10 +21,9 @@
#include "src/dsp/dsp.h"
#include "src/dsp/lossless.h"
#include "src/dsp/lossless_common.h"
#include "src/dsp/yuv.h"
#include "src/utils/endian_inl_utils.h"
#include "src/utils/huffman_utils.h"
#include "src/utils/utils.h"
#include "src/webp/format_constants.h"
#define NUM_ARGB_CACHE_ROWS 16
@ -101,6 +102,14 @@ static const uint16_t kTableSize[12] = {
FIXED_TABLE_SIZE + 2704
};
static int VP8LSetError(VP8LDecoder* const dec, VP8StatusCode error) {
// The oldest error reported takes precedence over the new one.
if (dec->status_ == VP8_STATUS_OK || dec->status_ == VP8_STATUS_SUSPENDED) {
dec->status_ = error;
}
return 0;
}
static int DecodeImageStream(int xsize, int ysize,
int is_level0,
VP8LDecoder* const dec,
@ -253,11 +262,11 @@ static int ReadHuffmanCodeLengths(
int symbol;
int max_symbol;
int prev_code_len = DEFAULT_CODE_LENGTH;
HuffmanCode table[1 << LENGTHS_TABLE_BITS];
HuffmanTables tables;
if (!VP8LBuildHuffmanTable(table, LENGTHS_TABLE_BITS,
code_length_code_lengths,
NUM_CODE_LENGTH_CODES)) {
if (!VP8LHuffmanTablesAllocate(1 << LENGTHS_TABLE_BITS, &tables) ||
!VP8LBuildHuffmanTable(&tables, LENGTHS_TABLE_BITS,
code_length_code_lengths, NUM_CODE_LENGTH_CODES)) {
goto End;
}
@ -277,7 +286,7 @@ static int ReadHuffmanCodeLengths(
int code_len;
if (max_symbol-- == 0) break;
VP8LFillBitWindow(br);
p = &table[VP8LPrefetchBits(br) & LENGTHS_TABLE_MASK];
p = &tables.curr_segment->start[VP8LPrefetchBits(br) & LENGTHS_TABLE_MASK];
VP8LSetBitPos(br, br->bit_pos_ + p->bits);
code_len = p->value;
if (code_len < kCodeLengthLiterals) {
@ -300,14 +309,16 @@ static int ReadHuffmanCodeLengths(
ok = 1;
End:
if (!ok) dec->status_ = VP8_STATUS_BITSTREAM_ERROR;
VP8LHuffmanTablesDeallocate(&tables);
if (!ok) return VP8LSetError(dec, VP8_STATUS_BITSTREAM_ERROR);
return ok;
}
// 'code_lengths' is pre-allocated temporary buffer, used for creating Huffman
// tree.
static int ReadHuffmanCode(int alphabet_size, VP8LDecoder* const dec,
int* const code_lengths, HuffmanCode* const table) {
int* const code_lengths,
HuffmanTables* const table) {
int ok = 0;
int size = 0;
VP8LBitReader* const br = &dec->br_;
@ -331,10 +342,7 @@ static int ReadHuffmanCode(int alphabet_size, VP8LDecoder* const dec,
int i;
int code_length_code_lengths[NUM_CODE_LENGTH_CODES] = { 0 };
const int num_codes = VP8LReadBits(br, 4) + 4;
if (num_codes > NUM_CODE_LENGTH_CODES) {
dec->status_ = VP8_STATUS_BITSTREAM_ERROR;
return 0;
}
assert(num_codes <= NUM_CODE_LENGTH_CODES);
for (i = 0; i < num_codes; ++i) {
code_length_code_lengths[kCodeLengthCodeOrder[i]] = VP8LReadBits(br, 3);
@ -349,36 +357,36 @@ static int ReadHuffmanCode(int alphabet_size, VP8LDecoder* const dec,
code_lengths, alphabet_size);
}
if (!ok || size == 0) {
dec->status_ = VP8_STATUS_BITSTREAM_ERROR;
return 0;
return VP8LSetError(dec, VP8_STATUS_BITSTREAM_ERROR);
}
return size;
}
static int ReadHuffmanCodes(VP8LDecoder* const dec, int xsize, int ysize,
int color_cache_bits, int allow_recursion) {
int i, j;
int i;
VP8LBitReader* const br = &dec->br_;
VP8LMetadata* const hdr = &dec->hdr_;
uint32_t* huffman_image = NULL;
HTreeGroup* htree_groups = NULL;
HuffmanCode* huffman_tables = NULL;
HuffmanCode* huffman_table = NULL;
HuffmanTables* huffman_tables = &hdr->huffman_tables_;
int num_htree_groups = 1;
int num_htree_groups_max = 1;
int max_alphabet_size = 0;
int* code_lengths = NULL;
const int table_size = kTableSize[color_cache_bits];
int* mapping = NULL;
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)) {
// use meta Huffman codes.
const int huffman_precision = VP8LReadBits(br, 3) + 2;
const int huffman_precision =
MIN_HUFFMAN_BITS + VP8LReadBits(br, NUM_HUFFMAN_BITS);
const int huffman_xsize = VP8LSubSampleSize(xsize, huffman_precision);
const int huffman_ysize = VP8LSubSampleSize(ysize, huffman_precision);
const int huffman_pixs = huffman_xsize * huffman_ysize;
if (!DecodeImageStream(huffman_xsize, huffman_ysize, 0, dec,
if (!DecodeImageStream(huffman_xsize, huffman_ysize, /*is_level0=*/0, dec,
&huffman_image)) {
goto Error;
}
@ -402,7 +410,7 @@ static int ReadHuffmanCodes(VP8LDecoder* const dec, int xsize, int ysize,
// values [0, num_htree_groups)
mapping = (int*)WebPSafeMalloc(num_htree_groups_max, sizeof(*mapping));
if (mapping == NULL) {
dec->status_ = VP8_STATUS_OUT_OF_MEMORY;
VP8LSetError(dec, VP8_STATUS_OUT_OF_MEMORY);
goto Error;
}
// -1 means a value is unmapped, and therefore unused in the Huffman
@ -421,29 +429,55 @@ static int ReadHuffmanCodes(VP8LDecoder* const dec, int xsize, int ysize,
if (br->eos_) goto Error;
// Find maximum alphabet size for the htree group.
for (j = 0; j < HUFFMAN_CODES_PER_META_CODE; ++j) {
int alphabet_size = kAlphabetSize[j];
if (j == 0 && color_cache_bits > 0) {
alphabet_size += 1 << color_cache_bits;
}
if (max_alphabet_size < alphabet_size) {
max_alphabet_size = alphabet_size;
}
if (!ReadHuffmanCodesHelper(color_cache_bits, num_htree_groups,
num_htree_groups_max, mapping, dec,
huffman_tables, &htree_groups)) {
goto Error;
}
ok = 1;
code_lengths = (int*)WebPSafeCalloc((uint64_t)max_alphabet_size,
sizeof(*code_lengths));
huffman_tables = (HuffmanCode*)WebPSafeMalloc(num_htree_groups * table_size,
sizeof(*huffman_tables));
htree_groups = VP8LHtreeGroupsNew(num_htree_groups);
// All OK. Finalize pointers.
hdr->huffman_image_ = huffman_image;
hdr->num_htree_groups_ = num_htree_groups;
hdr->htree_groups_ = htree_groups;
if (htree_groups == NULL || code_lengths == NULL || huffman_tables == NULL) {
dec->status_ = VP8_STATUS_OUT_OF_MEMORY;
Error:
WebPSafeFree(mapping);
if (!ok) {
WebPSafeFree(huffman_image);
VP8LHuffmanTablesDeallocate(huffman_tables);
VP8LHtreeGroupsFree(htree_groups);
}
return ok;
}
int ReadHuffmanCodesHelper(int color_cache_bits, int num_htree_groups,
int num_htree_groups_max, const int* const mapping,
VP8LDecoder* const dec,
HuffmanTables* const huffman_tables,
HTreeGroup** const htree_groups) {
int i, j, ok = 0;
const int max_alphabet_size =
kAlphabetSize[0] + ((color_cache_bits > 0) ? 1 << color_cache_bits : 0);
const int table_size = kTableSize[color_cache_bits];
int* code_lengths = NULL;
if ((mapping == NULL && num_htree_groups != num_htree_groups_max) ||
num_htree_groups > num_htree_groups_max) {
goto Error;
}
code_lengths =
(int*)WebPSafeCalloc((uint64_t)max_alphabet_size, sizeof(*code_lengths));
*htree_groups = VP8LHtreeGroupsNew(num_htree_groups);
if (*htree_groups == NULL || code_lengths == NULL ||
!VP8LHuffmanTablesAllocate(num_htree_groups * table_size,
huffman_tables)) {
VP8LSetError(dec, VP8_STATUS_OUT_OF_MEMORY);
goto Error;
}
huffman_table = huffman_tables;
for (i = 0; i < num_htree_groups_max; ++i) {
// If the index "i" is unused in the Huffman image, just make sure the
// coefficients are valid but do not store them.
@ -460,7 +494,7 @@ static int ReadHuffmanCodes(VP8LDecoder* const dec, int xsize, int ysize,
}
} else {
HTreeGroup* const htree_group =
&htree_groups[(mapping == NULL) ? i : mapping[i]];
&(*htree_groups)[(mapping == NULL) ? i : mapping[i]];
HuffmanCode** const htrees = htree_group->htrees;
int size;
int total_size = 0;
@ -468,19 +502,20 @@ static int ReadHuffmanCodes(VP8LDecoder* const dec, int xsize, int ysize,
int max_bits = 0;
for (j = 0; j < HUFFMAN_CODES_PER_META_CODE; ++j) {
int alphabet_size = kAlphabetSize[j];
htrees[j] = huffman_table;
if (j == 0 && color_cache_bits > 0) {
alphabet_size += (1 << color_cache_bits);
}
size = ReadHuffmanCode(alphabet_size, dec, code_lengths, huffman_table);
size =
ReadHuffmanCode(alphabet_size, dec, code_lengths, huffman_tables);
htrees[j] = huffman_tables->curr_segment->curr_table;
if (size == 0) {
goto Error;
}
if (is_trivial_literal && kLiteralMap[j] == 1) {
is_trivial_literal = (huffman_table->bits == 0);
is_trivial_literal = (htrees[j]->bits == 0);
}
total_size += huffman_table->bits;
huffman_table += size;
total_size += htrees[j]->bits;
huffman_tables->curr_segment->curr_table += size;
if (j <= ALPHA) {
int local_max_bits = code_lengths[0];
int k;
@ -511,19 +546,12 @@ static int ReadHuffmanCodes(VP8LDecoder* const dec, int xsize, int ysize,
}
ok = 1;
// All OK. Finalize pointers.
hdr->huffman_image_ = huffman_image;
hdr->num_htree_groups_ = num_htree_groups;
hdr->htree_groups_ = htree_groups;
hdr->huffman_tables_ = huffman_tables;
Error:
WebPSafeFree(code_lengths);
WebPSafeFree(mapping);
if (!ok) {
WebPSafeFree(huffman_image);
WebPSafeFree(huffman_tables);
VP8LHtreeGroupsFree(htree_groups);
VP8LHuffmanTablesDeallocate(huffman_tables);
VP8LHtreeGroupsFree(*htree_groups);
*htree_groups = NULL;
}
return ok;
}
@ -547,8 +575,7 @@ static int AllocateAndInitRescaler(VP8LDecoder* const dec, VP8Io* const io) {
scaled_data_size * sizeof(*scaled_data);
uint8_t* memory = (uint8_t*)WebPSafeMalloc(memory_size, sizeof(*memory));
if (memory == NULL) {
dec->status_ = VP8_STATUS_OUT_OF_MEMORY;
return 0;
return VP8LSetError(dec, VP8_STATUS_OUT_OF_MEMORY);
}
assert(dec->rescaler_memory == NULL);
dec->rescaler_memory = memory;
@ -598,8 +625,8 @@ static int EmitRescaledRowsRGBA(const VP8LDecoder* const dec,
int num_lines_in = 0;
int num_lines_out = 0;
while (num_lines_in < mb_h) {
uint8_t* const row_in = in + (uint64_t)num_lines_in * in_stride;
uint8_t* const row_out = out + (uint64_t)num_lines_out * out_stride;
uint8_t* const row_in = in + (ptrdiff_t)num_lines_in * in_stride;
uint8_t* const row_out = out + (ptrdiff_t)num_lines_out * out_stride;
const int lines_left = mb_h - num_lines_in;
const int needed_lines = WebPRescaleNeededLines(dec->rescaler, lines_left);
int lines_imported;
@ -801,7 +828,7 @@ static void ProcessRows(VP8LDecoder* const dec, int row) {
if (WebPIsRGBMode(output->colorspace)) { // convert to RGBA
const WebPRGBABuffer* const buf = &output->u.RGBA;
uint8_t* const rgba =
buf->rgba + (int64_t)dec->last_out_row_ * buf->stride;
buf->rgba + (ptrdiff_t)dec->last_out_row_ * buf->stride;
const int num_rows_out =
#if !defined(WEBP_REDUCE_SIZE)
io->use_scaling ?
@ -1082,12 +1109,10 @@ static int DecodeAlphaData(VP8LDecoder* const dec, uint8_t* const data,
End:
br->eos_ = VP8LIsEndOfStream(br);
if (!ok || (br->eos_ && pos < end)) {
ok = 0;
dec->status_ = br->eos_ ? VP8_STATUS_SUSPENDED
: VP8_STATUS_BITSTREAM_ERROR;
} else {
dec->last_pixel_ = pos;
return VP8LSetError(
dec, br->eos_ ? VP8_STATUS_SUSPENDED : VP8_STATUS_BITSTREAM_ERROR);
}
dec->last_pixel_ = pos;
return ok;
}
@ -1237,9 +1262,20 @@ static int DecodeImageData(VP8LDecoder* const dec, uint32_t* const data,
}
br->eos_ = VP8LIsEndOfStream(br);
if (dec->incremental_ && br->eos_ && src < src_end) {
// In incremental decoding:
// 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);
} else if (!br->eos_) {
} else if ((dec->incremental_ && src >= src_last) || !br->eos_) {
// Process the remaining rows corresponding to last row-block.
if (process_func != NULL) {
process_func(dec, row > last_row ? last_row : row);
@ -1254,8 +1290,7 @@ static int DecodeImageData(VP8LDecoder* const dec, uint32_t* const data,
return 1;
Error:
dec->status_ = VP8_STATUS_BITSTREAM_ERROR;
return 0;
return VP8LSetError(dec, VP8_STATUS_BITSTREAM_ERROR);
}
// -----------------------------------------------------------------------------
@ -1317,12 +1352,13 @@ static int ReadTransform(int* const xsize, int const* ysize,
switch (type) {
case PREDICTOR_TRANSFORM:
case CROSS_COLOR_TRANSFORM:
transform->bits_ = VP8LReadBits(br, 3) + 2;
transform->bits_ =
MIN_TRANSFORM_BITS + VP8LReadBits(br, NUM_TRANSFORM_BITS);
ok = DecodeImageStream(VP8LSubSampleSize(transform->xsize_,
transform->bits_),
VP8LSubSampleSize(transform->ysize_,
transform->bits_),
0, dec, &transform->data_);
/*is_level0=*/0, dec, &transform->data_);
break;
case COLOR_INDEXING_TRANSFORM: {
const int num_colors = VP8LReadBits(br, 8) + 1;
@ -1332,8 +1368,11 @@ static int ReadTransform(int* const xsize, int const* ysize,
: 3;
*xsize = VP8LSubSampleSize(transform->xsize_, bits);
transform->bits_ = bits;
ok = DecodeImageStream(num_colors, 1, 0, dec, &transform->data_);
ok = ok && ExpandColorMap(num_colors, transform);
ok = DecodeImageStream(num_colors, /*ysize=*/1, /*is_level0=*/0, dec,
&transform->data_);
if (ok && !ExpandColorMap(num_colors, transform)) {
return VP8LSetError(dec, VP8_STATUS_OUT_OF_MEMORY);
}
break;
}
case SUBTRACT_GREEN_TRANSFORM:
@ -1358,7 +1397,7 @@ static void ClearMetadata(VP8LMetadata* const hdr) {
assert(hdr != NULL);
WebPSafeFree(hdr->huffman_image_);
WebPSafeFree(hdr->huffman_tables_);
VP8LHuffmanTablesDeallocate(&hdr->huffman_tables_);
VP8LHtreeGroupsFree(hdr->htree_groups_);
VP8LColorCacheClear(&hdr->color_cache_);
VP8LColorCacheClear(&hdr->saved_color_cache_);
@ -1379,7 +1418,9 @@ VP8LDecoder* VP8LNew(void) {
return dec;
}
void VP8LClear(VP8LDecoder* const dec) {
// Resets the decoder in its initial state, reclaiming memory.
// Preserves the dec->status_ value.
static void VP8LClear(VP8LDecoder* const dec) {
int i;
if (dec == NULL) return;
ClearMetadata(&dec->hdr_);
@ -1439,7 +1480,7 @@ static int DecodeImageStream(int xsize, int ysize,
color_cache_bits = VP8LReadBits(br, 4);
ok = (color_cache_bits >= 1 && color_cache_bits <= MAX_CACHE_BITS);
if (!ok) {
dec->status_ = VP8_STATUS_BITSTREAM_ERROR;
VP8LSetError(dec, VP8_STATUS_BITSTREAM_ERROR);
goto End;
}
}
@ -1448,7 +1489,7 @@ static int DecodeImageStream(int xsize, int ysize,
ok = ok && ReadHuffmanCodes(dec, transform_xsize, transform_ysize,
color_cache_bits, is_level0);
if (!ok) {
dec->status_ = VP8_STATUS_BITSTREAM_ERROR;
VP8LSetError(dec, VP8_STATUS_BITSTREAM_ERROR);
goto End;
}
@ -1456,8 +1497,7 @@ static int DecodeImageStream(int xsize, int ysize,
if (color_cache_bits > 0) {
hdr->color_cache_size_ = 1 << color_cache_bits;
if (!VP8LColorCacheInit(&hdr->color_cache_, color_cache_bits)) {
dec->status_ = VP8_STATUS_OUT_OF_MEMORY;
ok = 0;
ok = VP8LSetError(dec, VP8_STATUS_OUT_OF_MEMORY);
goto End;
}
} else {
@ -1474,8 +1514,7 @@ static int DecodeImageStream(int xsize, int ysize,
const uint64_t total_size = (uint64_t)transform_xsize * transform_ysize;
data = (uint32_t*)WebPSafeMalloc(total_size, sizeof(*data));
if (data == NULL) {
dec->status_ = VP8_STATUS_OUT_OF_MEMORY;
ok = 0;
ok = VP8LSetError(dec, VP8_STATUS_OUT_OF_MEMORY);
goto End;
}
}
@ -1520,8 +1559,7 @@ static int AllocateInternalBuffers32b(VP8LDecoder* const dec, int final_width) {
dec->pixels_ = (uint32_t*)WebPSafeMalloc(total_num_pixels, sizeof(uint32_t));
if (dec->pixels_ == NULL) {
dec->argb_cache_ = NULL; // for soundness
dec->status_ = VP8_STATUS_OUT_OF_MEMORY;
return 0;
return VP8LSetError(dec, VP8_STATUS_OUT_OF_MEMORY);
}
dec->argb_cache_ = dec->pixels_ + num_pixels + cache_top_pixels;
return 1;
@ -1532,8 +1570,7 @@ static int AllocateInternalBuffers8b(VP8LDecoder* const dec) {
dec->argb_cache_ = NULL; // for soundness
dec->pixels_ = (uint32_t*)WebPSafeMalloc(total_num_pixels, sizeof(uint8_t));
if (dec->pixels_ == NULL) {
dec->status_ = VP8_STATUS_OUT_OF_MEMORY;
return 0;
return VP8LSetError(dec, VP8_STATUS_OUT_OF_MEMORY);
}
return 1;
}
@ -1588,7 +1625,8 @@ int VP8LDecodeAlphaHeader(ALPHDecoder* const alph_dec,
dec->status_ = VP8_STATUS_OK;
VP8LInitBitReader(&dec->br_, data, data_size);
if (!DecodeImageStream(alph_dec->width_, alph_dec->height_, 1, dec, NULL)) {
if (!DecodeImageStream(alph_dec->width_, alph_dec->height_, /*is_level0=*/1,
dec, /*decoded_data=*/NULL)) {
goto Err;
}
@ -1643,22 +1681,24 @@ int VP8LDecodeHeader(VP8LDecoder* const dec, VP8Io* const io) {
if (dec == NULL) return 0;
if (io == NULL) {
dec->status_ = VP8_STATUS_INVALID_PARAM;
return 0;
return VP8LSetError(dec, VP8_STATUS_INVALID_PARAM);
}
dec->io_ = io;
dec->status_ = VP8_STATUS_OK;
VP8LInitBitReader(&dec->br_, io->data, io->data_size);
if (!ReadImageInfo(&dec->br_, &width, &height, &has_alpha)) {
dec->status_ = VP8_STATUS_BITSTREAM_ERROR;
VP8LSetError(dec, VP8_STATUS_BITSTREAM_ERROR);
goto Error;
}
dec->state_ = READ_DIM;
io->width = width;
io->height = height;
if (!DecodeImageStream(width, height, 1, dec, NULL)) goto Error;
if (!DecodeImageStream(width, height, /*is_level0=*/1, dec,
/*decoded_data=*/NULL)) {
goto Error;
}
return 1;
Error:
@ -1673,7 +1713,7 @@ int VP8LDecodeImage(VP8LDecoder* const dec) {
if (dec == NULL) return 0;
assert(dec->hdr_.huffman_tables_ != NULL);
assert(dec->hdr_.huffman_tables_.root.start != NULL);
assert(dec->hdr_.htree_groups_ != NULL);
assert(dec->hdr_.num_htree_groups_ > 0);
@ -1688,7 +1728,7 @@ int VP8LDecodeImage(VP8LDecoder* const dec) {
assert(dec->output_ != NULL);
if (!WebPIoInitFromOptions(params->options, io, MODE_BGRA)) {
dec->status_ = VP8_STATUS_INVALID_PARAM;
VP8LSetError(dec, VP8_STATUS_INVALID_PARAM);
goto Err;
}
@ -1698,7 +1738,7 @@ int VP8LDecodeImage(VP8LDecoder* const dec) {
if (io->use_scaling && !AllocateAndInitRescaler(dec, io)) goto Err;
#else
if (io->use_scaling) {
dec->status_ = VP8_STATUS_INVALID_PARAM;
VP8LSetError(dec, VP8_STATUS_INVALID_PARAM);
goto Err;
}
#endif
@ -1716,7 +1756,7 @@ int VP8LDecodeImage(VP8LDecoder* const dec) {
dec->hdr_.saved_color_cache_.colors_ == NULL) {
if (!VP8LColorCacheInit(&dec->hdr_.saved_color_cache_,
dec->hdr_.color_cache_.hash_bits_)) {
dec->status_ = VP8_STATUS_OUT_OF_MEMORY;
VP8LSetError(dec, VP8_STATUS_OUT_OF_MEMORY);
goto Err;
}
}

View File

@ -20,6 +20,7 @@
#include "src/utils/bit_reader_utils.h"
#include "src/utils/color_cache_utils.h"
#include "src/utils/huffman_utils.h"
#include "src/webp/types.h"
#ifdef __cplusplus
extern "C" {
@ -51,7 +52,7 @@ typedef struct {
uint32_t* huffman_image_;
int num_htree_groups_;
HTreeGroup* htree_groups_;
HuffmanCode* huffman_tables_;
HuffmanTables huffman_tables_;
} VP8LMetadata;
typedef struct VP8LDecoder VP8LDecoder;
@ -99,33 +100,42 @@ struct ALPHDecoder; // Defined in dec/alphai.h.
// Decodes image header for alpha data stored using lossless compression.
// Returns false in case of error.
int VP8LDecodeAlphaHeader(struct ALPHDecoder* const alph_dec,
const uint8_t* const data, size_t data_size);
WEBP_NODISCARD int VP8LDecodeAlphaHeader(struct ALPHDecoder* const alph_dec,
const uint8_t* const data,
size_t data_size);
// Decodes *at least* 'last_row' rows of alpha. If some of the initial rows are
// already decoded in previous call(s), it will resume decoding from where it
// was paused.
// Returns false in case of bitstream error.
int VP8LDecodeAlphaImageStream(struct ALPHDecoder* const alph_dec,
int last_row);
WEBP_NODISCARD int VP8LDecodeAlphaImageStream(
struct ALPHDecoder* const alph_dec, int last_row);
// Allocates and initialize a new lossless decoder instance.
VP8LDecoder* VP8LNew(void);
WEBP_NODISCARD VP8LDecoder* VP8LNew(void);
// Decodes the image header. Returns false in case of error.
int VP8LDecodeHeader(VP8LDecoder* const dec, VP8Io* const io);
WEBP_NODISCARD int VP8LDecodeHeader(VP8LDecoder* const dec, VP8Io* const io);
// Decodes an image. It's required to decode the lossless header before calling
// this function. Returns false in case of error, with updated dec->status_.
int VP8LDecodeImage(VP8LDecoder* const dec);
// Resets the decoder in its initial state, reclaiming memory.
// Preserves the dec->status_ value.
void VP8LClear(VP8LDecoder* const dec);
WEBP_NODISCARD int VP8LDecodeImage(VP8LDecoder* const dec);
// Clears and deallocate a lossless decoder instance.
void VP8LDelete(VP8LDecoder* const dec);
// Helper function for reading the different Huffman codes and storing them in
// 'huffman_tables' and 'htree_groups'.
// If mapping is NULL 'num_htree_groups_max' must equal 'num_htree_groups'.
// If it is not NULL, it maps 'num_htree_groups_max' indices to the
// 'num_htree_groups' groups. If 'num_htree_groups_max' > 'num_htree_groups',
// some of those indices map to -1. This is used for non-balanced codes to
// limit memory usage.
WEBP_NODISCARD int ReadHuffmanCodesHelper(
int color_cache_bits, int num_htree_groups, int num_htree_groups_max,
const int* const mapping, VP8LDecoder* const dec,
HuffmanTables* const huffman_tables, HTreeGroup** const htree_groups);
//------------------------------------------------------------------------------
#ifdef __cplusplus

View File

@ -13,11 +13,16 @@
#include <stdlib.h>
#include "src/dec/common_dec.h"
#include "src/dec/vp8_dec.h"
#include "src/dec/vp8i_dec.h"
#include "src/dec/vp8li_dec.h"
#include "src/dec/webpi_dec.h"
#include "src/utils/rescaler_utils.h"
#include "src/utils/utils.h"
#include "src/webp/decode.h"
#include "src/webp/mux_types.h" // ALPHA_FLAG
#include "src/webp/types.h"
//------------------------------------------------------------------------------
// RIFF layout is:
@ -444,8 +449,9 @@ void WebPResetDecParams(WebPDecParams* const params) {
// "Into" decoding variants
// Main flow
static VP8StatusCode DecodeInto(const uint8_t* const data, size_t data_size,
WebPDecParams* const params) {
WEBP_NODISCARD static VP8StatusCode DecodeInto(const uint8_t* const data,
size_t data_size,
WebPDecParams* const params) {
VP8StatusCode status;
VP8Io io;
WebPHeaderStructure headers;
@ -459,7 +465,9 @@ static VP8StatusCode DecodeInto(const uint8_t* const data, size_t data_size,
}
assert(params != NULL);
VP8InitIo(&io);
if (!VP8InitIo(&io)) {
return VP8_STATUS_INVALID_PARAM;
}
io.data = headers.data + headers.offset;
io.data_size = headers.data_size - headers.offset;
WebPInitCustomIo(params, &io); // Plug the I/O functions.
@ -523,17 +531,16 @@ static VP8StatusCode DecodeInto(const uint8_t* const data, size_t data_size,
}
// Helpers
static uint8_t* DecodeIntoRGBABuffer(WEBP_CSP_MODE colorspace,
const uint8_t* const data,
size_t data_size,
uint8_t* const rgba,
int stride, size_t size) {
WEBP_NODISCARD static uint8_t* DecodeIntoRGBABuffer(WEBP_CSP_MODE colorspace,
const uint8_t* const data,
size_t data_size,
uint8_t* const rgba,
int stride, size_t size) {
WebPDecParams params;
WebPDecBuffer buf;
if (rgba == NULL) {
if (rgba == NULL || !WebPInitDecBuffer(&buf)) {
return NULL;
}
WebPInitDecBuffer(&buf);
WebPResetDecParams(&params);
params.output = &buf;
buf.colorspace = colorspace;
@ -578,8 +585,7 @@ uint8_t* WebPDecodeYUVInto(const uint8_t* data, size_t data_size,
uint8_t* v, size_t v_size, int v_stride) {
WebPDecParams params;
WebPDecBuffer output;
if (luma == NULL) return NULL;
WebPInitDecBuffer(&output);
if (luma == NULL || !WebPInitDecBuffer(&output)) return NULL;
WebPResetDecParams(&params);
params.output = &output;
output.colorspace = MODE_YUV;
@ -601,13 +607,17 @@ uint8_t* WebPDecodeYUVInto(const uint8_t* data, size_t data_size,
//------------------------------------------------------------------------------
static uint8_t* Decode(WEBP_CSP_MODE mode, const uint8_t* const data,
size_t data_size, int* const width, int* const height,
WebPDecBuffer* const keep_info) {
WEBP_NODISCARD static uint8_t* Decode(WEBP_CSP_MODE mode,
const uint8_t* const data,
size_t data_size, int* const width,
int* const height,
WebPDecBuffer* const keep_info) {
WebPDecParams params;
WebPDecBuffer output;
WebPInitDecBuffer(&output);
if (!WebPInitDecBuffer(&output)) {
return NULL;
}
WebPResetDecParams(&params);
params.output = &output;
output.colorspace = mode;
@ -658,19 +668,26 @@ uint8_t* WebPDecodeBGRA(const uint8_t* data, size_t data_size,
uint8_t* WebPDecodeYUV(const uint8_t* data, size_t data_size,
int* width, int* height, uint8_t** u, uint8_t** v,
int* stride, int* uv_stride) {
WebPDecBuffer output; // only to preserve the side-infos
uint8_t* const out = Decode(MODE_YUV, data, data_size,
width, height, &output);
if (out != NULL) {
const WebPYUVABuffer* const buf = &output.u.YUVA;
*u = buf->u;
*v = buf->v;
*stride = buf->y_stride;
*uv_stride = buf->u_stride;
assert(buf->u_stride == buf->v_stride);
// data, width and height are checked by Decode().
if (u == NULL || v == NULL || stride == NULL || uv_stride == NULL) {
return NULL;
}
{
WebPDecBuffer output; // only to preserve the side-infos
uint8_t* const out = Decode(MODE_YUV, data, data_size,
width, height, &output);
if (out != NULL) {
const WebPYUVABuffer* const buf = &output.u.YUVA;
*u = buf->u;
*v = buf->v;
*stride = buf->y_stride;
*uv_stride = buf->u_stride;
assert(buf->u_stride == buf->v_stride);
}
return out;
}
return out;
}
static void DefaultFeatures(WebPBitstreamFeatures* const features) {
@ -726,7 +743,64 @@ int WebPInitDecoderConfigInternal(WebPDecoderConfig* config,
}
memset(config, 0, sizeof(*config));
DefaultFeatures(&config->input);
WebPInitDecBuffer(&config->output);
if (!WebPInitDecBuffer(&config->output)) {
return 0;
}
return 1;
}
static int WebPCheckCropDimensionsBasic(int x, int y, int w, int h) {
return !(x < 0 || y < 0 || w <= 0 || h <= 0);
}
int WebPValidateDecoderConfig(const WebPDecoderConfig* config) {
const WebPDecoderOptions* options;
if (config == NULL) return 0;
if (!IsValidColorspace(config->output.colorspace)) {
return 0;
}
options = &config->options;
// bypass_filtering, no_fancy_upsampling, use_cropping, use_scaling,
// use_threads, flip can be any integer and are interpreted as boolean.
// Check for cropping.
if (options->use_cropping && !WebPCheckCropDimensionsBasic(
options->crop_left, options->crop_top,
options->crop_width, options->crop_height)) {
return 0;
}
// Check for scaling.
if (options->use_scaling &&
(options->scaled_width < 0 || options->scaled_height < 0 ||
(options->scaled_width == 0 && options->scaled_height == 0))) {
return 0;
}
// In case the WebPBitstreamFeatures has been filled in, check further.
if (config->input.width > 0 || config->input.height > 0) {
int scaled_width = options->scaled_width;
int scaled_height = options->scaled_height;
if (options->use_cropping &&
!WebPCheckCropDimensions(config->input.width, config->input.height,
options->crop_left, options->crop_top,
options->crop_width, options->crop_height)) {
return 0;
}
if (options->use_scaling && !WebPRescalerGetScaledDimensions(
config->input.width, config->input.height,
&scaled_width, &scaled_height)) {
return 0;
}
}
// Check for dithering.
if (options->dithering_strength < 0 || options->dithering_strength > 100 ||
options->alpha_dithering_strength < 0 ||
options->alpha_dithering_strength > 100) {
return 0;
}
return 1;
}
@ -765,7 +839,9 @@ VP8StatusCode WebPDecode(const uint8_t* data, size_t data_size,
if (WebPAvoidSlowMemory(params.output, &config->input)) {
// decoding to slow memory: use a temporary in-mem buffer to decode into.
WebPDecBuffer in_mem_buffer;
WebPInitDecBuffer(&in_mem_buffer);
if (!WebPInitDecBuffer(&in_mem_buffer)) {
return VP8_STATUS_INVALID_PARAM;
}
in_mem_buffer.colorspace = config->output.colorspace;
in_mem_buffer.width = config->input.width;
in_mem_buffer.height = config->input.height;
@ -787,8 +863,8 @@ VP8StatusCode WebPDecode(const uint8_t* data, size_t data_size,
int WebPCheckCropDimensions(int image_width, int image_height,
int x, int y, int w, int h) {
return !(x < 0 || y < 0 || w <= 0 || h <= 0 ||
x >= image_width || w > image_width || w > image_width - x ||
return WebPCheckCropDimensionsBasic(x, y, w, h) &&
!(x >= image_width || w > image_width || w > image_width - x ||
y >= image_height || h > image_height || h > image_height - y);
}

View File

@ -20,6 +20,7 @@ extern "C" {
#include "src/utils/rescaler_utils.h"
#include "src/dec/vp8_dec.h"
#include "src/webp/decode.h"
//------------------------------------------------------------------------------
// WebPDecParams: Decoding output parameters. Transient internal object.
@ -87,8 +88,9 @@ void WebPInitCustomIo(WebPDecParams* const params, VP8Io* const io);
// Setup crop_xxx fields, mb_w and mb_h in io. 'src_colorspace' refers
// to the *compressed* format, not the output one.
int WebPIoInitFromOptions(const WebPDecoderOptions* const options,
VP8Io* const io, WEBP_CSP_MODE src_colorspace);
WEBP_NODISCARD int WebPIoInitFromOptions(
const WebPDecoderOptions* const options, VP8Io* const io,
WEBP_CSP_MODE src_colorspace);
//------------------------------------------------------------------------------
// Internal functions regarding WebPDecBuffer memory (in buffer.c).

View File

@ -13,6 +13,6 @@ noinst_HEADERS =
noinst_HEADERS += ../webp/format_constants.h
libwebpdemux_la_LIBADD = ../libwebp.la
libwebpdemux_la_LDFLAGS = -no-undefined -version-info 2:12:0
libwebpdemux_la_LDFLAGS = -no-undefined -version-info 2:16:0
libwebpdemuxincludedir = $(includedir)/webp
pkgconfig_DATA = libwebpdemux.pc

View File

@ -20,6 +20,7 @@
#include "src/utils/utils.h"
#include "src/webp/decode.h"
#include "src/webp/demux.h"
#include "src/webp/types.h"
#define NUM_CHANNELS 4
@ -68,8 +69,9 @@ int WebPAnimDecoderOptionsInitInternal(WebPAnimDecoderOptions* dec_options,
return 1;
}
static int ApplyDecoderOptions(const WebPAnimDecoderOptions* const dec_options,
WebPAnimDecoder* const dec) {
WEBP_NODISCARD static int ApplyDecoderOptions(
const WebPAnimDecoderOptions* const dec_options,
WebPAnimDecoder* const dec) {
WEBP_CSP_MODE mode;
WebPDecoderConfig* config = &dec->config_;
assert(dec_options != NULL);
@ -82,7 +84,9 @@ static int ApplyDecoderOptions(const WebPAnimDecoderOptions* const dec_options,
dec->blend_func_ = (mode == MODE_RGBA || mode == MODE_BGRA)
? &BlendPixelRowNonPremult
: &BlendPixelRowPremult;
WebPInitDecoderConfig(config);
if (!WebPInitDecoderConfig(config)) {
return 0;
}
config->output.colorspace = mode;
config->output.is_external_memory = 1;
config->options.use_threads = dec_options->use_threads;
@ -157,8 +161,8 @@ static int IsFullFrame(int width, int height, int canvas_width,
}
// Clear the canvas to transparent.
static int ZeroFillCanvas(uint8_t* buf, uint32_t canvas_width,
uint32_t canvas_height) {
WEBP_NODISCARD static int ZeroFillCanvas(uint8_t* buf, uint32_t canvas_width,
uint32_t canvas_height) {
const uint64_t size =
(uint64_t)canvas_width * canvas_height * NUM_CHANNELS * sizeof(*buf);
if (!CheckSizeOverflow(size)) return 0;
@ -179,8 +183,8 @@ static void ZeroFillFrameRect(uint8_t* buf, int buf_stride, int x_offset,
}
// Copy width * height pixels from 'src' to 'dst'.
static int CopyCanvas(const uint8_t* src, uint8_t* dst,
uint32_t width, uint32_t height) {
WEBP_NODISCARD static int CopyCanvas(const uint8_t* src, uint8_t* dst,
uint32_t width, uint32_t height) {
const uint64_t size = (uint64_t)width * height * NUM_CHANNELS;
if (!CheckSizeOverflow(size)) return 0;
assert(src != NULL && dst != NULL);
@ -424,7 +428,9 @@ int WebPAnimDecoderGetNext(WebPAnimDecoder* dec,
WebPDemuxReleaseIterator(&dec->prev_iter_);
dec->prev_iter_ = iter;
dec->prev_frame_was_keyframe_ = is_key_frame;
CopyCanvas(dec->curr_frame_, dec->prev_frame_disposed_, width, height);
if (!CopyCanvas(dec->curr_frame_, dec->prev_frame_disposed_, width, height)) {
goto Error;
}
if (dec->prev_iter_.dispose_method == WEBP_MUX_DISPOSE_BACKGROUND) {
ZeroFillFrameRect(dec->prev_frame_disposed_, width * NUM_CHANNELS,
dec->prev_iter_.x_offset, dec->prev_iter_.y_offset,

View File

@ -24,7 +24,7 @@
#include "src/webp/format_constants.h"
#define DMUX_MAJ_VERSION 1
#define DMUX_MIN_VERSION 3
#define DMUX_MIN_VERSION 5
#define DMUX_REV_VERSION 0
typedef struct {

View File

@ -6,6 +6,6 @@ includedir=@includedir@
Name: libwebpdemux
Description: Library for parsing the WebP graphics format container
Version: @PACKAGE_VERSION@
Requires: libwebp >= 0.2.0
Requires.private: libwebp >= 0.2.0
Cflags: -I${includedir}
Libs: -L${libdir} -l@webp_libname_prefix@webpdemux

View File

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

View File

@ -5,6 +5,8 @@ noinst_LTLIBRARIES += libwebpdsp_sse2.la
noinst_LTLIBRARIES += libwebpdspdecode_sse2.la
noinst_LTLIBRARIES += libwebpdsp_sse41.la
noinst_LTLIBRARIES += libwebpdspdecode_sse41.la
noinst_LTLIBRARIES += libwebpdsp_avx2.la
noinst_LTLIBRARIES += libwebpdspdecode_avx2.la
noinst_LTLIBRARIES += libwebpdsp_neon.la
noinst_LTLIBRARIES += libwebpdspdecode_neon.la
noinst_LTLIBRARIES += libwebpdsp_msa.la
@ -44,6 +46,11 @@ ENC_SOURCES += lossless_enc.c
ENC_SOURCES += quant.h
ENC_SOURCES += ssim.c
libwebpdspdecode_avx2_la_SOURCES =
libwebpdspdecode_avx2_la_SOURCES += lossless_avx2.c
libwebpdspdecode_avx2_la_CPPFLAGS = $(libwebpdsp_la_CPPFLAGS)
libwebpdspdecode_avx2_la_CFLAGS = $(AM_CFLAGS) $(AVX2_FLAGS)
libwebpdspdecode_sse41_la_SOURCES =
libwebpdspdecode_sse41_la_SOURCES += alpha_processing_sse41.c
libwebpdspdecode_sse41_la_SOURCES += dec_sse41.c
@ -123,6 +130,12 @@ libwebpdsp_sse41_la_CPPFLAGS = $(libwebpdsp_la_CPPFLAGS)
libwebpdsp_sse41_la_CFLAGS = $(AM_CFLAGS) $(SSE41_FLAGS)
libwebpdsp_sse41_la_LIBADD = libwebpdspdecode_sse41.la
libwebpdsp_avx2_la_SOURCES =
libwebpdsp_avx2_la_SOURCES += lossless_enc_avx2.c
libwebpdsp_avx2_la_CPPFLAGS = $(libwebpdsp_la_CPPFLAGS)
libwebpdsp_avx2_la_CFLAGS = $(AM_CFLAGS) $(AVX2_FLAGS)
libwebpdsp_avx2_la_LIBADD = libwebpdspdecode_avx2.la
libwebpdsp_neon_la_SOURCES =
libwebpdsp_neon_la_SOURCES += cost_neon.c
libwebpdsp_neon_la_SOURCES += enc_neon.c
@ -167,6 +180,7 @@ libwebpdsp_la_LDFLAGS = -lm
libwebpdsp_la_LIBADD =
libwebpdsp_la_LIBADD += libwebpdsp_sse2.la
libwebpdsp_la_LIBADD += libwebpdsp_sse41.la
libwebpdsp_la_LIBADD += libwebpdsp_avx2.la
libwebpdsp_la_LIBADD += libwebpdsp_neon.la
libwebpdsp_la_LIBADD += libwebpdsp_msa.la
libwebpdsp_la_LIBADD += libwebpdsp_mips32.la
@ -180,6 +194,7 @@ if BUILD_LIBWEBPDECODER
libwebpdspdecode_la_LIBADD =
libwebpdspdecode_la_LIBADD += libwebpdspdecode_sse2.la
libwebpdspdecode_la_LIBADD += libwebpdspdecode_sse41.la
libwebpdspdecode_la_LIBADD += libwebpdspdecode_avx2.la
libwebpdspdecode_la_LIBADD += libwebpdspdecode_neon.la
libwebpdspdecode_la_LIBADD += libwebpdspdecode_msa.la
libwebpdspdecode_la_LIBADD += libwebpdspdecode_mips32.la

View File

@ -425,6 +425,7 @@ void (*WebPAlphaReplace)(uint32_t* src, int length, uint32_t color);
//------------------------------------------------------------------------------
// Init function
extern VP8CPUInfo VP8GetCPUInfo;
extern void WebPInitAlphaProcessingMIPSdspR2(void);
extern void WebPInitAlphaProcessingSSE2(void);
extern void WebPInitAlphaProcessingSSE41(void);

View File

@ -16,6 +16,8 @@
#if defined(WEBP_USE_SSE2)
#include <emmintrin.h>
#include "src/dsp/cpu.h"
//------------------------------------------------------------------------------
static int DispatchAlpha_SSE2(const uint8_t* WEBP_RESTRICT alpha,
@ -26,38 +28,44 @@ static int DispatchAlpha_SSE2(const uint8_t* WEBP_RESTRICT alpha,
uint32_t alpha_and = 0xff;
int i, j;
const __m128i zero = _mm_setzero_si128();
const __m128i rgb_mask = _mm_set1_epi32((int)0xffffff00); // to preserve RGB
const __m128i all_0xff = _mm_set_epi32(0, 0, ~0, ~0);
__m128i all_alphas = all_0xff;
const __m128i alpha_mask = _mm_set1_epi32((int)0xff); // to preserve A
const __m128i all_0xff = _mm_set1_epi8(0xff);
__m128i all_alphas16 = all_0xff;
__m128i all_alphas8 = all_0xff;
// We must be able to access 3 extra bytes after the last written byte
// 'dst[4 * width - 4]', because we don't know if alpha is the first or the
// last byte of the quadruplet.
const int limit = (width - 1) & ~7;
for (j = 0; j < height; ++j) {
__m128i* out = (__m128i*)dst;
for (i = 0; i < limit; i += 8) {
char* ptr = (char*)dst;
for (i = 0; i + 16 <= width - 1; i += 16) {
// load 16 alpha bytes
const __m128i a0 = _mm_loadu_si128((const __m128i*)&alpha[i]);
const __m128i a1_lo = _mm_unpacklo_epi8(a0, zero);
const __m128i a1_hi = _mm_unpackhi_epi8(a0, zero);
const __m128i a2_lo_lo = _mm_unpacklo_epi16(a1_lo, zero);
const __m128i a2_lo_hi = _mm_unpackhi_epi16(a1_lo, zero);
const __m128i a2_hi_lo = _mm_unpacklo_epi16(a1_hi, zero);
const __m128i a2_hi_hi = _mm_unpackhi_epi16(a1_hi, zero);
_mm_maskmoveu_si128(a2_lo_lo, alpha_mask, ptr + 0);
_mm_maskmoveu_si128(a2_lo_hi, alpha_mask, ptr + 16);
_mm_maskmoveu_si128(a2_hi_lo, alpha_mask, ptr + 32);
_mm_maskmoveu_si128(a2_hi_hi, alpha_mask, ptr + 48);
// accumulate 16 alpha 'and' in parallel
all_alphas16 = _mm_and_si128(all_alphas16, a0);
ptr += 64;
}
if (i + 8 <= width - 1) {
// load 8 alpha bytes
const __m128i a0 = _mm_loadl_epi64((const __m128i*)&alpha[i]);
const __m128i a1 = _mm_unpacklo_epi8(a0, zero);
const __m128i a2_lo = _mm_unpacklo_epi16(a1, zero);
const __m128i a2_hi = _mm_unpackhi_epi16(a1, zero);
// load 8 dst pixels (32 bytes)
const __m128i b0_lo = _mm_loadu_si128(out + 0);
const __m128i b0_hi = _mm_loadu_si128(out + 1);
// mask dst alpha values
const __m128i b1_lo = _mm_and_si128(b0_lo, rgb_mask);
const __m128i b1_hi = _mm_and_si128(b0_hi, rgb_mask);
// combine
const __m128i b2_lo = _mm_or_si128(b1_lo, a2_lo);
const __m128i b2_hi = _mm_or_si128(b1_hi, a2_hi);
// store
_mm_storeu_si128(out + 0, b2_lo);
_mm_storeu_si128(out + 1, b2_hi);
// accumulate eight alpha 'and' in parallel
all_alphas = _mm_and_si128(all_alphas, a0);
out += 2;
_mm_maskmoveu_si128(a2_lo, alpha_mask, ptr);
_mm_maskmoveu_si128(a2_hi, alpha_mask, ptr + 16);
// accumulate 8 alpha 'and' in parallel
all_alphas8 = _mm_and_si128(all_alphas8, a0);
i += 8;
}
for (; i < width; ++i) {
const uint32_t alpha_value = alpha[i];
@ -68,8 +76,9 @@ static int DispatchAlpha_SSE2(const uint8_t* WEBP_RESTRICT alpha,
dst += dst_stride;
}
// Combine the eight alpha 'and' into a 8-bit mask.
alpha_and &= _mm_movemask_epi8(_mm_cmpeq_epi8(all_alphas, all_0xff));
return (alpha_and != 0xff);
alpha_and &= _mm_movemask_epi8(_mm_cmpeq_epi8(all_alphas8, all_0xff)) & 0xff;
return (alpha_and != 0xff ||
_mm_movemask_epi8(_mm_cmpeq_epi8(all_alphas16, all_0xff)) != 0xffff);
}
static void DispatchAlphaToGreen_SSE2(const uint8_t* WEBP_RESTRICT alpha,
@ -144,6 +153,46 @@ static int ExtractAlpha_SSE2(const uint8_t* WEBP_RESTRICT argb, int argb_stride,
return (alpha_and == 0xff);
}
static void ExtractGreen_SSE2(const uint32_t* WEBP_RESTRICT argb,
uint8_t* WEBP_RESTRICT alpha, int size) {
int i;
const __m128i mask = _mm_set1_epi32(0xff);
const __m128i* src = (const __m128i*)argb;
for (i = 0; i + 16 <= size; i += 16, src += 4) {
const __m128i a0 = _mm_loadu_si128(src + 0);
const __m128i a1 = _mm_loadu_si128(src + 1);
const __m128i a2 = _mm_loadu_si128(src + 2);
const __m128i a3 = _mm_loadu_si128(src + 3);
const __m128i b0 = _mm_srli_epi32(a0, 8);
const __m128i b1 = _mm_srli_epi32(a1, 8);
const __m128i b2 = _mm_srli_epi32(a2, 8);
const __m128i b3 = _mm_srli_epi32(a3, 8);
const __m128i c0 = _mm_and_si128(b0, mask);
const __m128i c1 = _mm_and_si128(b1, mask);
const __m128i c2 = _mm_and_si128(b2, mask);
const __m128i c3 = _mm_and_si128(b3, mask);
const __m128i d0 = _mm_packs_epi32(c0, c1);
const __m128i d1 = _mm_packs_epi32(c2, c3);
const __m128i e = _mm_packus_epi16(d0, d1);
// store
_mm_storeu_si128((__m128i*)&alpha[i], e);
}
if (i + 8 <= size) {
const __m128i a0 = _mm_loadu_si128(src + 0);
const __m128i a1 = _mm_loadu_si128(src + 1);
const __m128i b0 = _mm_srli_epi32(a0, 8);
const __m128i b1 = _mm_srli_epi32(a1, 8);
const __m128i c0 = _mm_and_si128(b0, mask);
const __m128i c1 = _mm_and_si128(b1, mask);
const __m128i d = _mm_packs_epi32(c0, c1);
const __m128i e = _mm_packus_epi16(d, d);
_mm_storel_epi64((__m128i*)&alpha[i], e);
i += 8;
}
for (; i < size; ++i) alpha[i] = argb[i] >> 8;
}
//------------------------------------------------------------------------------
// Non-dither premultiplied modes
@ -354,6 +403,7 @@ WEBP_TSAN_IGNORE_FUNCTION void WebPInitAlphaProcessingSSE2(void) {
WebPDispatchAlpha = DispatchAlpha_SSE2;
WebPDispatchAlphaToGreen = DispatchAlphaToGreen_SSE2;
WebPExtractAlpha = ExtractAlpha_SSE2;
WebPExtractGreen = ExtractGreen_SSE2;
WebPHasAlpha8b = HasAlpha8b_SSE2;
WebPHasAlpha32b = HasAlpha32b_SSE2;

View File

@ -354,8 +354,8 @@ static int GetResidualCost_C(int ctx0, const VP8Residual* const res) {
return cost;
}
static void SetResidualCoeffs_C(const int16_t* const coeffs,
VP8Residual* const res) {
static void SetResidualCoeffs_C(const int16_t* WEBP_RESTRICT const coeffs,
VP8Residual* WEBP_RESTRICT const res) {
int n;
res->last = -1;
assert(res->first == 0 || coeffs[0] == 0);
@ -374,6 +374,7 @@ static void SetResidualCoeffs_C(const int16_t* const coeffs,
VP8GetResidualCostFunc VP8GetResidualCost;
VP8SetResidualCoeffsFunc VP8SetResidualCoeffs;
extern VP8CPUInfo VP8GetCPUInfo;
extern void VP8EncDspCostInitMIPS32(void);
extern void VP8EncDspCostInitMIPSdspR2(void);
extern void VP8EncDspCostInitSSE2(void);

View File

@ -96,8 +96,8 @@ static int GetResidualCost_MIPS32(int ctx0, const VP8Residual* const res) {
return cost;
}
static void SetResidualCoeffs_MIPS32(const int16_t* const coeffs,
VP8Residual* const res) {
static void SetResidualCoeffs_MIPS32(const int16_t* WEBP_RESTRICT const coeffs,
VP8Residual* WEBP_RESTRICT const res) {
const int16_t* p_coeffs = (int16_t*)coeffs;
int temp0, temp1, temp2, n, n1;
assert(res->first == 0 || coeffs[0] == 0);

View File

@ -19,8 +19,8 @@
static const uint8_t position[16] = { 1, 2, 3, 4, 5, 6, 7, 8,
9, 10, 11, 12, 13, 14, 15, 16 };
static void SetResidualCoeffs_NEON(const int16_t* const coeffs,
VP8Residual* const res) {
static void SetResidualCoeffs_NEON(const int16_t* WEBP_RESTRICT const coeffs,
VP8Residual* WEBP_RESTRICT const res) {
const int16x8_t minus_one = vdupq_n_s16(-1);
const int16x8_t coeffs_0 = vld1q_s16(coeffs);
const int16x8_t coeffs_1 = vld1q_s16(coeffs + 8);
@ -29,7 +29,7 @@ static void SetResidualCoeffs_NEON(const int16_t* const coeffs,
const uint8x16_t eob = vcombine_u8(vqmovn_u16(eob_0), vqmovn_u16(eob_1));
const uint8x16_t masked = vandq_u8(eob, vld1q_u8(position));
#ifdef __aarch64__
#if WEBP_AARCH64
res->last = vmaxvq_u8(masked) - 1;
#else
const uint8x8_t eob_8x8 = vmax_u8(vget_low_u8(masked), vget_high_u8(masked));
@ -43,7 +43,7 @@ static void SetResidualCoeffs_NEON(const int16_t* const coeffs,
vst1_lane_s32(&res->last, vreinterpret_s32_u32(eob_32x2), 0);
--res->last;
#endif // __aarch64__
#endif // WEBP_AARCH64
res->coeffs = coeffs;
}

View File

@ -22,8 +22,8 @@
//------------------------------------------------------------------------------
static void SetResidualCoeffs_SSE2(const int16_t* const coeffs,
VP8Residual* const res) {
static void SetResidualCoeffs_SSE2(const int16_t* WEBP_RESTRICT const coeffs,
VP8Residual* WEBP_RESTRICT const res) {
const __m128i c0 = _mm_loadu_si128((const __m128i*)(coeffs + 0));
const __m128i c1 = _mm_loadu_si128((const __m128i*)(coeffs + 8));
// Use SSE2 to compare 16 values with a single instruction.

View File

@ -36,18 +36,6 @@ static WEBP_INLINE void GetCPUInfo(int cpu_info[4], int info_type) {
: "=a"(cpu_info[0]), "=D"(cpu_info[1]), "=c"(cpu_info[2]), "=d"(cpu_info[3])
: "a"(info_type), "c"(0));
}
#elif defined(__x86_64__) && \
(defined(__code_model_medium__) || defined(__code_model_large__)) && \
defined(__PIC__)
static WEBP_INLINE void GetCPUInfo(int cpu_info[4], int info_type) {
__asm__ volatile (
"xchg{q}\t{%%rbx}, %q1\n"
"cpuid\n"
"xchg{q}\t{%%rbx}, %q1\n"
: "=a"(cpu_info[0]), "=&r"(cpu_info[1]), "=c"(cpu_info[2]),
"=d"(cpu_info[3])
: "a"(info_type), "c"(0));
}
#elif defined(__i386__) || defined(__x86_64__)
static WEBP_INLINE void GetCPUInfo(int cpu_info[4], int info_type) {
__asm__ volatile (
@ -173,6 +161,7 @@ static int x86CPUInfo(CPUFeature feature) {
}
return 0;
}
WEBP_EXTERN VP8CPUInfo VP8GetCPUInfo;
VP8CPUInfo VP8GetCPUInfo = x86CPUInfo;
#elif defined(WEBP_ANDROID_NEON) // NB: needs to be before generic NEON test.
static int AndroidCPUInfo(CPUFeature feature) {
@ -184,6 +173,7 @@ static int AndroidCPUInfo(CPUFeature feature) {
}
return 0;
}
WEBP_EXTERN VP8CPUInfo VP8GetCPUInfo;
VP8CPUInfo VP8GetCPUInfo = AndroidCPUInfo;
#elif defined(EMSCRIPTEN) // also needs to be before generic NEON test
// Use compile flags as an indicator of SIMD support instead of a runtime check.
@ -208,6 +198,7 @@ static int wasmCPUInfo(CPUFeature feature) {
}
return 0;
}
WEBP_EXTERN VP8CPUInfo VP8GetCPUInfo;
VP8CPUInfo VP8GetCPUInfo = wasmCPUInfo;
#elif defined(WEBP_HAVE_NEON)
// In most cases this function doesn't check for NEON support (it's assumed by
@ -236,6 +227,7 @@ static int armCPUInfo(CPUFeature feature) {
return 1;
#endif
}
WEBP_EXTERN VP8CPUInfo VP8GetCPUInfo;
VP8CPUInfo VP8GetCPUInfo = armCPUInfo;
#elif defined(WEBP_USE_MIPS32) || defined(WEBP_USE_MIPS_DSP_R2) || \
defined(WEBP_USE_MSA)
@ -247,7 +239,9 @@ static int mipsCPUInfo(CPUFeature feature) {
}
}
WEBP_EXTERN VP8CPUInfo VP8GetCPUInfo;
VP8CPUInfo VP8GetCPUInfo = mipsCPUInfo;
#else
WEBP_EXTERN VP8CPUInfo VP8GetCPUInfo;
VP8CPUInfo VP8GetCPUInfo = NULL;
#endif

View File

@ -43,6 +43,9 @@
#define __has_builtin(x) 0
#endif
//------------------------------------------------------------------------------
// x86 defines.
#if !defined(HAVE_CONFIG_H)
#if defined(_MSC_VER) && _MSC_VER > 1310 && \
(defined(_M_X64) || defined(_M_IX86))
@ -53,6 +56,11 @@
(defined(_M_X64) || defined(_M_IX86))
#define WEBP_MSC_SSE41 // Visual C++ SSE4.1 targets
#endif
#if defined(_MSC_VER) && _MSC_VER >= 1700 && \
(defined(_M_X64) || defined(_M_IX86))
#define WEBP_MSC_AVX2 // Visual C++ AVX2 targets
#endif
#endif
// WEBP_HAVE_* are used to indicate the presence of the instruction set in dsp
@ -77,9 +85,22 @@
#define WEBP_HAVE_SSE41
#endif
#if (defined(__AVX2__) || defined(WEBP_MSC_AVX2)) && \
(!defined(HAVE_CONFIG_H) || defined(WEBP_HAVE_AVX2))
#define WEBP_USE_AVX2
#endif
#if defined(WEBP_USE_AVX2) && !defined(WEBP_HAVE_AVX2)
#define WEBP_HAVE_AVX2
#endif
#undef WEBP_MSC_AVX2
#undef WEBP_MSC_SSE41
#undef WEBP_MSC_SSE2
//------------------------------------------------------------------------------
// Arm defines.
// The intrinsics currently cause compiler errors with arm-nacl-gcc and the
// inline assembly would need to be modified for use with Native Client.
#if ((defined(__ARM_NEON__) || defined(__aarch64__)) && \
@ -98,16 +119,26 @@
// inclusion of arm64_neon.h; Visual Studio 2019 includes this file in
// arm_neon.h. Compile errors were seen with Visual Studio 2019 16.4 with
// vtbl4_u8(); a fix was made in 16.6.
#if defined(_MSC_VER) && ((_MSC_VER >= 1700 && defined(_M_ARM)) || \
(_MSC_VER >= 1926 && defined(_M_ARM64)))
#if defined(_MSC_VER) && \
((_MSC_VER >= 1700 && defined(_M_ARM)) || \
(_MSC_VER >= 1926 && (defined(_M_ARM64) || defined(_M_ARM64EC))))
#define WEBP_USE_NEON
#define WEBP_USE_INTRINSICS
#endif
#if defined(__aarch64__) || defined(_M_ARM64) || defined(_M_ARM64EC)
#define WEBP_AARCH64 1
#else
#define WEBP_AARCH64 0
#endif
#if defined(WEBP_USE_NEON) && !defined(WEBP_HAVE_NEON)
#define WEBP_HAVE_NEON
#endif
//------------------------------------------------------------------------------
// MIPS defines.
#if defined(__mips__) && !defined(__mips64) && defined(__mips_isa_rev) && \
(__mips_isa_rev >= 1) && (__mips_isa_rev < 6)
#define WEBP_USE_MIPS32
@ -123,6 +154,8 @@
#define WEBP_USE_MSA
#endif
//------------------------------------------------------------------------------
#ifndef WEBP_DSP_OMIT_C_CODE
#define WEBP_DSP_OMIT_C_CODE 1
#endif
@ -133,13 +166,14 @@
#define WEBP_NEON_OMIT_C_CODE 0
#endif
#if !(LOCAL_CLANG_PREREQ(3, 8) || LOCAL_GCC_PREREQ(4, 8) || \
defined(__aarch64__))
#if !(LOCAL_CLANG_PREREQ(3, 8) || LOCAL_GCC_PREREQ(4, 8) || WEBP_AARCH64)
#define WEBP_NEON_WORK_AROUND_GCC 1
#else
#define WEBP_NEON_WORK_AROUND_GCC 0
#endif
//------------------------------------------------------------------------------
// This macro prevents thread_sanitizer from reporting known concurrent writes.
#define WEBP_TSAN_IGNORE_FUNCTION
#if defined(__has_feature)
@ -241,16 +275,7 @@ typedef enum {
kMSA
} CPUFeature;
#ifdef __cplusplus
extern "C" {
#endif
// returns true if the CPU supports the feature.
typedef int (*VP8CPUInfo)(CPUFeature feature);
WEBP_EXTERN VP8CPUInfo VP8GetCPUInfo;
#ifdef __cplusplus
} // extern "C"
#endif
#endif // WEBP_DSP_CPU_H_

View File

@ -37,19 +37,19 @@ static WEBP_INLINE uint8_t clip_8b(int v) {
STORE(3, y, DC - (d)); \
} while (0)
#define MUL1(a) ((((a) * 20091) >> 16) + (a))
#define MUL2(a) (((a) * 35468) >> 16)
#if !WEBP_NEON_OMIT_C_CODE
static void TransformOne_C(const int16_t* in, uint8_t* dst) {
static void TransformOne_C(const int16_t* WEBP_RESTRICT in,
uint8_t* WEBP_RESTRICT dst) {
int C[4 * 4], *tmp;
int i;
tmp = C;
for (i = 0; i < 4; ++i) { // vertical pass
const int a = in[0] + in[8]; // [-4096, 4094]
const int b = in[0] - in[8]; // [-4095, 4095]
const int c = MUL2(in[4]) - MUL1(in[12]); // [-3783, 3783]
const int d = MUL1(in[4]) + MUL2(in[12]); // [-3785, 3781]
const int c = WEBP_TRANSFORM_AC3_MUL2(in[4]) -
WEBP_TRANSFORM_AC3_MUL1(in[12]); // [-3783, 3783]
const int d = WEBP_TRANSFORM_AC3_MUL1(in[4]) +
WEBP_TRANSFORM_AC3_MUL2(in[12]); // [-3785, 3781]
tmp[0] = a + d; // [-7881, 7875]
tmp[1] = b + c; // [-7878, 7878]
tmp[2] = b - c; // [-7878, 7878]
@ -69,8 +69,10 @@ static void TransformOne_C(const int16_t* in, uint8_t* dst) {
const int dc = tmp[0] + 4;
const int a = dc + tmp[8];
const int b = dc - tmp[8];
const int c = MUL2(tmp[4]) - MUL1(tmp[12]);
const int d = MUL1(tmp[4]) + MUL2(tmp[12]);
const int c =
WEBP_TRANSFORM_AC3_MUL2(tmp[4]) - WEBP_TRANSFORM_AC3_MUL1(tmp[12]);
const int d =
WEBP_TRANSFORM_AC3_MUL1(tmp[4]) + WEBP_TRANSFORM_AC3_MUL2(tmp[12]);
STORE(0, 0, a + d);
STORE(1, 0, b + c);
STORE(2, 0, b - c);
@ -81,22 +83,22 @@ static void TransformOne_C(const int16_t* in, uint8_t* dst) {
}
// Simplified transform when only in[0], in[1] and in[4] are non-zero
static void TransformAC3_C(const int16_t* in, uint8_t* dst) {
static void TransformAC3_C(const int16_t* WEBP_RESTRICT in,
uint8_t* WEBP_RESTRICT dst) {
const int a = in[0] + 4;
const int c4 = MUL2(in[4]);
const int d4 = MUL1(in[4]);
const int c1 = MUL2(in[1]);
const int d1 = MUL1(in[1]);
const int c4 = WEBP_TRANSFORM_AC3_MUL2(in[4]);
const int d4 = WEBP_TRANSFORM_AC3_MUL1(in[4]);
const int c1 = WEBP_TRANSFORM_AC3_MUL2(in[1]);
const int d1 = WEBP_TRANSFORM_AC3_MUL1(in[1]);
STORE2(0, a + d4, d1, c1);
STORE2(1, a + c4, d1, c1);
STORE2(2, a - c4, d1, c1);
STORE2(3, a - d4, d1, c1);
}
#undef MUL1
#undef MUL2
#undef STORE2
static void TransformTwo_C(const int16_t* in, uint8_t* dst, int do_two) {
static void TransformTwo_C(const int16_t* WEBP_RESTRICT in,
uint8_t* WEBP_RESTRICT dst, int do_two) {
TransformOne_C(in, dst);
if (do_two) {
TransformOne_C(in + 16, dst + 4);
@ -104,13 +106,15 @@ static void TransformTwo_C(const int16_t* in, uint8_t* dst, int do_two) {
}
#endif // !WEBP_NEON_OMIT_C_CODE
static void TransformUV_C(const int16_t* in, uint8_t* dst) {
static void TransformUV_C(const int16_t* WEBP_RESTRICT in,
uint8_t* WEBP_RESTRICT dst) {
VP8Transform(in + 0 * 16, dst, 1);
VP8Transform(in + 2 * 16, dst + 4 * BPS, 1);
}
#if !WEBP_NEON_OMIT_C_CODE
static void TransformDC_C(const int16_t* in, uint8_t* dst) {
static void TransformDC_C(const int16_t* WEBP_RESTRICT in,
uint8_t* WEBP_RESTRICT dst) {
const int DC = in[0] + 4;
int i, j;
for (j = 0; j < 4; ++j) {
@ -121,7 +125,8 @@ static void TransformDC_C(const int16_t* in, uint8_t* dst) {
}
#endif // !WEBP_NEON_OMIT_C_CODE
static void TransformDCUV_C(const int16_t* in, uint8_t* dst) {
static void TransformDCUV_C(const int16_t* WEBP_RESTRICT in,
uint8_t* WEBP_RESTRICT dst) {
if (in[0 * 16]) VP8TransformDC(in + 0 * 16, dst);
if (in[1 * 16]) VP8TransformDC(in + 1 * 16, dst + 4);
if (in[2 * 16]) VP8TransformDC(in + 2 * 16, dst + 4 * BPS);
@ -134,7 +139,8 @@ static void TransformDCUV_C(const int16_t* in, uint8_t* dst) {
// Paragraph 14.3
#if !WEBP_NEON_OMIT_C_CODE
static void TransformWHT_C(const int16_t* in, int16_t* out) {
static void TransformWHT_C(const int16_t* WEBP_RESTRICT in,
int16_t* WEBP_RESTRICT out) {
int tmp[16];
int i;
for (i = 0; i < 4; ++i) {
@ -162,7 +168,7 @@ static void TransformWHT_C(const int16_t* in, int16_t* out) {
}
#endif // !WEBP_NEON_OMIT_C_CODE
void (*VP8TransformWHT)(const int16_t* in, int16_t* out);
VP8WHT VP8TransformWHT;
//------------------------------------------------------------------------------
// Intra predictions
@ -662,32 +668,32 @@ static void HFilter16i_C(uint8_t* p, int stride,
#if !WEBP_NEON_OMIT_C_CODE
// 8-pixels wide variant, for chroma filtering
static void VFilter8_C(uint8_t* u, uint8_t* v, int stride,
int thresh, int ithresh, int hev_thresh) {
static void VFilter8_C(uint8_t* WEBP_RESTRICT u, uint8_t* WEBP_RESTRICT v,
int stride, int thresh, int ithresh, int hev_thresh) {
FilterLoop26_C(u, stride, 1, 8, thresh, ithresh, hev_thresh);
FilterLoop26_C(v, stride, 1, 8, thresh, ithresh, hev_thresh);
}
#endif // !WEBP_NEON_OMIT_C_CODE
#if !WEBP_NEON_OMIT_C_CODE || WEBP_NEON_WORK_AROUND_GCC
static void HFilter8_C(uint8_t* u, uint8_t* v, int stride,
int thresh, int ithresh, int hev_thresh) {
static void HFilter8_C(uint8_t* WEBP_RESTRICT u, uint8_t* WEBP_RESTRICT v,
int stride, int thresh, int ithresh, int hev_thresh) {
FilterLoop26_C(u, 1, stride, 8, thresh, ithresh, hev_thresh);
FilterLoop26_C(v, 1, stride, 8, thresh, ithresh, hev_thresh);
}
#endif // !WEBP_NEON_OMIT_C_CODE || WEBP_NEON_WORK_AROUND_GCC
#if !WEBP_NEON_OMIT_C_CODE
static void VFilter8i_C(uint8_t* u, uint8_t* v, int stride,
int thresh, int ithresh, int hev_thresh) {
static void VFilter8i_C(uint8_t* WEBP_RESTRICT u, uint8_t* WEBP_RESTRICT v,
int stride, int thresh, int ithresh, int hev_thresh) {
FilterLoop24_C(u + 4 * stride, stride, 1, 8, thresh, ithresh, hev_thresh);
FilterLoop24_C(v + 4 * stride, stride, 1, 8, thresh, ithresh, hev_thresh);
}
#endif // !WEBP_NEON_OMIT_C_CODE
#if !WEBP_NEON_OMIT_C_CODE || WEBP_NEON_WORK_AROUND_GCC
static void HFilter8i_C(uint8_t* u, uint8_t* v, int stride,
int thresh, int ithresh, int hev_thresh) {
static void HFilter8i_C(uint8_t* WEBP_RESTRICT u, uint8_t* WEBP_RESTRICT v,
int stride, int thresh, int ithresh, int hev_thresh) {
FilterLoop24_C(u + 4, 1, stride, 8, thresh, ithresh, hev_thresh);
FilterLoop24_C(v + 4, 1, stride, 8, thresh, ithresh, hev_thresh);
}
@ -695,8 +701,8 @@ static void HFilter8i_C(uint8_t* u, uint8_t* v, int stride,
//------------------------------------------------------------------------------
static void DitherCombine8x8_C(const uint8_t* dither, uint8_t* dst,
int dst_stride) {
static void DitherCombine8x8_C(const uint8_t* WEBP_RESTRICT dither,
uint8_t* WEBP_RESTRICT dst, int dst_stride) {
int i, j;
for (j = 0; j < 8; ++j) {
for (i = 0; i < 8; ++i) {
@ -731,9 +737,10 @@ VP8SimpleFilterFunc VP8SimpleHFilter16;
VP8SimpleFilterFunc VP8SimpleVFilter16i;
VP8SimpleFilterFunc VP8SimpleHFilter16i;
void (*VP8DitherCombine8x8)(const uint8_t* dither, uint8_t* dst,
int dst_stride);
void (*VP8DitherCombine8x8)(const uint8_t* WEBP_RESTRICT dither,
uint8_t* WEBP_RESTRICT dst, int dst_stride);
extern VP8CPUInfo VP8GetCPUInfo;
extern void VP8DspInitSSE2(void);
extern void VP8DspInitSSE41(void);
extern void VP8DspInitNEON(void);

View File

@ -18,8 +18,8 @@
#include "src/dsp/mips_macro.h"
static const int kC1 = 20091 + (1 << 16);
static const int kC2 = 35468;
static const int kC1 = WEBP_TRANSFORM_AC3_C1;
static const int kC2 = WEBP_TRANSFORM_AC3_C2;
static WEBP_INLINE int abs_mips32(int x) {
const int sign = x >> 31;
@ -133,26 +133,26 @@ static void HFilter16(uint8_t* p, int stride,
}
// 8-pixels wide variant, for chroma filtering
static void VFilter8(uint8_t* u, uint8_t* v, int stride,
int thresh, int ithresh, int hev_thresh) {
static void VFilter8(uint8_t* WEBP_RESTRICT u, uint8_t* WEBP_RESTRICT v,
int stride, int thresh, int ithresh, int hev_thresh) {
FilterLoop26(u, stride, 1, 8, thresh, ithresh, hev_thresh);
FilterLoop26(v, stride, 1, 8, thresh, ithresh, hev_thresh);
}
static void HFilter8(uint8_t* u, uint8_t* v, int stride,
int thresh, int ithresh, int hev_thresh) {
static void HFilter8(uint8_t* WEBP_RESTRICT u, uint8_t* WEBP_RESTRICT v,
int stride, int thresh, int ithresh, int hev_thresh) {
FilterLoop26(u, 1, stride, 8, thresh, ithresh, hev_thresh);
FilterLoop26(v, 1, stride, 8, thresh, ithresh, hev_thresh);
}
static void VFilter8i(uint8_t* u, uint8_t* v, int stride,
int thresh, int ithresh, int hev_thresh) {
static void VFilter8i(uint8_t* WEBP_RESTRICT u, uint8_t* WEBP_RESTRICT v,
int stride, int thresh, int ithresh, int hev_thresh) {
FilterLoop24(u + 4 * stride, stride, 1, 8, thresh, ithresh, hev_thresh);
FilterLoop24(v + 4 * stride, stride, 1, 8, thresh, ithresh, hev_thresh);
}
static void HFilter8i(uint8_t* u, uint8_t* v, int stride,
int thresh, int ithresh, int hev_thresh) {
static void HFilter8i(uint8_t* WEBP_RESTRICT u, uint8_t* WEBP_RESTRICT v,
int stride, int thresh, int ithresh, int hev_thresh) {
FilterLoop24(u + 4, 1, stride, 8, thresh, ithresh, hev_thresh);
FilterLoop24(v + 4, 1, stride, 8, thresh, ithresh, hev_thresh);
}
@ -215,11 +215,12 @@ static void SimpleHFilter16i(uint8_t* p, int stride, int thresh) {
}
}
static void TransformOne(const int16_t* in, uint8_t* dst) {
static void TransformOne(const int16_t* WEBP_RESTRICT in,
uint8_t* WEBP_RESTRICT dst) {
int temp0, temp1, temp2, temp3, temp4;
int temp5, temp6, temp7, temp8, temp9;
int temp10, temp11, temp12, temp13, temp14;
int temp15, temp16, temp17, temp18;
int temp15, temp16, temp17, temp18, temp19;
int16_t* p_in = (int16_t*)in;
// loops unrolled and merged to avoid usage of tmp buffer
@ -233,16 +234,14 @@ static void TransformOne(const int16_t* in, uint8_t* dst) {
"addu %[temp16], %[temp0], %[temp8] \n\t"
"subu %[temp0], %[temp0], %[temp8] \n\t"
"mul %[temp8], %[temp4], %[kC2] \n\t"
"mul %[temp17], %[temp12], %[kC1] \n\t"
"mul %[temp4], %[temp4], %[kC1] \n\t"
MUL_SHIFT_C1(temp17, temp12)
MUL_SHIFT_C1_IO(temp4, temp19)
"mul %[temp12], %[temp12], %[kC2] \n\t"
"lh %[temp1], 2(%[in]) \n\t"
"lh %[temp5], 10(%[in]) \n\t"
"lh %[temp9], 18(%[in]) \n\t"
"lh %[temp13], 26(%[in]) \n\t"
"sra %[temp8], %[temp8], 16 \n\t"
"sra %[temp17], %[temp17], 16 \n\t"
"sra %[temp4], %[temp4], 16 \n\t"
"sra %[temp12], %[temp12], 16 \n\t"
"lh %[temp2], 4(%[in]) \n\t"
"lh %[temp6], 12(%[in]) \n\t"
@ -261,49 +260,43 @@ static void TransformOne(const int16_t* in, uint8_t* dst) {
"addu %[temp12], %[temp0], %[temp17] \n\t"
"subu %[temp0], %[temp0], %[temp17] \n\t"
"mul %[temp9], %[temp5], %[kC2] \n\t"
"mul %[temp17], %[temp13], %[kC1] \n\t"
"mul %[temp5], %[temp5], %[kC1] \n\t"
MUL_SHIFT_C1(temp17, temp13)
MUL_SHIFT_C1_IO(temp5, temp19)
"mul %[temp13], %[temp13], %[kC2] \n\t"
"sra %[temp9], %[temp9], 16 \n\t"
"sra %[temp17], %[temp17], 16 \n\t"
"subu %[temp17], %[temp9], %[temp17] \n\t"
"sra %[temp5], %[temp5], 16 \n\t"
"sra %[temp13], %[temp13], 16 \n\t"
"addu %[temp5], %[temp5], %[temp13] \n\t"
"addu %[temp13], %[temp1], %[temp17] \n\t"
"subu %[temp1], %[temp1], %[temp17] \n\t"
"mul %[temp17], %[temp14], %[kC1] \n\t"
MUL_SHIFT_C1(temp17, temp14)
"mul %[temp14], %[temp14], %[kC2] \n\t"
"addu %[temp9], %[temp16], %[temp5] \n\t"
"subu %[temp5], %[temp16], %[temp5] \n\t"
"addu %[temp16], %[temp2], %[temp10] \n\t"
"subu %[temp2], %[temp2], %[temp10] \n\t"
"mul %[temp10], %[temp6], %[kC2] \n\t"
"mul %[temp6], %[temp6], %[kC1] \n\t"
"sra %[temp17], %[temp17], 16 \n\t"
MUL_SHIFT_C1_IO(temp6, temp19)
"sra %[temp14], %[temp14], 16 \n\t"
"sra %[temp10], %[temp10], 16 \n\t"
"sra %[temp6], %[temp6], 16 \n\t"
"subu %[temp17], %[temp10], %[temp17] \n\t"
"addu %[temp6], %[temp6], %[temp14] \n\t"
"addu %[temp10], %[temp16], %[temp6] \n\t"
"subu %[temp6], %[temp16], %[temp6] \n\t"
"addu %[temp14], %[temp2], %[temp17] \n\t"
"subu %[temp2], %[temp2], %[temp17] \n\t"
"mul %[temp17], %[temp15], %[kC1] \n\t"
MUL_SHIFT_C1(temp17, temp15)
"mul %[temp15], %[temp15], %[kC2] \n\t"
"addu %[temp16], %[temp3], %[temp11] \n\t"
"subu %[temp3], %[temp3], %[temp11] \n\t"
"mul %[temp11], %[temp7], %[kC2] \n\t"
"mul %[temp7], %[temp7], %[kC1] \n\t"
MUL_SHIFT_C1_IO(temp7, temp19)
"addiu %[temp8], %[temp8], 4 \n\t"
"addiu %[temp12], %[temp12], 4 \n\t"
"addiu %[temp0], %[temp0], 4 \n\t"
"addiu %[temp4], %[temp4], 4 \n\t"
"sra %[temp17], %[temp17], 16 \n\t"
"sra %[temp15], %[temp15], 16 \n\t"
"sra %[temp11], %[temp11], 16 \n\t"
"sra %[temp7], %[temp7], 16 \n\t"
"subu %[temp17], %[temp11], %[temp17] \n\t"
"addu %[temp7], %[temp7], %[temp15] \n\t"
"addu %[temp15], %[temp3], %[temp17] \n\t"
@ -313,48 +306,40 @@ static void TransformOne(const int16_t* in, uint8_t* dst) {
"addu %[temp16], %[temp8], %[temp10] \n\t"
"subu %[temp8], %[temp8], %[temp10] \n\t"
"mul %[temp10], %[temp9], %[kC2] \n\t"
"mul %[temp17], %[temp11], %[kC1] \n\t"
"mul %[temp9], %[temp9], %[kC1] \n\t"
MUL_SHIFT_C1(temp17, temp11)
MUL_SHIFT_C1_IO(temp9, temp19)
"mul %[temp11], %[temp11], %[kC2] \n\t"
"sra %[temp10], %[temp10], 16 \n\t"
"sra %[temp17], %[temp17], 16 \n\t"
"sra %[temp9], %[temp9], 16 \n\t"
"sra %[temp11], %[temp11], 16 \n\t"
"subu %[temp17], %[temp10], %[temp17] \n\t"
"addu %[temp11], %[temp9], %[temp11] \n\t"
"addu %[temp10], %[temp12], %[temp14] \n\t"
"subu %[temp12], %[temp12], %[temp14] \n\t"
"mul %[temp14], %[temp13], %[kC2] \n\t"
"mul %[temp9], %[temp15], %[kC1] \n\t"
"mul %[temp13], %[temp13], %[kC1] \n\t"
MUL_SHIFT_C1(temp9, temp15)
MUL_SHIFT_C1_IO(temp13, temp19)
"mul %[temp15], %[temp15], %[kC2] \n\t"
"sra %[temp14], %[temp14], 16 \n\t"
"sra %[temp9], %[temp9], 16 \n\t"
"sra %[temp13], %[temp13], 16 \n\t"
"sra %[temp15], %[temp15], 16 \n\t"
"subu %[temp9], %[temp14], %[temp9] \n\t"
"addu %[temp15], %[temp13], %[temp15] \n\t"
"addu %[temp14], %[temp0], %[temp2] \n\t"
"subu %[temp0], %[temp0], %[temp2] \n\t"
"mul %[temp2], %[temp1], %[kC2] \n\t"
"mul %[temp13], %[temp3], %[kC1] \n\t"
"mul %[temp1], %[temp1], %[kC1] \n\t"
MUL_SHIFT_C1(temp13, temp3)
MUL_SHIFT_C1_IO(temp1, temp19)
"mul %[temp3], %[temp3], %[kC2] \n\t"
"sra %[temp2], %[temp2], 16 \n\t"
"sra %[temp13], %[temp13], 16 \n\t"
"sra %[temp1], %[temp1], 16 \n\t"
"sra %[temp3], %[temp3], 16 \n\t"
"subu %[temp13], %[temp2], %[temp13] \n\t"
"addu %[temp3], %[temp1], %[temp3] \n\t"
"addu %[temp2], %[temp4], %[temp6] \n\t"
"subu %[temp4], %[temp4], %[temp6] \n\t"
"mul %[temp6], %[temp5], %[kC2] \n\t"
"mul %[temp1], %[temp7], %[kC1] \n\t"
"mul %[temp5], %[temp5], %[kC1] \n\t"
MUL_SHIFT_C1(temp1, temp7)
MUL_SHIFT_C1_IO(temp5, temp19)
"mul %[temp7], %[temp7], %[kC2] \n\t"
"sra %[temp6], %[temp6], 16 \n\t"
"sra %[temp1], %[temp1], 16 \n\t"
"sra %[temp5], %[temp5], 16 \n\t"
"sra %[temp7], %[temp7], 16 \n\t"
"subu %[temp1], %[temp6], %[temp1] \n\t"
"addu %[temp7], %[temp5], %[temp7] \n\t"
@ -542,13 +527,14 @@ static void TransformOne(const int16_t* in, uint8_t* dst) {
[temp9]"=&r"(temp9), [temp10]"=&r"(temp10), [temp11]"=&r"(temp11),
[temp12]"=&r"(temp12), [temp13]"=&r"(temp13), [temp14]"=&r"(temp14),
[temp15]"=&r"(temp15), [temp16]"=&r"(temp16), [temp17]"=&r"(temp17),
[temp18]"=&r"(temp18)
[temp18]"=&r"(temp18), [temp19]"=&r"(temp19)
: [in]"r"(p_in), [kC1]"r"(kC1), [kC2]"r"(kC2), [dst]"r"(dst)
: "memory", "hi", "lo"
);
}
static void TransformTwo(const int16_t* in, uint8_t* dst, int do_two) {
static void TransformTwo(const int16_t* WEBP_RESTRICT in,
uint8_t* WEBP_RESTRICT dst, int do_two) {
TransformOne(in, dst);
if (do_two) {
TransformOne(in + 16, dst + 4);

View File

@ -18,12 +18,11 @@
#include "src/dsp/mips_macro.h"
static const int kC1 = 20091 + (1 << 16);
static const int kC2 = 35468;
static const int kC1 = WEBP_TRANSFORM_AC3_C1;
static const int kC2 = WEBP_TRANSFORM_AC3_C2;
#define MUL(a, b) (((a) * (b)) >> 16)
static void TransformDC(const int16_t* in, uint8_t* dst) {
static void TransformDC(const int16_t* WEBP_RESTRICT in,
uint8_t* WEBP_RESTRICT dst) {
int temp1, temp2, temp3, temp4, temp5, temp6, temp7, temp8, temp9, temp10;
__asm__ volatile (
@ -47,12 +46,13 @@ static void TransformDC(const int16_t* in, uint8_t* dst) {
);
}
static void TransformAC3(const int16_t* in, uint8_t* dst) {
static void TransformAC3(const int16_t* WEBP_RESTRICT in,
uint8_t* WEBP_RESTRICT dst) {
const int a = in[0] + 4;
int c4 = MUL(in[4], kC2);
const int d4 = MUL(in[4], kC1);
const int c1 = MUL(in[1], kC2);
const int d1 = MUL(in[1], kC1);
int c4 = WEBP_TRANSFORM_AC3_MUL2(in[4]);
const int d4 = WEBP_TRANSFORM_AC3_MUL1(in[4]);
const int c1 = WEBP_TRANSFORM_AC3_MUL2(in[1]);
const int d1 = WEBP_TRANSFORM_AC3_MUL1(in[1]);
int temp1, temp2, temp3, temp4, temp5, temp6, temp7, temp8, temp9;
int temp10, temp11, temp12, temp13, temp14, temp15, temp16, temp17, temp18;
@ -83,7 +83,8 @@ static void TransformAC3(const int16_t* in, uint8_t* dst) {
);
}
static void TransformOne(const int16_t* in, uint8_t* dst) {
static void TransformOne(const int16_t* WEBP_RESTRICT in,
uint8_t* WEBP_RESTRICT dst) {
int temp1, temp2, temp3, temp4, temp5, temp6, temp7, temp8, temp9;
int temp10, temp11, temp12, temp13, temp14, temp15, temp16, temp17, temp18;
@ -150,7 +151,8 @@ static void TransformOne(const int16_t* in, uint8_t* dst) {
);
}
static void TransformTwo(const int16_t* in, uint8_t* dst, int do_two) {
static void TransformTwo(const int16_t* WEBP_RESTRICT in,
uint8_t* WEBP_RESTRICT dst, int do_two) {
TransformOne(in, dst);
if (do_two) {
TransformOne(in + 16, dst + 4);
@ -436,14 +438,14 @@ static void HFilter16(uint8_t* p, int stride,
}
// 8-pixels wide variant, for chroma filtering
static void VFilter8(uint8_t* u, uint8_t* v, int stride,
int thresh, int ithresh, int hev_thresh) {
static void VFilter8(uint8_t* WEBP_RESTRICT u, uint8_t* WEBP_RESTRICT v,
int stride, int thresh, int ithresh, int hev_thresh) {
FilterLoop26(u, stride, 1, 8, thresh, ithresh, hev_thresh);
FilterLoop26(v, stride, 1, 8, thresh, ithresh, hev_thresh);
}
static void HFilter8(uint8_t* u, uint8_t* v, int stride,
int thresh, int ithresh, int hev_thresh) {
static void HFilter8(uint8_t* WEBP_RESTRICT u, uint8_t* WEBP_RESTRICT v,
int stride, int thresh, int ithresh, int hev_thresh) {
FilterLoop26(u, 1, stride, 8, thresh, ithresh, hev_thresh);
FilterLoop26(v, 1, stride, 8, thresh, ithresh, hev_thresh);
}
@ -467,20 +469,18 @@ static void HFilter16i(uint8_t* p, int stride,
}
}
static void VFilter8i(uint8_t* u, uint8_t* v, int stride,
int thresh, int ithresh, int hev_thresh) {
static void VFilter8i(uint8_t* WEBP_RESTRICT u, uint8_t* WEBP_RESTRICT v,
int stride, int thresh, int ithresh, int hev_thresh) {
FilterLoop24(u + 4 * stride, stride, 1, 8, thresh, ithresh, hev_thresh);
FilterLoop24(v + 4 * stride, stride, 1, 8, thresh, ithresh, hev_thresh);
}
static void HFilter8i(uint8_t* u, uint8_t* v, int stride,
int thresh, int ithresh, int hev_thresh) {
static void HFilter8i(uint8_t* WEBP_RESTRICT u, uint8_t* WEBP_RESTRICT v,
int stride, int thresh, int ithresh, int hev_thresh) {
FilterLoop24(u + 4, 1, stride, 8, thresh, ithresh, hev_thresh);
FilterLoop24(v + 4, 1, stride, 8, thresh, ithresh, hev_thresh);
}
#undef MUL
//------------------------------------------------------------------------------
// Simple In-loop filtering (Paragraph 15.2)

View File

@ -37,10 +37,9 @@
d1_m = d_tmp1_m + d_tmp2_m; \
BUTTERFLY_4(a1_m, b1_m, c1_m, d1_m, out0, out1, out2, out3); \
}
#define MULT1(a) ((((a) * 20091) >> 16) + (a))
#define MULT2(a) (((a) * 35468) >> 16)
static void TransformOne(const int16_t* in, uint8_t* dst) {
static void TransformOne(const int16_t* WEBP_RESTRICT in,
uint8_t* WEBP_RESTRICT dst) {
v8i16 input0, input1;
v4i32 in0, in1, in2, in3, hz0, hz1, hz2, hz3, vt0, vt1, vt2, vt3;
v4i32 res0, res1, res2, res3;
@ -67,14 +66,16 @@ static void TransformOne(const int16_t* in, uint8_t* dst) {
ST4x4_UB(res0, res0, 3, 2, 1, 0, dst, BPS);
}
static void TransformTwo(const int16_t* in, uint8_t* dst, int do_two) {
static void TransformTwo(const int16_t* WEBP_RESTRICT in,
uint8_t* WEBP_RESTRICT dst, int do_two) {
TransformOne(in, dst);
if (do_two) {
TransformOne(in + 16, dst + 4);
}
}
static void TransformWHT(const int16_t* in, int16_t* out) {
static void TransformWHT(const int16_t* WEBP_RESTRICT in,
int16_t* WEBP_RESTRICT out) {
v8i16 input0, input1;
const v8i16 mask0 = { 0, 1, 2, 3, 8, 9, 10, 11 };
const v8i16 mask1 = { 4, 5, 6, 7, 12, 13, 14, 15 };
@ -116,18 +117,20 @@ static void TransformWHT(const int16_t* in, int16_t* out) {
out[240] = __msa_copy_s_h(out1, 7);
}
static void TransformDC(const int16_t* in, uint8_t* dst) {
static void TransformDC(const int16_t* WEBP_RESTRICT in,
uint8_t* WEBP_RESTRICT dst) {
const int DC = (in[0] + 4) >> 3;
const v8i16 tmp0 = __msa_fill_h(DC);
ADDBLK_ST4x4_UB(tmp0, tmp0, tmp0, tmp0, dst, BPS);
}
static void TransformAC3(const int16_t* in, uint8_t* dst) {
static void TransformAC3(const int16_t* WEBP_RESTRICT in,
uint8_t* WEBP_RESTRICT dst) {
const int a = in[0] + 4;
const int c4 = MULT2(in[4]);
const int d4 = MULT1(in[4]);
const int in2 = MULT2(in[1]);
const int in3 = MULT1(in[1]);
const int c4 = WEBP_TRANSFORM_AC3_MUL2(in[4]);
const int d4 = WEBP_TRANSFORM_AC3_MUL1(in[4]);
const int in2 = WEBP_TRANSFORM_AC3_MUL2(in[1]);
const int in3 = WEBP_TRANSFORM_AC3_MUL1(in[1]);
v4i32 tmp0 = { 0 };
v4i32 out0 = __msa_fill_w(a + d4);
v4i32 out1 = __msa_fill_w(a + c4);
@ -477,8 +480,8 @@ static void HFilter16i(uint8_t* src_y, int stride,
}
// 8-pixels wide variants, for chroma filtering
static void VFilter8(uint8_t* src_u, uint8_t* src_v, int stride,
int b_limit_in, int limit_in, int thresh_in) {
static void VFilter8(uint8_t* WEBP_RESTRICT src_u, uint8_t* WEBP_RESTRICT src_v,
int stride, int b_limit_in, int limit_in, int thresh_in) {
uint8_t* ptmp_src_u = src_u - 4 * stride;
uint8_t* ptmp_src_v = src_v - 4 * stride;
uint64_t p2_d, p1_d, p0_d, q0_d, q1_d, q2_d;
@ -522,8 +525,8 @@ static void VFilter8(uint8_t* src_u, uint8_t* src_v, int stride,
SD(q2_d, ptmp_src_v);
}
static void HFilter8(uint8_t* src_u, uint8_t* src_v, int stride,
int b_limit_in, int limit_in, int thresh_in) {
static void HFilter8(uint8_t* WEBP_RESTRICT src_u, uint8_t* WEBP_RESTRICT src_v,
int stride, int b_limit_in, int limit_in, int thresh_in) {
uint8_t* ptmp_src_u = src_u - 4;
uint8_t* ptmp_src_v = src_v - 4;
v16u8 p3, p2, p1, p0, q3, q2, q1, q0, mask, hev;
@ -558,7 +561,8 @@ static void HFilter8(uint8_t* src_u, uint8_t* src_v, int stride,
ST6x4_UB(tmp7, 0, tmp5, 4, ptmp_src_v, stride);
}
static void VFilter8i(uint8_t* src_u, uint8_t* src_v, int stride,
static void VFilter8i(uint8_t* WEBP_RESTRICT src_u,
uint8_t* WEBP_RESTRICT src_v, int stride,
int b_limit_in, int limit_in, int thresh_in) {
uint64_t p1_d, p0_d, q0_d, q1_d;
v16u8 p3, p2, p1, p0, q3, q2, q1, q0, mask, hev;
@ -589,7 +593,8 @@ static void VFilter8i(uint8_t* src_u, uint8_t* src_v, int stride,
SD4(q1_d, q0_d, p0_d, p1_d, src_v, -stride);
}
static void HFilter8i(uint8_t* src_u, uint8_t* src_v, int stride,
static void HFilter8i(uint8_t* WEBP_RESTRICT src_u,
uint8_t* WEBP_RESTRICT src_v, int stride,
int b_limit_in, int limit_in, int thresh_in) {
v16u8 p3, p2, p1, p0, q3, q2, q1, q0, mask, hev;
v16u8 row0, row1, row2, row3, row4, row5, row6, row7, row8;

View File

@ -916,8 +916,8 @@ static void HFilter16i_NEON(uint8_t* p, int stride,
#endif // !WORK_AROUND_GCC
// 8-pixels wide variant, for chroma filtering
static void VFilter8_NEON(uint8_t* u, uint8_t* v, int stride,
int thresh, int ithresh, int hev_thresh) {
static void VFilter8_NEON(uint8_t* WEBP_RESTRICT u, uint8_t* WEBP_RESTRICT v,
int stride, int thresh, int ithresh, int hev_thresh) {
uint8x16_t p3, p2, p1, p0, q0, q1, q2, q3;
Load8x8x2_NEON(u, v, stride, &p3, &p2, &p1, &p0, &q0, &q1, &q2, &q3);
{
@ -932,7 +932,8 @@ static void VFilter8_NEON(uint8_t* u, uint8_t* v, int stride,
Store8x2x2_NEON(oq1, oq2, u + 2 * stride, v + 2 * stride, stride);
}
}
static void VFilter8i_NEON(uint8_t* u, uint8_t* v, int stride,
static void VFilter8i_NEON(uint8_t* WEBP_RESTRICT u, uint8_t* WEBP_RESTRICT v,
int stride,
int thresh, int ithresh, int hev_thresh) {
uint8x16_t p3, p2, p1, p0, q0, q1, q2, q3;
u += 4 * stride;
@ -949,8 +950,8 @@ static void VFilter8i_NEON(uint8_t* u, uint8_t* v, int stride,
}
#if !defined(WORK_AROUND_GCC)
static void HFilter8_NEON(uint8_t* u, uint8_t* v, int stride,
int thresh, int ithresh, int hev_thresh) {
static void HFilter8_NEON(uint8_t* WEBP_RESTRICT u, uint8_t* WEBP_RESTRICT v,
int stride, int thresh, int ithresh, int hev_thresh) {
uint8x16_t p3, p2, p1, p0, q0, q1, q2, q3;
Load8x8x2T_NEON(u, v, stride, &p3, &p2, &p1, &p0, &q0, &q1, &q2, &q3);
{
@ -964,7 +965,8 @@ static void HFilter8_NEON(uint8_t* u, uint8_t* v, int stride,
}
}
static void HFilter8i_NEON(uint8_t* u, uint8_t* v, int stride,
static void HFilter8i_NEON(uint8_t* WEBP_RESTRICT u, uint8_t* WEBP_RESTRICT v,
int stride,
int thresh, int ithresh, int hev_thresh) {
uint8x16_t p3, p2, p1, p0, q0, q1, q2, q3;
u += 4;
@ -1000,8 +1002,9 @@ static void HFilter8i_NEON(uint8_t* u, uint8_t* v, int stride,
// libwebp adds 1 << 16 to cospi8sqrt2minus1 (kC1). However, this causes the
// same issue with kC1 and vqdmulh that we work around by down shifting kC2
static const int16_t kC1 = 20091;
static const int16_t kC2 = 17734; // half of kC2, actually. See comment above.
static const int16_t kC1 = WEBP_TRANSFORM_AC3_C1;
static const int16_t kC2 =
WEBP_TRANSFORM_AC3_C2 / 2; // half of kC2, actually. See comment above.
#if defined(WEBP_USE_INTRINSICS)
static WEBP_INLINE void Transpose8x2_NEON(const int16x8_t in0,
@ -1040,7 +1043,8 @@ static WEBP_INLINE void TransformPass_NEON(int16x8x2_t* const rows) {
Transpose8x2_NEON(E0, E1, rows);
}
static void TransformOne_NEON(const int16_t* in, uint8_t* dst) {
static void TransformOne_NEON(const int16_t* WEBP_RESTRICT in,
uint8_t* WEBP_RESTRICT dst) {
int16x8x2_t rows;
INIT_VECTOR2(rows, vld1q_s16(in + 0), vld1q_s16(in + 8));
TransformPass_NEON(&rows);
@ -1050,7 +1054,8 @@ static void TransformOne_NEON(const int16_t* in, uint8_t* dst) {
#else
static void TransformOne_NEON(const int16_t* in, uint8_t* dst) {
static void TransformOne_NEON(const int16_t* WEBP_RESTRICT in,
uint8_t* WEBP_RESTRICT dst) {
const int kBPS = BPS;
// kC1, kC2. Padded because vld1.16 loads 8 bytes
const int16_t constants[4] = { kC1, kC2, 0, 0 };
@ -1183,14 +1188,16 @@ static void TransformOne_NEON(const int16_t* in, uint8_t* dst) {
#endif // WEBP_USE_INTRINSICS
static void TransformTwo_NEON(const int16_t* in, uint8_t* dst, int do_two) {
static void TransformTwo_NEON(const int16_t* WEBP_RESTRICT in,
uint8_t* WEBP_RESTRICT dst, int do_two) {
TransformOne_NEON(in, dst);
if (do_two) {
TransformOne_NEON(in + 16, dst + 4);
}
}
static void TransformDC_NEON(const int16_t* in, uint8_t* dst) {
static void TransformDC_NEON(const int16_t* WEBP_RESTRICT in,
uint8_t* WEBP_RESTRICT dst) {
const int16x8_t DC = vdupq_n_s16(in[0]);
Add4x4_NEON(DC, DC, dst);
}
@ -1204,7 +1211,8 @@ static void TransformDC_NEON(const int16_t* in, uint8_t* dst) {
*dst = vgetq_lane_s32(rows.val[3], col); (dst) += 16; \
} while (0)
static void TransformWHT_NEON(const int16_t* in, int16_t* out) {
static void TransformWHT_NEON(const int16_t* WEBP_RESTRICT in,
int16_t* WEBP_RESTRICT out) {
int32x4x4_t tmp;
{
@ -1255,15 +1263,13 @@ static void TransformWHT_NEON(const int16_t* in, int16_t* out) {
//------------------------------------------------------------------------------
#define MUL(a, b) (((a) * (b)) >> 16)
static void TransformAC3_NEON(const int16_t* in, uint8_t* dst) {
static const int kC1_full = 20091 + (1 << 16);
static const int kC2_full = 35468;
static void TransformAC3_NEON(const int16_t* WEBP_RESTRICT in,
uint8_t* WEBP_RESTRICT dst) {
const int16x4_t A = vld1_dup_s16(in);
const int16x4_t c4 = vdup_n_s16(MUL(in[4], kC2_full));
const int16x4_t d4 = vdup_n_s16(MUL(in[4], kC1_full));
const int c1 = MUL(in[1], kC2_full);
const int d1 = MUL(in[1], kC1_full);
const int16x4_t c4 = vdup_n_s16(WEBP_TRANSFORM_AC3_MUL2(in[4]));
const int16x4_t d4 = vdup_n_s16(WEBP_TRANSFORM_AC3_MUL1(in[4]));
const int c1 = WEBP_TRANSFORM_AC3_MUL2(in[1]);
const int d1 = WEBP_TRANSFORM_AC3_MUL1(in[1]);
const uint64_t cd = (uint64_t)( d1 & 0xffff) << 0 |
(uint64_t)( c1 & 0xffff) << 16 |
(uint64_t)(-c1 & 0xffff) << 32 |
@ -1274,7 +1280,6 @@ static void TransformAC3_NEON(const int16_t* in, uint8_t* dst) {
const int16x8_t m2_m3 = vcombine_s16(vqsub_s16(B, c4), vqsub_s16(B, d4));
Add4x4_NEON(m0_m1, m2_m3, dst);
}
#undef MUL
//------------------------------------------------------------------------------
// 4x4
@ -1303,18 +1308,19 @@ static void DC4_NEON(uint8_t* dst) { // DC
static WEBP_INLINE void TrueMotion_NEON(uint8_t* dst, int size) {
const uint8x8_t TL = vld1_dup_u8(dst - BPS - 1); // top-left pixel 'A[-1]'
const uint8x8_t T = vld1_u8(dst - BPS); // top row 'A[0..3]'
const int16x8_t d = vreinterpretq_s16_u16(vsubl_u8(T, TL)); // A[c] - A[-1]
const uint16x8_t d = vsubl_u8(T, TL); // A[c] - A[-1]
int y;
for (y = 0; y < size; y += 4) {
// left edge
const int16x8_t L0 = ConvertU8ToS16_NEON(vld1_dup_u8(dst + 0 * BPS - 1));
const int16x8_t L1 = ConvertU8ToS16_NEON(vld1_dup_u8(dst + 1 * BPS - 1));
const int16x8_t L2 = ConvertU8ToS16_NEON(vld1_dup_u8(dst + 2 * BPS - 1));
const int16x8_t L3 = ConvertU8ToS16_NEON(vld1_dup_u8(dst + 3 * BPS - 1));
const int16x8_t r0 = vaddq_s16(L0, d); // L[r] + A[c] - A[-1]
const int16x8_t r1 = vaddq_s16(L1, d);
const int16x8_t r2 = vaddq_s16(L2, d);
const int16x8_t r3 = vaddq_s16(L3, d);
const uint8x8_t L0 = vld1_dup_u8(dst + 0 * BPS - 1);
const uint8x8_t L1 = vld1_dup_u8(dst + 1 * BPS - 1);
const uint8x8_t L2 = vld1_dup_u8(dst + 2 * BPS - 1);
const uint8x8_t L3 = vld1_dup_u8(dst + 3 * BPS - 1);
// L[r] + A[c] - A[-1]
const int16x8_t r0 = vreinterpretq_s16_u16(vaddw_u8(d, L0));
const int16x8_t r1 = vreinterpretq_s16_u16(vaddw_u8(d, L1));
const int16x8_t r2 = vreinterpretq_s16_u16(vaddw_u8(d, L2));
const int16x8_t r3 = vreinterpretq_s16_u16(vaddw_u8(d, L3));
// Saturate and store the result.
const uint32x2_t r0_u32 = vreinterpret_u32_u8(vqmovun_s16(r0));
const uint32x2_t r1_u32 = vreinterpret_u32_u8(vqmovun_s16(r1));
@ -1428,7 +1434,7 @@ static WEBP_INLINE void DC8_NEON(uint8_t* dst, int do_top, int do_left) {
if (do_top) {
const uint8x8_t A = vld1_u8(dst - BPS); // top row
#if defined(__aarch64__)
#if WEBP_AARCH64
const uint16_t p2 = vaddlv_u8(A);
sum_top = vdupq_n_u16(p2);
#else
@ -1511,7 +1517,7 @@ static WEBP_INLINE void DC16_NEON(uint8_t* dst, int do_top, int do_left) {
if (do_top) {
const uint8x16_t A = vld1q_u8(dst - BPS); // top row
#if defined(__aarch64__)
#if WEBP_AARCH64
const uint16_t p3 = vaddlvq_u8(A);
sum_top = vdupq_n_u16(p3);
#else
@ -1575,23 +1581,24 @@ static void TM16_NEON(uint8_t* dst) {
const uint8x8_t TL = vld1_dup_u8(dst - BPS - 1); // top-left pixel 'A[-1]'
const uint8x16_t T = vld1q_u8(dst - BPS); // top row 'A[0..15]'
// A[c] - A[-1]
const int16x8_t d_lo = vreinterpretq_s16_u16(vsubl_u8(vget_low_u8(T), TL));
const int16x8_t d_hi = vreinterpretq_s16_u16(vsubl_u8(vget_high_u8(T), TL));
const uint16x8_t d_lo = vsubl_u8(vget_low_u8(T), TL);
const uint16x8_t d_hi = vsubl_u8(vget_high_u8(T), TL);
int y;
for (y = 0; y < 16; y += 4) {
// left edge
const int16x8_t L0 = ConvertU8ToS16_NEON(vld1_dup_u8(dst + 0 * BPS - 1));
const int16x8_t L1 = ConvertU8ToS16_NEON(vld1_dup_u8(dst + 1 * BPS - 1));
const int16x8_t L2 = ConvertU8ToS16_NEON(vld1_dup_u8(dst + 2 * BPS - 1));
const int16x8_t L3 = ConvertU8ToS16_NEON(vld1_dup_u8(dst + 3 * BPS - 1));
const int16x8_t r0_lo = vaddq_s16(L0, d_lo); // L[r] + A[c] - A[-1]
const int16x8_t r1_lo = vaddq_s16(L1, d_lo);
const int16x8_t r2_lo = vaddq_s16(L2, d_lo);
const int16x8_t r3_lo = vaddq_s16(L3, d_lo);
const int16x8_t r0_hi = vaddq_s16(L0, d_hi);
const int16x8_t r1_hi = vaddq_s16(L1, d_hi);
const int16x8_t r2_hi = vaddq_s16(L2, d_hi);
const int16x8_t r3_hi = vaddq_s16(L3, d_hi);
const uint8x8_t L0 = vld1_dup_u8(dst + 0 * BPS - 1);
const uint8x8_t L1 = vld1_dup_u8(dst + 1 * BPS - 1);
const uint8x8_t L2 = vld1_dup_u8(dst + 2 * BPS - 1);
const uint8x8_t L3 = vld1_dup_u8(dst + 3 * BPS - 1);
// L[r] + A[c] - A[-1]
const int16x8_t r0_lo = vreinterpretq_s16_u16(vaddw_u8(d_lo, L0));
const int16x8_t r1_lo = vreinterpretq_s16_u16(vaddw_u8(d_lo, L1));
const int16x8_t r2_lo = vreinterpretq_s16_u16(vaddw_u8(d_lo, L2));
const int16x8_t r3_lo = vreinterpretq_s16_u16(vaddw_u8(d_lo, L3));
const int16x8_t r0_hi = vreinterpretq_s16_u16(vaddw_u8(d_hi, L0));
const int16x8_t r1_hi = vreinterpretq_s16_u16(vaddw_u8(d_hi, L1));
const int16x8_t r2_hi = vreinterpretq_s16_u16(vaddw_u8(d_hi, L2));
const int16x8_t r3_hi = vreinterpretq_s16_u16(vaddw_u8(d_hi, L3));
// Saturate and store the result.
const uint8x16_t row0 = vcombine_u8(vqmovun_s16(r0_lo), vqmovun_s16(r0_hi));
const uint8x16_t row1 = vcombine_u8(vqmovun_s16(r1_lo), vqmovun_s16(r1_hi));

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