What is WebP? Why should I use it?
WebP is a method of lossy and lossless compression that can be used on a large variety of photographic, translucent and graphical images found on the web. The degree of lossy compression is adjustable so a user can choose the trade-off between file size and image quality. WebP typically achieves an average of 30% more compression than JPEG and JPEG 2000, without loss of image quality (see Comparative Study).
The WebP format essentially aims at creating smaller, better looking images that can help make the web faster.
Which web browsers natively support WebP?
Webmasters interested in improving site performance can easily create optimized WebP alternatives for their current images, and serve them on a targeted basis to browsers that support WebP.
- WebP lossy support
- Google Chrome (desktop) 17+
- Google Chrome for Android version 25+
- Opera 11.10+
- Native web browser, Android 4.0+ (ICS)
- WebP lossy, lossless & alpha support
- Google Chrome (desktop) 23+
- Google Chrome for Android version 25+
- Opera 12.10+
- Native web browser, Android 4.2+ (JB-MR1)
- Pale Moon 26+
- WebP Animation support
- Google Chrome (desktop and Android) 32+
- Opera 19+
Also see the Wikipedia WebP article.
How can I detect browser support for WebP?
You'll want to serve WebP images only to clients that can display them properly, and fall back to legacy formats for clients that can't. Fortunately there are several techniques for detecting WebP support, both on the client-side and server-side. Some CDN providers offer WebP support detection as part of their service.
Server-side content negotiation via Accept headers
It's becoming more common for web clients to send an "Accept" request header, indicating which content formats they are willing to accept in response. If a browser indicates in advance that it will "accept" the image/webp format, the web server knows it can safely send WebP images, greatly simplifying content negotiation. See the following links for more information.
Modernizr
Modernizr is a JavaScript library for conviently detecting HTML5 and CSS3 feature support in web browsers. Look for the properties Modernizr.webp, Modernizr.webp.lossless, Modernizr.webp.alpha and Modernizr.webp.animation.
HTML5 <picture>
element
HTML5 supports a <picture>
element, which allows you to list multiple,
alternative image targets in priority order, such that a client will request
the first candidate image that it can display properly. See
this discussion on HTML5 Rocks. The <picture>
element is
supported by more browsers all the time.
In your own JavaScript
Another detection method is to attempt to decode a very small WebP image that uses a particular feature, and check for success. Example:
// check_webp_feature:
// 'feature' can be one of 'lossy', 'lossless', 'alpha' or 'animation'.
// 'callback(feature, result)' will be passed back the detection result (in an asynchronous way!)
function check_webp_feature(feature, callback) {
var kTestImages = {
lossy: "UklGRiIAAABXRUJQVlA4IBYAAAAwAQCdASoBAAEADsD+JaQAA3AAAAAA",
lossless: "UklGRhoAAABXRUJQVlA4TA0AAAAvAAAAEAcQERGIiP4HAA==",
alpha: "UklGRkoAAABXRUJQVlA4WAoAAAAQAAAAAAAAAAAAQUxQSAwAAAARBxAR/Q9ERP8DAABWUDggGAAAABQBAJ0BKgEAAQAAAP4AAA3AAP7mtQAAAA==",
animation: "UklGRlIAAABXRUJQVlA4WAoAAAASAAAAAAAAAAAAQU5JTQYAAAD/////AABBTk1GJgAAAAAAAAAAAAAAAAAAAGQAAABWUDhMDQAAAC8AAAAQBxAREYiI/gcA"
};
var img = new Image();
img.onload = function () {
var result = (img.width > 0) && (img.height > 0);
callback(feature, result);
};
img.onerror = function () {
callback(feature, false);
};
img.src = "data:image/webp;base64," + kTestImages[feature];
}
Note that image-loading is non-blocking and asynchronous. This means that any code that depends on WebP support should preferably be put in the callback function.
Why did Google release WebP as open source?
We deeply believe in the importance of the open source model. With WebP in open source, anyone can work with the format and suggest improvements. With your input and suggestions, we believe that WebP will become even more useful as a graphic format over time.
How can I convert my personal images files to WebP?
You can use the WebP command line utility to convert your personal image files to WebP format. See Using WebP for more details.
If you have many images to convert you can use your platform's shell to simplify the operation. For example, to convert all jpeg files in a folder try the following:
Windows:
> for /R . %I in (*.jpg) do ( cwebp.exe %I -o %~fnI.webp )
Linux / Mac:
$ for F in *.jpg; do cwebp $F -o `basename ${F%.jpg}`.webp; done
How can I judge WebP image quality for myself?
Currently, you can view WebP files by converting them into a common format that uses lossless compression, such as PNG, and then view the PNG files in any browser or image viewer. To get a quick idea of WebP quality, see the Gallery on this site for side-by-side photo comparisons.
How do I get the source code?
The converter code is available on the downloads section of the WebP open-source project page. The code for the lightweight decoder and the VP8 specification are on the WebM site. See the RIFF Container page for the container specification.
What is the maximum size a WebP image can be?
WebP is bitstream-compatible with VP8 and uses 14 bits for width and height. The maximum pixel dimensions of a WebP image is 16383 x 16383.
What color spaces does the WebP format support?
Consistent with the VP8 bitstream, lossy WebP works exclusively with an 8-bit Y'CbCr 4:2:0 (often called YUV420) image format. Please refer to Section 2, "Format Overview" of RFC 6386, VP8 Data Format and Decoding Guide for more detail.
Lossless WebP works exclusively with the RGBA format. See the WebP Lossless Bitstream specification.
Can a WebP image grow larger than its source image?
Yes, usually when converting from a lossy format to WebP lossless or vice versa. This is mainly due to the colorspace difference (YUV420 vs ARGB) and the conversion between these.
There are three typical situations:
- If the source image is in lossless ARGB format, the spatial downsampling to YUV420 will introduce new colors that are harder to compress than the original ones. This situation can typically happen when the source is in PNG format with few colors: converting to lossy WebP (or, similarly to a lossy JPEG) will potentially result in a larger file size.
- If the source is in lossy format, using lossless WebP compression to capture the lossy nature of the source will typically result in a larger file. This is not particular to WebP, and can occur when converting a JPEG source to lossless WebP or PNG formats, for instance.
- If the source is in lossy format and you are trying to compress it
as a lossy WebP with higher quality setting. For instance, trying to
convert a JPEG file saved at quality 80 to a WebP file with quality 95
will usually result in a larger file, even if both formats are lossy.
Assessing the source's quality is often impossible, so it is advised to
lower the target WebP quality if the file size is consistently larger.
Another possibility is to avoid using the quality setting, and instead
target a given file size using the
-size
option in thecwebp
tool, or the equivalent API. For instance, targeting 80% of the original file size might prove more robust.
Note that converting a JPEG source to lossy WebP, or a PNG source to lossless WebP are not prone to such file size surprises.
Does WebP support progressive or interlaced display?
WebP does not offer a progressive or interlaced decoding refresh in the JPEG or PNG sense. This is likely to put too much pressure on the CPU and memory of the decoding client as each refresh event involves a full pass through the decompression system.
On average, decoding a progressive JPEG image is equivalent to decoding the baseline one 3 times.
Alternatively, WebP offers incremental decoding, where all available incoming bytes of the bitstream are used to try and produce a displayable sample row as soon as possible. This both saves memory, CPU and re-paint effort on the client while providing visual cues about the download status. The incremental decoding feature is available through the Advanced Decoding API.
How do I use the libwebp Java bindings in my Android project?
WebP includes support for JNI bindings to the simple encoder and decoder
interfaces in the swig/
directory.
Building the library in Eclipse:
- Make sure you have the ADT plugin installed along the with NDK tools and your NDK path is set correctly (Preferences > Android > NDK).
- Create a new project: File > New > Project > Android Application Project.
- Clone or
unpack libwebp to a folder named
jni
in the new project. - Add
swig/libwebp_java_wrap.c
to theLOCAL_SRC_FILES
list. - Right-click on the new project and select Android Tools > Add Native Support ... to include the library in your build.
Open the project properties and go to C/C++ Build > Behaviour. Add
ENABLE_SHARED=1
to theBuild (Incremental build)
section to build libwebp as a shared library.Note Setting
NDK_TOOLCHAIN_VERSION=4.8
will in general improve 32-bit build performance.Add
swig/libwebp.jar
to thelibs/
project folder.Build your project. This will create
libs/<target-arch>/libwebp.so
.Use
System.loadLibrary("webp")
to load the library at runtime.
Note that the library can be built manually with ndk-build
and the included
Android.mk
. Some of the steps described above can be reused in that case.
How do I use libwebp with C#?
WebP can be built as a DLL which exports the libwebp API. These functions can then be imported in C#.
Build libwebp.dll. This will set WEBP_EXTERN properly to export the API functions.
libwebp> nmake /f Makefile.vc CFG=release-dynamic
Add libwebp.dll to your project and import the desired functions. Note if you use the simple API you should call
WebPFree()
to free any buffers returned.[DllImport("libwebp.dll", CallingConvention = CallingConvention.Cdecl)] static extern int WebPEncodeBGRA(IntPtr rgba, int width, int height, int stride, float quality_factor, out IntPtr output); [DllImport("libwebp.dll", CallingConvention = CallingConvention.Cdecl)] static extern int WebPFree(IntPtr p); void Encode() { Bitmap source = new Bitmap("input.png"); BitmapData data = source.LockBits( new Rectangle(0, 0, source.Width, source.Height), ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb); IntPtr webp_data; const int size = WebPEncodeBGRA(data.Scan0, source.Width, source.Height, data.Stride, 80, out webp_data); // ... WebPFree(webp_data); }
Why should I use animated WebP?
Advantages of animated WebP compared to animated GIF
WebP supports 24-bit RGB color with an 8-bit alpha channel, compared to GIF's 8-bit color and 1-bit alpha.
WebP supports both lossy and lossless compression; in fact, a single animation can combine lossy and lossless frames. GIF only supports lossless compression. WebP's lossy compression techniques are well-suited to animated images created from real-world videos, an increasingly popular source of animated images.
WebP requires fewer bytes than GIF1. Animated GIFs converted to lossy WebPs are 64% smaller, while lossless WebPs are 19% smaller. This is especially important on mobile networks.
WebP takes less time to decode in the presence of seeking. In Blink, scrolling or changing tabs can hide and show images, resulting in animations being paused and then skipped forward to a different point. Excessive CPU usage that results in animations dropping frames can also require the decoder to seek forward in the animation. In these scenarios, animated WebP takes 0.57x as much total decode time2 as GIF, resulting in less jank during scrolling and faster recovery from CPU utilization spikes. This is due to two advantages of WebP over GIF:
WebP images store metadata about whether each frame contains alpha, eliminating the need to decode the frame to make this determination. This leads to more accurate inference of which previous frames a given frame depends on, thereby reducing unnecessary decoding of previous frames.
Much like a modern video encoder, the WebP encoder heuristically adds key-frames at regular intervals (which most GIF encoders do not do). This dramatically improves seeking in long animations. To facilitate inserting such frames without significantly increasing image size, WebP adds a 'blending method' flag for each frame in addition to the frame disposal method that GIF uses. This allows a keyframe to draw as if the entire image had been cleared to the background color without forcing the previous frame to be full-size.
Disadvantages of animated WebP compared to animated GIF
In the absence of seeking, straight-line decoding of WebP is more CPU-intensive than GIF. Lossy WebP takes 2.2x as much decode time as GIF, while lossless WebP takes 1.5x as much.
WebP support is not nearly as widespread as GIF support, which is effectively universal.
Adding WebP support to browsers increases the code footprint and attack surface. In Blink this is approximately 1500 additional lines of code (including the WebP demux library and Blink-side WebP image decoder). Note that this problem could be reduced in the future if WebP and WebM share more common decoding code, or if WebP's capabilities are subsumed in WebM's.
Why not simply support WebM in <img>
?
It may make sense long-term to support video formats inside the <img>
tag. However, doing so now, with the intent that WebM in <img>
can fill
the proposed role of animated WebP, is problematic:
When decoding a frame that relies on previous frames, WebM requires 50% more memory than animated WebP to hold the minimum number of previous frames3.
Video codec and container support varies widely across browsers and devices. To facilitate automatic content transcoding (e.g. for bandwidth-saving proxies), browsers would need to add accept headers indicating what formats their image tags support. Even this might be insufficient, as MIME types like "video/webm" or "video/mpeg" still don't indicate the codec support (e.g. VP8 vs. VP9). On the other hand, the WebP format is effectively frozen, and if vendors who ship it agree to ship animated WebP, the behavior of WebP across all UAs should be consistent; and since the "image/webp" accept header is already used to indicate WebP support, no new accept header changes are necessary.
The Chromium video stack is optimized for smooth playback, and assumes there's only one or two videos playing at a time. As a result, the implementation is aggressive in consuming system resources (threads, memory, etc.) to maximize playback quality. Such an implementation does not scale well to many simultaneous videos and would need to be redesigned to be suitable for use with image-heavy webpages.
WebM does not currently incorporate all the compression techniques from WebP. As a result, this image compresses significantly better with WebP than the alternatives:
1 For all comparisons between animated GIF and animated WebP, we used a corpus of about 7000 animated GIF images taken randomly from the web. These images were converted to animated WebP using the 'gif2webp' tool using default settings (built from the latest libwebp source tree as of 10/08/2013). The comparative numbers are the average values across these images.
2 The decode times were computed using the latest libwebp + ToT Blink as of 10/08/2013 using a benchmark tool. "Decode time with seeking" is computed as "Decode the first five frames, clear the frame buffer cache, decode the next five frames, and so forth".
3 WebM keeps 4 YUV reference frames in memory, with each frame
storing (width+96)*(height+96) pixels. For YUV4:2:0, we need 4 bytes per 6
pixels (or 3/2 bytes per pixel). So, these reference frames use
4*3/2*(width+96)*(height+96)
bytes of memory. WebP on the other hand would
only need the previous frame (in RGBA) to be available, which is
4*width*height
bytes of memory.
4 Animated WebP rendering requires Google Chrome version 32+