libwebp2: Upstream sync

Squashed commits:
c77f16a1feaca094e8bef4c1126533b077eae46a Merge "Fix assert in BITTRACE+DBG mode"
61f61f3ed67a56ffc9cd99a025b35ad25aa9a0cf Fix assert in BITTRACE+DBG mode
984e444dc24df5b8d4b05748203d60876256a560 wp2: Fix aom_utils inspection (retrieve blocks)
4b00934f8529546a79458d2cba1f51d9592c5e5c Enable palette+spatial at speed 9
7a8a79377d2de81fe3b900cbac4edd3d0c185f77 Merge "wp2: Avoid calling SyntaxWriter::InitPass() twice"
b114d51aea055f84f93e34e296b600cff217cf6e QuantMatrix: use one big matrix for all transforms
caaba60116d7ced92ed9d62332664839d164814b wp2: Avoid calling SyntaxWriter::InitPass() twice
1be8c6f987118308de236a8a9528f556e2b0f2e1 Add more flexibility to image transforms.
384dd9bc1d4ffbdcc6ef0bfed0b78254e79bf6dc Quantizer: simplify qmatrix and segments
e3eaea27d5d1055067c21a5108a836b4b25c3232 Merge "TiffDec: enforce stricter mem/dimension limit on tiles"
9ad0c51c9aa8b5852bd64ed80bea5dd5bcb4e966 SymbolsInfo: de-inline / move some code around
78752ec980d19d4a748a09cf0708f7fef9b6d95f CountsBuffer: simplify
7dd50ac7e20003e257740027989c4e1240aad585 some cleanup around Symbols
c6209c7a014e495fbdb6bfed183e3ef57889038b vwp2: Fix DisplayForcedSegments()
996c8d4fa0e8a25228415ea9ecacf402d4400b7e wp2: Split monoliths in src/enc/partitioning
d5153ee58974e668d67c485734411c6a022dbfd0 Change signatures: cluster/sym -> sym/cluster
b6ba72e2d09777b3ad1674b7eefdc0d5e113f08f wp2: Move files to src/enc/partitioning
0ec6db36b5f1c4ad71cf3776d9d6db63c6d38e54 Merge "SymbolCounter::Allocate: no need to sort symbols"
ed693a2e88d8b6c0554adef71e803f9221e5cd6e SymbolCounter::Allocate: no need to sort symbols
3976b7767d784140a7b1f99649975e7431b1624b cleanup: simplify test_coded_block.
93ef5a80661c4009d48f26f3a05d8dad39524f86 TiffDec: check that memory estimate
dbdf35b93aa52cc165655c99b07589357124c3ae Do not count WP2_ENC_DEC_MATCH tokens in the total ANS cost.
d362e8e405580a06f70e3e048df40cd34dfd7c42 Deblock split_tf edges.
bfb89f37ea5fd8a92c32e7dec58d9e5922fe9f8e remove unused SymbolDecoderContext
d3f1ee14fd224fbd8e9c03bd6040bc0c02b58b21 Merge "Extend the bottom left context for angle predictors > 180°."
7c3bb5c9bcb28fb097dc75e9124aa29078e2419f Cleanup: Remove QuantStats + AOMContext
c2316eed92c63f70185b6e06d3a244cccd30adfa Merge "Cleanup: remove unused SourceStats, ..."

Change-Id: Ie9db6e55a5b3f7601484adf64e180882bebbeadc
Reviewed-on: https://chromium-review.googlesource.com/c/codecs/libwebp2/+/2633268
Reviewed-by: Pascal Massimino <skal@google.com>
Tested-by: Pascal Massimino <skal@google.com>
Verified-Ubuntu: Pascal Massimino <skal@google.com>
93 files changed
tree: 50e031df8e88303906fa5adcad5cba8b2c680f71
  1. API.txt
  2. AUTHORS
  3. CMakeLists.txt
  4. CONTRIBUTING.md
  5. LICENSE
  6. Makefile
  7. README.md
  8. README.wp2_js
  9. cmake/
  10. codereview.settings
  11. doc/
  12. examples/
  13. extras/
  14. imageio/
  15. kokoro/
  16. man/
  17. src/
  18. swig/
  19. tests/
  20. wp2_js/
README.md

WebP 2

WebP 2 is the successor of the WebP image format, currently in development. It is not ready for general use, and the format is not finalized so changes to the library can break compatibility with images encoded with previous versions. USE AT YOU OWN RISK!

This package contains the library that can be used in other programs to encode or decode Webp 2 images, as well as command line tools.

See http://developers.google.com/speed/webp for the first version of WebP .

What to expect?

The WebP 2 experimental codec is mostly pushing the features of WebP further in terms of compression efficiency. The new features (like 10b HDR support) are kept minimal. The axis of experimentation are:

  • more efficient lossy compression (~30% better than WebP, as close to AVIF as possible)
  • better visual degradation at very low bitrate
  • improved lossless compression
  • improved transparency compression
  • animation support
  • ultra-light previews
  • lightweight incremental decoding
  • small container overhead, tailored specifically for image compression
  • full 10bit architecture (HDR10)
  • strong focus on software implementation, fully multi-threaded

The use cases remain mostly the same as WebP: transfer over the wire, faster web, smaller apps, better user experience... WebP 2 is primarily tuned for the typical content available on the Web and Mobile apps: medium-range dimensions, transparency, short animations, thumbnails.

WebP2 is currently only partially optimized and, roughly speaking 5x slower than WebP for lossy compression. It still compresses 2x faster than AVIF, but takes 3x more time to decompress. The goal is to reach decompression speed parity.

Building

Prerequisites

A compiler (e.g., gcc 6+, clang 7+ or Microsoft Visual Studio 2017+ are recommended) and CMake.

On a Debian-like system the following should install everything you need for a minimal build:

$ sudo apt-get install build-essential cmake

Compiling

$ mkdir build && cd build
$ cmake ..
$ make -j

Configuration options:

  • WP2_ENABLE_SIMD: enable any SIMD optimization.
  • WP2_ENABLE_BITTRACE: enable tracing.

For additional options see:

$ cmake .. -LH

Binaries

cwp2

cwp2 is a tool to encode images in webp2.

Usage:

$ cwp2 in_file [options] [-o out_file]

Example for a single image:

$ cwp2 -q 70 input.png -o output.wp2

Example for an animation, with list of frames and durations in ms:

$ cwp2 -q 70 -f frame1.png 10 frame2.png 20 frame3.png 5 -o output.wp2

Important options:

FlagDefault valueDescription
-o <string>output file path
-q <float>75image quality factor [0=lossy : 100=lossless]*
-alpha_q <float>100alpha quality factor [0=lossy : 100=lossless]*
-effort <int>5compression effort [0=fast : 9=slower/better]
-f [<str> <int>]create an animation (alternate image, duration)

* The quality factor range corresponds to:

Quality factorMeaning
0Lossy compression, smallest file size and worst quality
...Lossy compression
95Lossy compression, biggest file size and best quality
96Near-lossless compression (maximum preprocessing)
...Near-lossless compression
99Near-lossless compression (minimum preprocessing)
100Lossless compression

Use cwp2 -h to see a full list of available options.

dwp2

dwp2 is a tool to decode webp2 images.

Usage:

$ dwp2 in_file [options] [-o out_file]

Use dwp2 -h to see a full list of available options.

vwp2

vwp2 is a visual inspection and debugging tool. You need OpenGL and GLUT to build it.

Screenshot of vwp2

To open any image (jpeg, png, etc.) then compress it in WebP 2 and view the result:

$ vwp2 in_file...

vwp2 takes most of the same flags as cwp2, e.g. -q for quality. Encoding parameters can also be changed dynamically in the tool using key bindings.

Press h to a list of key bindings.

Use the top left menu or press v and shift+v to cycle between views.

Press i to show or hide info (note this hides the menu).

To view an already compressed file, use:

$ vwp2 -d path/to/image.wp2

rd_curve

rd_curve is a command-line tool for compressing images at multiple quality levels using different codecs (webp2, webp, jpeg, av1) to create rate-distortion curves (rd curves). An rd curve is a plot of distortion (difference between source and encoded image) vs bits per pixel, for different quality settings.

$ rd_curve [options] input_file

rd_curve takes most of the same flags as cwp2, e.g. -q for quality, -effort, and so on.

By default, only the webp2 codec is used. Use -webp, -jpeg or -av1 flags to add other codecs.

By default, results are printed as plain text on standard output.

With the -html flag, rd_curve outputs an html file. It also saves compressed images (turns on the -save option). Use the -save_folder option to set the directory where images are saved.

$ rd_curve input.png -webp -jpeg -av1 -html -save_folder $(pwd) > myfile.html

get_disto

get_disto computes the difference between two images (typically the compressed file and the original file)

$ get_disto [options] compressed_file orig_file

get_disto outputs in order:

  • compressed file size
  • overall PSNR (or other metric, if specified through flags)
  • PSNR (or other metric) for A, R, G and B channels, in order
  • compressed file bits per pixel

API

Encoding API

Encoding functions are available in the header src/wp2/encode.h.

Encoding an image

#include "imageio/image_dec.h"
#include "src/wp2/base.h"
#include "src/wp2/encode.h"

WP2::ArgbBuffer input_buffer;
WP2Status status = WP2::ReadImage("path/to/image.png", &input_buffer);
if (status != WP2_STATUS_OK) { /* handle error */ }
WP2::EncoderConfig config;
config.quality = 70;
WP2::MemoryWriter writer;
status = WP2::Encode(input_buffer, &writer, config);
if (status != WP2_STATUS_OK) { /* handle error */ }
// do something with writer.mem_

Encoding an animation

#include "imageio/image_dec.h"
#include "src/wp2/base.h"
#include "src/wp2/encode.h"

WP2::ArgbBuffer frame1, frame2;
WP2Status status = WP2::ReadImage("path/to/frame1.png", &frame1);
if (status != WP2_STATUS_OK) { /* handle error */ }
status = WP2::ReadImage("path/to/frame2.png", &frame2);
if (status != WP2_STATUS_OK) { /* handle error */ }

WP2::AnimationEncoder encoder;
status = encoder.AddFrame(frame1, /*duration_ms=*/100);
if (status != WP2_STATUS_OK) { /* handle error */ }
status = encoder.AddFrame(frame2, /*duration_ms=*/50);
if (status != WP2_STATUS_OK) { /* handle error */ }

WP2::EncoderConfig config;
config.quality = 70;
WP2::MemoryWriter writer;
status = encoder.Encode(&writer, config, /*loop_count=*/1);
if (status != WP2_STATUS_OK) { /* handle error */ }
// do something with writer.mem_

Decoding API

Decoding functions are available in the header src/wp2/decode.h.

Simple decoding

This is mainly just one function to call:

#include "src/wp2/base.h"
#include "src/wp2/decode.h"

const std::string data = ...
WP2::ArgbBuffer output_buffer;
WP2Status status = WP2::Decode(data, &output_buffer);

If the file is a WebP 2 animation, output_buffer will contain the first frame.

Please have a look at the file src/wp2/decode.h for further details.

Animation decoding

To decode all the frames of an animation, the more advanced Decoder API can be used. See tests/test_decoder_api.cc for common use cases.

WP2::ArrayDecoder decoder(data, data_size);
uint32_t duration_ms;
while (decoder.ReadFrame(&duration_ms))  {
  // A frame is ready. Use or copy its 'duration_ms' and 'decoder.GetPixels()'.
}
if (decoder.GetStatus() != WP2_STATUS_OK) { /* error */ }

Incremental decoding

If you want to start decoding before all the data is available, you can use the Decoder API. Use an WP2::ArrayDecoder if the data is stored in an array that progressively gets larger, with old bytes still available as new bytes come in. Use a WP2::StreamDecoder if data is streamed, with old bytes no longer available as new bytes come in. You can also subclass WP2::CustomDecoder to fit your needs. See tests/test_decoder_api.cc for common use cases.

Below is an example with WP2::StreamDecoder.

WP2::StreamDecoder decoder;
while (/*additional data is available in some 'new_data[]' buffer*/) {
  decoder.AppendInput(new_data, new_data_size);
  while (decoder.ReadFrame()) {
    // ReadFrame() returns true when an entire frame is available
    // (a still image is considered as a single-frame animation).
    // The canvas is stored in GetPixels() till the next call to ReadFrame().

    // Use the whole GetPixels().
  }
  if (decoder.Failed()) break;
  if (!decoder.GetDecodedArea().IsEmpty()) {
    // Use the partially GetDecodedArea() of GetPixels().
  }
}
if (decoder.GetStatus() != WP2_STATUS_OK) { /* error */ }

Development

Bugs

Please report all bugs to the issue tracker: https://bugs.chromium.org/p/webp2

Contributing

See CONTRIBUTING.md for details on how to submit patches.

One of the easiest ways to contribute is to report cases with compression artifacts or surprising output size. These ‘bad cases’ are very useful to help improve the compression library!

Please use the tracker to report such issues, making sure to include:

  • the version or revision used (using “git rev-parse HEAD” for instance)

  • the version of the compiler used (if you compiled your own version)

  • the problematic source image (will only be used for debugging and discarded afterward!)

  • the exact command line to use to reproduce the issue

  • the output file, if applicable.

Coding conventions and style

  • Code must follow the Google C++ style guide unless local style differs.

  • const is used for variables everywhere possible, including for pointers in function declarations. Input parameters use const references.

    void DoSomething(const Type1& const input, Type2* const out)
    
  • Do not use C++ exceptions.

  • Do not use std containers in the main library, e.g. no std::vector/set/map (but they can be used in tests). For vectors, use WP2::Vector instead.

  • Use uint32_t for sizes, width, height, loop indices, etc.

  • Most functions should return a WP2Status

Google Test Integration

A part of testing support is built using Google Test. To enable it the WP2_ENABLE_TESTS cmake variable must be turned on at cmake generation time (ON by default), and the GTEST_SOURCE_DIR cmake variable must be set to the path of the Google Test source directory (../googletest by default):

$ git clone https://github.com/google/googletest.git path/to/googletest
$ cmake path/to/wp2 -DWP2_ENABLE_TESTS=ON -DGTEST_SOURCE_DIR=path/to/googletest

To run the tests you can use ctest after the build:

$ make
$ ctest

Discussion

Email: webp-discuss@googlegroups.com

Web: https://groups.google.com/forum/#!forum/webp-discuss