gowebp

package module
v0.1.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Apr 14, 2026 License: MIT Imports: 13 Imported by: 0

README

Codecov Coverage Go Reference

Native WebP for Go

This is a native WebP encoder written entirely in Go, with no dependencies on libwebp or other external libraries. Designed for performance and efficiency, this encoder generates smaller files than the standard Go PNG encoder and is approximately 50% faster in execution.

Supported output formats:

  • VP8L (lossless) — default, used when Options.Lossy is false or Options is nil. Preserves every pixel exactly.

  • VP8 (lossy) — enabled by Options.Lossy = true. Pure-Go VP8 keyframe encoder supporting I16 (4 modes), B_PRED (10 I4 modes per 4×4 sub-block), UV8 chroma prediction, DCT + Walsh-Hadamard transforms, round-to-nearest quantization, context-adaptive boolean arithmetic coding of coefficient tokens, the decoder-side loop filter, and per-MB I16/B_PRED arbitration at Method=3.

    Measured RGB-PSNR (spec-correct, limited-range BT.601) on smooth content: ~41 dB at Q=90, ~40 dB at Q=75, ~32 dB at Q=50 — visually lossless at high Q and comparable to cwebp within a few dB. Files are roughly 1.5–3× cwebp's size at the same quality setting; closing that gap with full rate-distortion optimization and trellis quantization is future work.

    BT.601 range note: VP8 uses limited-range BT.601 YCbCr (luma 16–235) per RFC 6386. Go's stdlib image/color.YCbCrToRGB uses JFIF full-range BT.601, so when you decode a lossy WebP with golang.org/x/image/webp and convert to RGB via .At().RGBA(), colors shift 2–5 units per channel — making Go's naive RGB-PSNR look like ~28 dB even on near-perfect output. Real VP8 decoders (libwebp, browsers) apply the correct inverse and show the encoder's true quality. This is a Go stdlib issue, not an encoder bug.

  • Animation (ANIM/ANMF) — supported for both VP8L and VP8 frames. EncodeAll respects Options.Lossy per-animation.

Decoding Support

We provide WebP decoding through a wrapper around golang.org/x/image/webp, with an additional DecodeIgnoreAlphaFlag function to handle VP8X images where the alpha flag causes decoding issues.

Benchmark

We conducted a quick benchmark to showcase file size reduction and encoding performance. Using an image from Google’s WebP Lossless and Alpha Gallery, we compared the results of our gowebp encoder with the standard PNG encoder.

For the PNG encoder, we applied the png.BestCompression setting to achieve the most competitive compression outcomes.

PNG encoder nativeWebP encoder reduction

file size 120 kb 96 kb 20% smaller
encoding time 42945049 ns/op 27716447 ns/op 35% faster

file size 46 kb 36 kb 22% smaller
encoding time 98509399 ns/op 31461759 ns/op 68% faster

file size 236 kb 194 kb 18% smaller
encoding time 178205535 ns/op 102454192 ns/op 43% faster

file size 53 kb 41 kb 23% smaller
encoding time 29088555 ns/op 14959849 ns/op 49% faster

file size 139 kb 123 kb 12% smaller
encoding time 63423995 ns/op 21717392 ns/op 66% faster

image source: https://developers.google.com/speed/webp/gallery2

Installation

To install the gowebp package, use the following command:

go get github.com/KarpelesLab/gowebp

Usage

Here’s a simple example of how to encode an image losslessly (VP8L):

file, err := os.Create(name)
if err != nil {
  log.Fatalf("Error creating file %s: %v", name, err)
}
defer file.Close()

err = gowebp.Encode(file, img, nil)
if err != nil {
  log.Fatalf("Error encoding image to WebP: %v", err)
}

Or encode with lossy VP8 compression:

err = gowebp.Encode(file, img, &gowebp.Options{
  Lossy:   true,
  Quality: 75, // 0 (smallest) to 100 (best); 75 is a reasonable default
  Method:  3,  // speed/quality tradeoff
})

