Awesome
libspng
libspng (simple png) is a C library for reading and writing Portable Network Graphics (PNG) format files with a focus on security and ease of use.
libspng is an alternative to libpng, the projects are separate and the APIs are not compatible.
Motivation
The goal is to provide a fast PNG library with a simpler API than libpng, it outperforms the reference implementation in common use cases.
Performance
Features
Feature | spng | libpng | stb_image | lodepng |
---|---|---|---|---|
Decode from stream | ✅ | ✅ | ✅ | ❌ |
Gamma correction | ✅ | ✅ | ❌ | ❌ |
No known security bugs<sup>[1]</sup> | ✅ | ✅ | ❌ | ✅ |
Progressive image read | ✅ | ✅ | ❌ | ❌ |
Parses all standard chunks | ✅ | ✅ | ❌ | ❌ |
Doesn't require zlib<sup>[2]</sup> | ✅ | ❌ | ✅ | ✅ |
Encoding | ✅ | ✅ | ✅ | ✅ |
Animated PNG | Planned | ✅<sup>[3]</sup> | ❌ | ❌ |
<sup>[1]</sup> The project is fuzz tested on OSS-Fuzz and vulnerabilities are fixed before they become public.
<sup>[2]</sup> Building with miniz is supported.
<sup>[3]</sup> With a 3rd party patch
Getting spng
Download the latest release and include spng.c/spng.h
in your project,
you can also build with CMake or Meson, refer to the documentation for details.
Usage
#include <spng.h>
/* Create a decoder context */
spng_ctx *ctx = spng_ctx_new(0);
/* Set an input buffer */
spng_set_png_buffer(ctx, buf, buf_size);
/* Determine output image size */
spng_decoded_image_size(ctx, SPNG_FMT_RGBA8, &out_size);
/* Decode to 8-bit RGBA */
spng_decode_image(ctx, out, out_size, SPNG_FMT_RGBA8, 0);
/* Free context memory */
spng_ctx_free(ctx);
/* Creating an encoder context requires a flag */
spng_ctx *enc = spng_ctx_new(SPNG_CTX_ENCODER);
/* Encode to internal buffer managed by the library */
spng_set_option(enc, SPNG_ENCODE_TO_BUFFER, 1);
/* Specify image dimensions, PNG format */
struct spng_ihdr ihdr =
{
.width = width,
.height = height,
.bit_depth = 8,
.color_type = SPNG_COLOR_TYPE_TRUECOLOR_ALPHA
};
/* Image will be encoded according to ihdr.color_type, .bit_depth */
spng_set_ihdr(enc, &ihdr);
/* SPNG_FMT_PNG is a special value that matches the format in ihdr,
SPNG_ENCODE_FINALIZE will finalize the PNG with the end-of-file marker */
spng_encode_image(enc, image, image_size, SPNG_FMT_PNG, SPNG_ENCODE_FINALIZE);
/* PNG is written to an internal buffer by default */
void *png = spng_get_png_buffer(enc, &png_size, &error);
/* User owns the buffer after a successful call */
free(png);
/* Free context memory */
spng_ctx_free(enc);
See example.c.
License
Code is licensed under the BSD 2-clause "Simplified" License.
The project contains optimizations and test images from libpng, these are licensed under the PNG Reference Library License version 2.
Security & Testing
Code is written according to the rules of the CERT C Coding Standard. All integer arithmetic is checked for overflow and all error conditions are handled gracefully.
The library is continuously fuzzed by OSS-Fuzz, code is also scanned with Clang Static Analyzer, Coverity Scan and PVS-Studio.
The test suite consists of over 1000 test cases, 175 test images are decoded with all possible output format and flag combinations and compared against libpng for correctness.
Versioning
Releases follow the semantic versioning scheme with additional guarantees:
- Releases from 0.4.0 to 0.8.x are stable
- If 1.0.0 will introduce breaking changes then 0.8.x will be maintained as a separate stable branch
Currently 1.0.0 is planned to be compatible.
Documentation
Online documentation is available at libspng.org/docs.
Known Issues
- Decoding to
SPNG_FMT_G8
,SPNG_FMT_GA8
andSPNG_FMT_GA16
output formats is not supported for all PNG color type and bit depth combinations, see documentation for details. - Gamma correction is not implemented for
SPNG_FMT_PNG
,SPNG_FMT_G8
,SPNG_FMT_GA8
andSPNG_FMT_GA16
output formats.
Supporting spng
You can sponsor development through OpenCollective, funds will be used for maintenance and further development according to the roadmap.
OpenCollective backers
Individuals
<a href="https://opencollective.com/libspng"><img src="https://opencollective.com/libspng/backers.svg?width=890"></a>
Organizations
Support this project with your organization. Your logo will show up here with a link to your website. [Contribute]
<a href="https://opencollective.com/libspng/sponsor/0/website"><img src="https://opencollective.com/libspng/sponsor/0/avatar.svg"></a> <a href="https://opencollective.com/libspng/sponsor/1/website"><img src="https://opencollective.com/libspng/sponsor/1/avatar.svg"></a> <a href="https://opencollective.com/libspng/sponsor/2/website"><img src="https://opencollective.com/libspng/sponsor/2/avatar.svg"></a> <a href="https://opencollective.com/libspng/sponsor/3/website"><img src="https://opencollective.com/libspng/sponsor/3/avatar.svg"></a> <a href="https://opencollective.com/libspng/sponsor/4/website"><img src="https://opencollective.com/libspng/sponsor/4/avatar.svg"></a> <a href="https://opencollective.com/libspng/sponsor/5/website"><img src="https://opencollective.com/libspng/sponsor/5/avatar.svg"></a> <a href="https://opencollective.com/libspng/sponsor/6/website"><img src="https://opencollective.com/libspng/sponsor/6/avatar.svg"></a> <a href="https://opencollective.com/libspng/sponsor/7/website"><img src="https://opencollective.com/libspng/sponsor/7/avatar.svg"></a> <a href="https://opencollective.com/libspng/sponsor/8/website"><img src="https://opencollective.com/libspng/sponsor/8/avatar.svg"></a> <a href="https://opencollective.com/libspng/sponsor/9/website"><img src="https://opencollective.com/libspng/sponsor/9/avatar.svg"></a>