Skip to content

Usage

The context must be created with the SPNG_CTX_ENCODER flag set.

Before any (implicit) write operation an output must be set with spng_set_png_stream() or spng_set_png_file().

Alternatively the SPNG_ENCODE_TO_BUFFER option can be enabled with spng_set_option(), in this case the encoder will create and manage an internal output buffer, it is freed by spng_ctx_free() unless it’s retrieved with spng_get_png_buffer().

In all cases the PNG must be explicitly finalized, this can be done with the SPNG_ENCODE_FINALIZE flag or with a call to spng_encode_chunks() after the image has been encoded.

Memory usage

On top of the overhead of the the context buffer the internal write buffer may grow to the length of entire chunks or more than the length of the PNG file when encoding to the internal buffer.

Encoding an image requires at least 2 rows to be kept in memory, this may increase to 3 rows for future versions.

Data types

spng_encode_flags

enum spng_encode_flags
{
    SPNG_ENCODE_PROGRESSIVE = 1, /* Initialize for progressive writes */
    SPNG_ENCODE_FINALIZE = 2, /* Finalize PNG after encoding image */
};

API

spng_encode_chunks()

int spng_encode_chunks(spng_ctx *ctx)

Encode all stored chunks before or after the image data (IDAT) stream, depending on the state of the encoder.

If the image is encoded this function will also finalize the PNG with the end-of-file (IEND) marker.

Calling this function before spng_encode_image() is optional.

spng_encode_image()

int spng_encode_image(spng_ctx *ctx, const void *img, size_t len, int fmt, int flags)

Encodes the image from img in the source format fmt to the specified PNG format set with spng_set_ihdr().

The width, height, color type, bit depth and interlace method must be set with spng_set_ihdr().

If the color type is set to SPNG_COLOR_TYPE_INDEXED a palette must be set with spng_set_plte().

img must point to a buffer of length len, len must be equal to the expected image size for the given format fmt.

This function may call spng_encode_chunks(), writing any pending chunks before the image data.

If the SPNG_ENCODE_FINALIZE flag is set this function will call spng_encode_chunks() on the last scanline/row, writing any pending chunks after the image data and finalize the PNG with the end-of-file (IEND) marker before returning. In most cases the only data after the image is the 12-byte IEND marker.

When the image is encoded to an internal buffer and the PNG is finalized spng_get_png_buffer() will return the encoded buffer, this must be freed by the user. If this function isn’t called or an error is encountered the internal buffer is freed by spng_ctx_free().

Supported format, flag combinations

Input format PNG Format Flags Notes
SPNG_FMT_PNG Any format* All Converted from host-endian if required
SPNG_FMT_RAW Any format* All No conversion (assumes big-endian)

* Any combination of color type and bit depth defined in the standard.

16-bit images are assumed to be host-endian except for SPNG_FMT_RAW.

The alpha channel is always straight alpha, premultiplied alpha is not supported.

Compression level and other options can be customized with spng_set_option(), see Encode options for all options. Note that encoder options are optimized based on PNG format and compression level, overriding other options such as filtering may disable some of these optimizations.

Progressive image encoding

If the SPNG_ENCODE_PROGRESSIVE flag is set the encoder will be initialized with fmt and flags for progressive encoding, the values of img, len are ignored.

With the SPNG_ENCODE_FINALIZE flag set the PNG is finalized on the last scanline or row.

Progressive encoding is straightforward when the image is not interlaced, calling spng_encode_row() for each row of the image will yield the return value SPNG_EOI for the final row:

int error;
size_t image_width = image_size / ihdr.height;

for(i = 0; i < ihdr.height; i++)
{
    void *row = image + image_width * i;

    error = spng_encode_row(ctx, row, image_width);

    if(error) break;
}

if(error == SPNG_EOI) /* success */

But for interlaced images (spng_ihdr.interlaced_method set to 1) rows are accessed multiple times and non-sequentially, use spng_get_row_info() to get the current row number:

int error;
struct spng_row_info row_info;

do
{
    error = spng_get_row_info(ctx, &row_info);
    if(error) break;

    void *row = image + image_width * row_info.row_num;

    error = spng_encode_row(ctx, row, len);
}
while(!error)

if(error == SPNG_EOI) /* success */

spng_encode_scanline()

int spng_encode_scanline(spng_ctx *ctx, const void *scanline, size_t len)

Encodes scanline, this function is meant to be used for interlaced PNG’s with image data that is already split into multiple passes.

This function requires the encoder to be initialized by calling spng_encode_image() with the SPNG_ENCODE_PROGRESSIVE flag set.

For the last scanline and subsequent calls the return value is SPNG_EOI.

spng_encode_row()

int spng_encode_row(spng_ctx *ctx, const void *row, size_t len)

Encodes row, interlacing it if necessary.

This function requires the encoder to be initialized by calling spng_encode_image() with the SPNG_ENCODE_PROGRESSIVE flag set.

See also: Progressive-image-encoding

For the last row and subsequent calls the return value is SPNG_EOI.

If the image is not interlaced this function’s behavior is identical to spng_encode_scanline().

spng_get_png_buffer()

void *spng_get_png_buffer(spng_ctx *ctx, size_t *len, int *error)

If SPNG_ENCODE_TO_BUFFER is enabled via spng_set_option() the encoded buffer is returned, it must be called after spng_encode_image() and the PNG must be finalized.

On success the buffer must be freed by the user.

Encode options

Option Default value Description
SPNG_IMG_COMPRESSION_LEVEL Z_DEFAULT_COMPRESSION Set image compression level (0-9)
SPNG_IMG_WINDOW_BITS 15* Set image zlib window bits (9-15)
SPNG_IMG_MEM_LEVEL 8 Set zlib memLevel for images
SPNG_IMG_COMPRESSION_STRATEGY Z_FILTERED* Set image compression strategy
SPNG_TEXT_COMPRESSION_LEVEL Z_DEFAULT_COMPRESSION Set text compression level (0-9)
SPNG_TEXT_WINDOW_BITS 15 Set text zlib window bits (9-15)
SPNG_TEXT_MEM_LEVEL 8 Set zlib memLevel for text
SPNG_TEXT_COMPRESSION_STRATEGY Z_DEFAULT_STRATEGY Set text compression strategy
SPNG_FILTER_CHOICE SPNG_FILTER_CHOICE_ALL* Configure or disable filtering
SPNG_ENCODE_TO_BUFFER 0 Encode to internal buffer

* Option may be optimized if not set explicitly.

Options not listed here have no effect on encoders.

Performance

The default encoder settings match the reference implementation and will produce files of the exact same size, but there are settings that offer better performance for a small increase in file size. Reducing compression level (set SPNG_IMG_COMPRESSION_LEVEL to a value lower than 6) will reduce encoding time for all image types.

  • Truecolor images - Reduce compression level (between 1 and 5) and leave everything else on defaults, file size should not increase by more than 10% but encode up to three times faster.

  • Indexed-color - Choose a reduced compression level (1-5), file size should stay within 5% but encode up to two times faster.

  • Grayscale - Choose a reduced compression level (1-5), file size should stay within 5% but encode up to two times faster.

  • Grayscale-alpha images - Choose a reduced compression level (1-5), file size should stay within 5% but encode up to four times faster.

  • Disabling filtering may further improve performance but will significantly increase file size.

Note

See encode experiments for more details.

Recommendations are based on benchmarks with zlib, performance with other implementations (miniz, zlib-ng) was not measured.