Method levels (measured on i9-14900K, 256×256 image):

Method Description Speed File size Quality
0 I16 with DC_PRED only fastest baseline baseline
1 I16 with 4-mode SSE search (DC/V/H/TM) +40% = +1-3 dB
2 B_PRED with 10 I4 modes per 4×4 sub-block +55% +5% +2-5 dB
3 Per-MB I16/B_PRED arbitration (prediction-SSE) slightly smaller good default
4 Per-MB arbitration with I16 reconstruction RDO 2.5× smallest recommended
5 Dual-path arbitration (both sides measured) 2.8× = reference
6 Adds trailing-coefficient trellis trim 2.9× ≤ M5 for textured content

On natural content, Method=4 produces both smaller files AND higher PSNR than Method=3, at a reasonable speed overhead. It's recommended for most use cases. Method=5 is a more principled but rarely- different reference; Method=6 adds a simple trellis that helps on textured content where post-quantization noise survives. Higher levels (>6) currently behave like 6.

Encoding is goroutine-safe — each Encode call is self-contained and has no shared mutable state.

Here’s a simple example of how to encode an animation:

file, err := os.Create(name)
if err != nil {
  log.Fatalf("Error creating file %s: %v", name, err)
}
defer file.Close()

ani := gowebp.Animation{
  Images: []image.Image{
    frame1,
    frame2,
  },
  Durations: []uint {
    100,
    100,
  },
  Disposals: []uint {
    0,
    0,
  },
  LoopCount: 0,
  BackgroundColor: 0xffffffff,
}

err = gowebp.EncodeAll(file, &ani, nil)
if err != nil {
  log.Fatalf("Error encoding WebP animation: %v", err)
}

Pass &gowebp.Options{Lossy: true, Quality: 75} to EncodeAll to produce an animation whose frames use VP8 (lossy) instead of VP8L.

Implementation notes and references

The VP8 encoder in internal/vp8enc/ is a pure-Go implementation built against the RFC 6386 specification (The VP8 Data Format and Decoding Guide). The following open-source implementations were consulted as references for bit-exact roundtrip compatibility; no code was copied, but table values (which are specification constants) were transcribed:

  • golang.org/x/image/vp8 — pure-Go VP8 decoder, used as the round-trip test oracle (BSD-3-Clause).
  • libwebp — the reference C encoder/decoder from Google (BSD-3-Clause).
  • libvpx — VP8/VP9 reference codec (BSD-3-Clause).

Every file in internal/vp8enc/ includes an RFC 6386 section pointer and cross-reference to the equivalent path in the x/image/vp8 decoder, which is what the encoder is verified against in the roundtrip tests.

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func Decode

func Decode(r io.Reader) (image.Image, error)

Decode reads a WebP image from the provided io.Reader and returns it as an image.Image.

This function is a wrapper around the underlying WebP decode package (golang.org/x/image/webp). It supports both lossy and lossless WebP formats, decoding the image accordingly.

Parameters:

r - The source io.Reader containing the WebP encoded image.

Returns:

The decoded image as image.Image or an error if the decoding fails.

func DecodeConfig

func DecodeConfig(r io.Reader) (image.Config, error)

DecodeConfig reads the image configuration from the provided io.Reader without fully decoding the image.

This function is a wrapper around the underlying WebP decode package (golang.org/x/image/webp) and provides access to the image's metadata, such as its dimensions and color model. It is useful for obtaining image information before performing a full decode.

Parameters:

r - The source io.Reader containing the WebP encoded image.

Returns:

An image.Config containing the image's dimensions and color model, or an error if the configuration cannot be retrieved

func DecodeIgnoreAlphaFlag

func DecodeIgnoreAlphaFlag(r io.Reader) (image.Image, error)

DecodeIgnoreAlphaFlag reads a WebP image from the provided io.Reader and returns it as an image.Image.

This function fixes x/image/webp rejecting VP8L images with the VP8X alpha flag, expecting an ALPHA chunk. VP8L handles transparency internally, and the WebP spec requires the flag for transparency.

