Donner SVG main
0.8.0 ยท 382bd0190.8.0 main
SVG editor and embeddable C⁠+⁠+⁠20 engine.
Loading...
Searching...
No Matches
donner::svg::GifEncoder Class Reference

Incremental in-memory encoder for looping animated GIF89a images. More...

#include "donner/svg/renderer/GifEncoder.h"

Classes

struct  Rgb
 An opaque 8-bit sRGB color. More...
struct  Options
 Encoder configuration. More...

Public Types

enum class  Error {
  None ,
  InvalidConfiguration ,
  InvalidFrame ,
  ResourceLimit ,
  Finished
}
 Reason the most recent operation failed. More...

Public Member Functions

 GifEncoder (const Options &options)
 Create an encoder and write the GIF header, logical screen descriptor and NETSCAPE2.0 loop extension.
bool addFrame (std::span< const uint8_t > rgbaPixels, size_t strideInPixels, uint16_t delayCentiseconds)
 Add one animation frame.
std::vector< uint8_t > finish ()
 Flush the last frame, write the trailer, and return the encoded GIF.
int storedFrameCount () const
 Number of frames stored so far, after merging identical consecutive frames. The pending last frame is included.
Error error () const
 Reason the most recent operation failed, or Error::None after a successful operation.

Static Public Member Functions

static std::optional< size_t > WorkspaceUpperBound (int width, int height)
 Conservative encoder-owned workspace needed for a steady-state frame of this size.
static std::vector< uint16_t > FrameDelaysCentiseconds (double fps, int frameCount)
 Split an animation into per-frame GIF delays.

Static Public Attributes

static constexpr size_t kMaximumOutputBytes = 256 * 1024 * 1024
 Hard limit on the complete retained GIF file. A vector growth may transiently retain its old allocation too, so this is an encoded-byte limit rather than an exact process-RSS limit.
static constexpr size_t kMaximumWorkspaceBytes = 256 * 1024 * 1024
 Hard limit on non-output encoder work buffers, excluding caller-owned pixels.

Friends

class GifEncoderTestPeer

Detailed Description

Incremental in-memory encoder for looping animated GIF89a images.

Frames are RGBA8 bitmaps with straight (non-premultiplied) alpha, all the size given in Options. Each frame gets its own color table: a frame with at most 256 distinct colors (255 without Options::background, since every frame of a transparent GIF reserves one entry for transparency) is stored losslessly, and a frame with more colors is reduced with weighted median cut, which keeps the dominant flat colors of a diagram exact and spends the remaining entries on anti-aliased edges.

Output size is reduced in two ways:

  • A frame identical to its predecessor extends the previous frame's delay instead of being stored again. This never changes decoded pixels.
  • With an opaque background, each frame stores only the rectangle that changed since the previous frame. The frame's color table then only has to cover that rectangle, so a frame that needs quantization may quantize differently than it would uncropped.

Usage:

GifEncoder encoder({.width = 320, .height = 200});
encoder.addFrame(rgbaPixels, 0, 5); // 5 centiseconds, i.e. 20 fps.
std::vector<uint8_t> gif = encoder.finish();
GifEncoder(const Options &options)
Create an encoder and write the GIF header, logical screen descriptor and NETSCAPE2....

Class Documentation

◆ donner::svg::GifEncoder::Options

struct donner::svg::GifEncoder::Options

Encoder configuration.

Class Members
optional< Rgb > background If set, frames are composited over this color and the GIF is fully opaque.

If unset, the GIF keeps binary transparency: pixels with alpha below 128 become transparent and the rest keep their color with alpha discarded.

int height = 0 Image height in pixels, in [1, 65535].
uint16_t loopCount = 0 Number of times to repeat the animation after the first play; 0 loops forever.
size_t maximumOutputBytes = kMaximumOutputBytes Retained-output limit.

Callers may lower the hard limit for a smaller resource envelope; zero or a value above kMaximumOutputBytes is invalid.

size_t maximumWorkspaceBytes = kMaximumWorkspaceBytes Encoder-workspace limit.

Callers may lower the hard limit for a smaller resource envelope; zero or a value above kMaximumWorkspaceBytes is invalid.

int width = 0 Image width in pixels, in [1, 65535].

Member Enumeration Documentation

◆ Error

enum class donner::svg::GifEncoder::Error
strong

Reason the most recent operation failed.

Enumerator
None 

No error.

InvalidConfiguration 

Dimensions or configured limits are invalid.

InvalidFrame 

The input pixel layout is invalid.

ResourceLimit 

Output or workspace admission failed.

Finished 

A frame was added after finish().

Constructor & Destructor Documentation

◆ GifEncoder()

donner::svg::GifEncoder::GifEncoder ( const Options & options)
explicit

Create an encoder and write the GIF header, logical screen descriptor and NETSCAPE2.0 loop extension.

Parameters
optionsEncoder configuration. Invalid dimensions or limits, or a workspace or header that exceeds the configured limits, make every addFrame call fail; error reports the reason.

Member Function Documentation

◆ addFrame()

bool donner::svg::GifEncoder::addFrame ( std::span< const uint8_t > rgbaPixels,
size_t strideInPixels,
uint16_t delayCentiseconds )

Add one animation frame.

Parameters
rgbaPixelsStraight-alpha RGBA8 pixels, including every pixel of the final row.
strideInPixelsRow stride in pixels; 0 means the image width.
delayCentisecondsHow long the frame is shown, in hundredths of a second.
Returns
False if the encoder is finished, the dimensions or pixel layout are invalid, or a resource limit would be exceeded. The frame is not added, and a resource-limit failure makes the entire result unavailable rather than returning a truncated animation.

◆ finish()

std::vector< uint8_t > donner::svg::GifEncoder::finish ( )

Flush the last frame, write the trailer, and return the encoded GIF.

Further addFrame calls fail.

Returns
The complete GIF file, or an empty vector if no frame was added or any terminal error occurred.

◆ FrameDelaysCentiseconds()

std::vector< uint16_t > donner::svg::GifEncoder::FrameDelaysCentiseconds ( double fps,
int frameCount )
static

Split an animation into per-frame GIF delays.

GIF delays are whole centiseconds. Rounding each frame independently would drift (30 fps would play at 33.3 fps), so frame i lasts round((i + 1) * 100 / fps) - round(i * 100 / fps) centiseconds and the total stays within half a centisecond of the true duration. Above 100 fps some delays are 0. Frames longer than the largest GIF delay, 65535 centiseconds, are clamped to it.

Parameters
fpsFrames per second, positive.
frameCountNumber of frames.
Returns
One delay per frame.

◆ WorkspaceUpperBound()

std::optional< size_t > donner::svg::GifEncoder::WorkspaceUpperBound ( int width,
int height )
static

Conservative encoder-owned workspace needed for a steady-state frame of this size.

Includes resolved current and previous pixels, canonical histogram entries, palette indices, and pending and next encoded image blocks. Caller-owned input and renderer buffers are not included.

Parameters
widthCanvas width in pixels.
heightCanvas height in pixels.
Returns
The conservative byte bound, or std::nullopt for invalid dimensions or size overflow.

The documentation for this class was generated from the following file: