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. | |
Friends | |
| class | GifEncoderTestPeer |
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:
Usage:
| 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]. |
|
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(). |
|
explicit |
| bool donner::svg::GifEncoder::addFrame | ( | std::span< const uint8_t > | rgbaPixels, |
| size_t | strideInPixels, | ||
| uint16_t | delayCentiseconds ) |
Add one animation frame.
| rgbaPixels | Straight-alpha RGBA8 pixels, including every pixel of the final row. |
| strideInPixels | Row stride in pixels; 0 means the image width. |
| delayCentiseconds | How long the frame is shown, in hundredths of a second. |
| std::vector< uint8_t > donner::svg::GifEncoder::finish | ( | ) |
Flush the last frame, write the trailer, and return the encoded GIF.
Further addFrame calls fail.
|
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.
| fps | Frames per second, positive. |
| frameCount | Number of frames. |
|
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.
| width | Canvas width in pixels. |
| height | Canvas height in pixels. |