This function is a wrapper around the underlying WebP decode package (golang.org/x/image/webp). It supports both lossy and lossless WebP formats, decoding the image accordingly.

Parameters:

r - The source io.Reader containing the WebP encoded image.

Returns:

The decoded image as image.Image or an error if the decoding fails.

func Encode

func Encode(w io.Writer, img image.Image, o *Options) error

Encode writes the provided image.Image to the specified io.Writer in WebP format.

This function always encodes the image using VP8L (lossless WebP). If `UseExtendedFormat` is enabled, it wraps the VP8L frame inside a VP8X container, allowing the use of metadata such as EXIF, ICC color profiles, or XMP metadata.

Note: VP8L already supports transparency, so VP8X is **not required** for alpha support.

Parameters:

w   - The destination writer where the encoded WebP image will be written.
img - The input image to be encoded.
o   - Pointer to Options containing encoding settings:
      - UseExtendedFormat: If true, wraps the image in a VP8X container to enable
        extended WebP features like metadata.

Returns:

An error if encoding fails or writing to the io.Writer encounters an issue.

func EncodeAll

func EncodeAll(w io.Writer, ani *Animation, o *Options) error

EncodeAll writes the provided animation sequence to the specified io.Writer in WebP format.

This function encodes a list of frames as a WebP animation using the VP8X container, which supports features like looping, frame timing, disposal methods, and background color settings. Each frame is individually compressed using the VP8L (lossless) format.

Note: Even if `UseExtendedFormat` is not explicitly set, animations always use the VP8X container because it is required for WebP animation support.

Parameters:

w   - The destination writer where the encoded WebP animation will be written.
ani - Pointer to Animation containing the frames and animation settings:
      - Images: List of frames to encode.
      - Durations: Display times for each frame in milliseconds.
      - Disposals: Disposal methods after frame display (keep or clear).
      - LoopCount: Number of times the animation should loop (0 = infinite).
      - BackgroundColor: Background color for the canvas, used when clearing.
o   - Pointer to Options containing additional encoding settings:
      - UseExtendedFormat: Currently unused for animations, but accepted for consistency.

Returns:

An error if encoding fails or writing to the io.Writer encounters an issue.

Types

type Animation

type Animation struct {
	Images          []image.Image
	Durations       []uint
	Disposals       []uint
	LoopCount       uint16
	BackgroundColor uint32
}

Animation holds configuration settings for WebP animations.

It allows encoding a sequence of frames with individual timing and disposal options, supporting features like looping and background color settings.

Fields:

  • Images: A list of frames to be displayed in sequence.
  • Durations: Timing for each frame in milliseconds, matching the Images slice.
  • Disposals: Disposal methods for frames after display; 0 = keep, 1 = clear to background.
  • LoopCount: Number of times the animation should repeat; 0 means infinite looping.
  • BackgroundColor: Canvas background color in BGRA order, used for clear operations.

type Options

type Options struct {
	UseExtendedFormat bool
	Lossy             bool
	Quality           float32
	Method            int
}

Options holds configuration settings for WebP encoding.

Fields:

  • UseExtendedFormat: If true, wraps the VP8L frame inside a VP8X container to enable metadata support. This does not affect image compression or encoding itself, as VP8L remains the encoding format.
  • Lossy: If true, encode as VP8 (lossy). Otherwise (default) encode as VP8L (lossless), preserving existing behavior byte-for-byte.
  • Quality: Lossy quality in [0, 100]. Higher values preserve more detail. Default (when zero) is 75. Ignored when Lossy is false.
  • Method: Lossy speed/quality tradeoff in [0, 6]. Higher values spend more time searching for better compression. Default 4. Ignored when Lossy is false.

Directories

Path Synopsis
internal
vp8enc
Package vp8enc implements a VP8 (lossy) keyframe encoder for WebP.
Package vp8enc implements a VP8 (lossy) keyframe encoder for WebP.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL