libspng
repository·master·Indexed 21 days ago
https://github.com/randy408/libspngA fast, secure, and easy-to-use C library for reading and writing PNG files, designed as a modern alternative to libpng with a simplified API. It supports decoding and encoding images, managing PNG chunks (such as text, EXIF, and ICC profiles), and provides flexible build options via CMake, Meson, or direct source embedding. The library can optionally use miniz as a zlib replacement for easier integration.
What's inside libspng
- libspng is a C library designed for reading and writing Portable Network Graphics (PNG) files. Its primary design goals are security and ease of use.
Understand chunk data semantics in libspng
masterChunk data is stored within the
spng_ctx. Understanding how data is retrieved and modified is critical for correct usage:Error Handling
All
spng_get_*()functions return0on success. If they return a non-zero error, specificallySPNG_ECHUNKAVAIL, it means the PNG does not contain that chunk or it was not previously set.Setting and Overwriting Data
- Replacement: A successful
spng_set_*()call replaces any previously set value or list. It does not combine data from the file with existing data or combine multiplespng_set_*()calls. - Persistence: Data set via
spng_set_*()is never replaced by input file chunk data. If you manually set a value, it remains that way regardless of what is in the source file.
Decoder Context Behavior
- Chunk Reading: When calling
spng_get_*()orspng_set_*(), the decoder reads and validates all chunks up to the firstIDATchunk (exceptspng_get_ihdr(), which only reads the header). - Post-Decode Reading: After the image has been decoded, calling
spng_get_*()will read all chunks up to theIENDmarker. - Recommendation: For certain chunks like
text,time,unknown_chunks, andexif, it is recommended to call the getter functions afterspng_decode_image()to ensure all chunks are retrieved.
- Replacement: A successful
Understand libspng Contexts
masterIn
libspng, thespng_ctxhandle is an opaque datatype that serves as the central container for all information. Unlikelibpng, there is no separate info struct.- Creation: Use
spng_ctx_new()orspng_ctx_new2()(for custom memory allocators) to create a new context. - Role: Contexts are decoders by default. To create an encoder, you must pass the
SPNG_CTX_ENCODERflag during creation. - Cleanup: Use
spng_ctx_free()to release all associated context data.
- Creation: Use
Understand libspng error return values
masterIn libspng, all functions follow a consistent error reporting pattern: they return
0on success and a non-zero integer on error.Non-recoverable states: Certain errors—such as integer overflows, Out of Memory (OOM) conditions, or specific decoding errors—may put the library into a non-recoverable state. If this occurs, all subsequent function calls will return the error code
SPNG_EBADSTATE.Understand libspng versioning and stability
masterlibspng follows semantic versioning.
Key stability guarantees:
- Releases from
0.4.0to0.8.xare considered stable. - If
1.0.0introduces breaking changes, the0.8.xseries will be maintained as a separate stable branch. - Note:
1.0.0is currently planned to be compatible with previous versions.
- Releases from
Retrieve image information and chunk data
masterBasic image properties (dimensions, bit depth, color type, etc.) are retrieved via
spng_get_ihdr().Data Handling Nuances:
- Copying: Most chunk data is copied by
libspng. - Arbitrary Length Chunks: Data for chunks like
eXIf,text,sPLT, and unknown chunks is not copied. - Chunk Lists: Lists are not copied; the reference must remain valid for the lifetime of the context.
- Buffer Allocation: Unlike
libpng, you cannot access internal list pointers fortext,sPLT, and unknown chunks. You must first query the list size and then allocate your own buffers to retrieve the data.
- Copying: Most chunk data is copied by
Handle decoding errors in libspng
masterErrors in libspng are categorized into two types:
- Critical Errors: These are non-recoverable. The decoder stops parsing, invalidates the context, and returns an error code. Any partial image output should be considered invalid. Subsequent calls to the context will return
SPNG_EBADSTATE. - Non-critical Errors: These are file corruption issues that can be handled deterministically (e.g., by ignoring checksums or discarding invalid chunks). The image is extracted consistently, but may suffer from lost color accuracy or transparency.
Note on Truncation: Truncated PNGs or truncated image data are always treated as critical errors.
- Critical Errors: These are non-recoverable. The decoder stops parsing, invalidates the context, and returns an error code. Any partial image output should be considered invalid. Subsequent calls to the context will return
Use miniz as a zlib replacement
masterBy setting theSPNG_USE_MINIZcompiler option, libspng will useminizinstead ofzlib. This allows you to embed libspng into a project using only four files:spng.c,miniz.c, and their respective headers. Performance is generally comparable to or slightly better than stock zlib.Understand image formats and endianness in libspng
masterlibspng uses explicit, host-endian
spng_formatvalues (except forSPNG_FMT_PNGandSPNG_FMT_RAW).- Alpha Channel: When the destination format has an alpha channel but the source does not, alpha samples are implicitly set to fully opaque (maximum value). The library uses straight alpha; premultiplied alpha is not supported.
- SPNG_FMT_PNG: Represents the PNG format specified in the IHDR chunk in host-endianness (e.g., little-endian on x86). When decoding, the output is always host-endian. When encoding, the source is assumed to be host-endian.
- SPNG_FMT_RAW: Represents the PNG format in big-endian. This is equivalent to performing no transformations when decoding or encoding with libpng. When decoding 16-bit images, the output will always be big-endian.
Note: Always check supported format and flag combinations for decoding and encoding, as some combinations are not supported.
Handle errors in libspng
masterAll
libspngfunctions follow a consistent error pattern:- Success: Returns
0. - Error: Returns a non-zero error code.
Critical Behavior: Decoding or encoding errors will invalidate the context. Once a context is invalidated, most subsequent function calls will return
SPNG_EBADSTATEto signal that the context is no longer in a valid state for operations.- Success: Returns
Perform progressive image decoding
masterTo decode images incrementally (useful for large files or streaming), initialize the decoder with the
SPNG_DECODE_PROGRESSIVEflag inspng_decode_image().For both interlaced and non-interlaced images, the recommended approach is to use
spng_decode_row()in a loop combined withspng_get_row_info()to handle the non-sequential access required by interlaced formats.Implementation Pattern:
int error; struct spng_row_info row_info; do { error = spng_get_row_info(ctx, &row_info); if(error) break; void *row = image_buffer + (image_width * row_info.row_num); error = spng_decode_row(ctx, row, row_len); } while(error != SPNG_EOI);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_decode_row(ctx, row, len); } while(!error) if(error == SPNG_EOI) /* success */Apply Profile-guided optimization (PGO)
masterPGO can improve performance by up to 10%. To use it with Meson, follow these steps to generate the profile and then use it for the final build:
- Generate the profile:
- Configure with
-Db_pgo=generate. - Build and run the examples with benchmark images.
- Configure with
- Use the profile:
- Configure with
-Db_pgo=use. - Build and install.
- Configure with
# Run in root directory git clone https://github.com/libspng/benchmark_images.git cd build meson configure -Dbuildtype=release --default-library both -Db_pgo=generate ninja ./example ../benchmark_images/medium_rgb8.png ./example ../benchmark_images/medium_rgba8.png ./example ../benchmark_images/large_palette.png meson configure -Db_pgo=use ninja ninja install- Generate the profile: