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().

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.

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.