LodePNG
| Language | C and C++ |
|---|---|
| License | zlib license |
| Repository | github.com/lvandeve/lodepng |
| Documentation | comments in lodepng.h |
| Depends on | nothing (contains its own zlib / DEFLATE) |
| Read / write | yes / yes |
LodePNG is 2 files, lodepng.cpp and lodepng.h, that decode and encode PNG with no external dependencies. It’s the easiest way to add PNG support to a C or C++ program. Compile the .cpp file as C to use it from C (rename it to lodepng.c).
It decodes all PNG color types, converts them to the format you ask for (8-bit RGBA by default), reads text chunks, and encodes with an automatic choice of color type. Decoding is slower than libpng or libspng.
Installation#
Copy lodepng.cpp and lodepng.h from the repository into your project and compile lodepng.cpp with the rest of your code. It’s also in vcpkg (vcpkg install lodepng) and Conan.
Basic usage: decode and encode#
C++
#include "lodepng.h"
#include <iostream>
#include <vector>
int main() {
std::vector<unsigned char> image; // RGBA, 4 bytes per pixel
unsigned width, height;
unsigned error = lodepng::decode(image, width, height, "in.png");
if (error) {
std::cerr << "decode error " << error << ": " << lodepng_error_text(error) << "\n";
return 1;
}
std::cout << width << " x " << height << "\n";
// invert colors, keep alpha
for (size_t i = 0; i < image.size(); i += 4) {
image[i] = 255 - image[i];
image[i + 1] = 255 - image[i + 1];
image[i + 2] = 255 - image[i + 2];
}
error = lodepng::encode("out.png", image, width, height);
if (error) {
std::cerr << "encode error " << error << ": " << lodepng_error_text(error) << "\n";
return 1;
}
return 0;
}
Using LodePNG from C#
C
#include "lodepng.h"
#include <stdio.h>
#include <stdlib.h>
int main(void) {
unsigned char *image = NULL;
unsigned width, height;
unsigned error = lodepng_decode32_file(&image, &width, &height, "in.png");
if (error) {
printf("error %u: %s\n", error, lodepng_error_text(error));
return 1;
}
error = lodepng_encode32_file("out.png", image, width, height);
free(image);
return error ? 1 : 0;
}
How to get the size and color type without decoding#
C++
std::vector<unsigned char> png;
lodepng::load_file(png, "in.png");
unsigned w, h;
lodepng::State state;
unsigned error = lodepng_inspect(&w, &h, &state, png.data(), png.size());
if (!error) {
const LodePNGColorMode &color = state.info_png.color;
std::cout << w << " x " << h << ", color type " << color.colortype
<< ", bit depth " << color.bitdepth << "\n";
}
How to read text chunks#
C++
std::vector<unsigned char> png, image;
lodepng::load_file(png, "in.png");
lodepng::State state; // text chunks are read by default (state.decoder.read_text_chunks)
unsigned w, h;
unsigned error = lodepng::decode(image, w, h, state, png);
if (!error) {
const LodePNGInfo &info = state.info_png;
for (size_t i = 0; i < info.text_num; i++)
std::cout << info.text_keys[i] << ": " << info.text_strings[i] << "\n";
for (size_t i = 0; i < info.itext_num; i++) // UTF-8 iTXt chunks
std::cout << info.itext_keys[i] << ": " << info.itext_strings[i] << "\n";
}
How to save a grayscale PNG#
Pass the color type and bit depth of your buffer:
C++
std::vector<unsigned char> gray(width * height); // 1 byte per pixel
// ... fill gray ...
unsigned error = lodepng::encode("gray.png", gray, width, height, LCT_GREY, 8);
Other color types: LCT_RGB, LCT_RGBA, LCT_GREY_ALPHA, LCT_PALETTE.
Tips#
- By default the encoder picks the smallest color type that keeps all pixels (e.g. palette for few colors). Set
state.encoder.auto_convert = 0to keep the type you pass. - Define
LODEPNG_NO_COMPILE_ENCODERorLODEPNG_NO_COMPILE_DECODERto compile only the half you need. - For smaller files run the output through oxipng or LodePNG’s own
pngdetail/zopflipngtools.