libfacade 1.1
A library for manipulating PNG images with payloads.
Loading...
Searching...
No Matches
Classes | Namespaces | Macros | Typedefs | Enumerations | Functions
png.hpp File Reference

Code functionality for dealing with PNG images. More...

#include <algorithm>
#include <cmath>
#include <cstddef>
#include <cstdint>
#include <cstring>
#include <fstream>
#include <limits>
#include <map>
#include <optional>
#include <set>
#include <string>
#include <type_traits>
#include <utility>
#include <variant>
#include <vector>
#include <facade/platform.hpp>
#include <facade/exception.hpp>
#include <facade/utility.hpp>

Go to the source code of this file.

Classes

class  facade::png::ChunkTag
 The string tag identifying a given facade::png::ChunkVec or facade::png::ChunkPtr. More...
 
class  facade::png::ChunkVec
 A vector-based version of a given PNG chunk. More...
 
class  facade::png::ChunkPtr
 The chunk class responsible for parsing the raw data of a PNG file. More...
 
class  facade::png::Sample< _Base, _Bits >
 A sample of data for a given pixel. More...
 
class  facade::png::GrayscalePixel< _Base, _Bits >
 A grayscale pixel object, based on the facade::png::Sample class. More...
 
class  facade::png::TrueColorPixel< _Sample >
 An RGB pixel object. More...
 
class  facade::png::PalettePixel< _Bits >
 A paletted pixel object. More...
 
class  facade::png::AlphaGrayscalePixel< _Base >
 A grayscale pixel with alpha channel. More...
 
class  facade::png::AlphaTrueColorPixel< _Sample >
 An RGB pixel with alpha channel. More...
 
class  facade::png::PixelSpan< PixelType >
 A span of data representing the underlying bits or bytes of a pixel. More...
 
class  facade::png::Header
 A PNG header object. More...
 
class  facade::png::Text
 A tEXt chunk object. More...
 
class  facade::png::ZText
 A compressed text chunk. More...
 
class  facade::png::End
 The end chunk for a given PNG file. More...
 
class  facade::png::ScanlineBase< PixelType >
 The base scanline class containing a row of facade::png::PixelSpan of the given pixel type. More...
 
class  facade::png::Scanline
 A wrapper object for ScanlineVariant. More...
 
class  facade::png::Image
 A class for loading and manipulating PNG images. More...
 

Namespaces

namespace  facade
 
namespace  facade::png
 

Macros

#define ASSERT_PIXEL(pixel)
 Macro that creates a static_assert that the given argument class is a known base pixel type.
 

Typedefs

using facade::png::Sample1Bit = Sample< std::uint8_t, 1 >
 
using facade::png::Sample2Bit = Sample< std::uint8_t, 2 >
 
using facade::png::Sample4Bit = Sample< std::uint8_t, 4 >
 
using facade::png::Sample8Bit = Sample< std::uint8_t >
 
using facade::png::Sample16Bit = Sample< std::uint16_t >
 
using facade::png::GrayscalePixel1Bit = GrayscalePixel< std::uint8_t, 1 >
 A facade::png::GrayscalePixel with a 1-bit facade::png::Sample value.
 
using facade::png::GrayscalePixel2Bit = GrayscalePixel< std::uint8_t, 2 >
 A facade::png::GrayscalePixel with a 2-bit facade::png::Sample value.
 
using facade::png::GrayscalePixel4Bit = GrayscalePixel< std::uint8_t, 4 >
 A facade::png::GrayscalePixel with a 4-bit facade::png::Sample value.
 
using facade::png::GrayscalePixel8Bit = GrayscalePixel< std::uint8_t >
 A facade::png::GrayscalePixel with an 8-bit facade::png::Sample value.
 
using facade::png::GrayscalePixel16Bit = GrayscalePixel< std::uint16_t >
 A facade::png::GrayscalePixel with a 16-bit facade::png::Sample value.
 
using facade::png::TrueColorPixel8Bit = TrueColorPixel< Sample8Bit >
 A facade::png::TrueColorPixel with an 8-bit facade::png::Sample value.
 
using facade::png::TrueColorPixel16Bit = TrueColorPixel< Sample16Bit >
 A facade::png::TrueColorPixel with a 16-bit facade::png::Sample value.
 
using facade::png::PalettePixel1Bit = PalettePixel< 1 >
 A facade::png::PalettePixel object with a 1-bit facade::png::Sample value.
 
using facade::png::PalettePixel2Bit = PalettePixel< 2 >
 A facade::png::PalettePixel object with a 2-bit facade::png::Sample value.
 
using facade::png::PalettePixel4Bit = PalettePixel< 4 >
 A facade::png::PalettePixel object with a 4-bit facade::png::Sample value.
 
using facade::png::PalettePixel8Bit = PalettePixel< 8 >
 A facade::png::PalettePixel object with an 8-bit facade::png::Sample value.
 
using facade::png::AlphaGrayscalePixel8Bit = AlphaGrayscalePixel< std::uint8_t >
 An facade::png::AlphaGrayscalePixel with an 8-bit facade::png::Sample size.
 
using facade::png::AlphaGrayscalePixel16Bit = AlphaGrayscalePixel< std::uint16_t >
 An facade::png::AlphaGrayscalePixel with a 16-bit facade::png::Sample size.
 
using facade::png::AlphaTrueColorPixel8Bit = AlphaTrueColorPixel< Sample8Bit >
 An facade::png::AlphaTrueColorPixel with an 8-bit facade::png::Sample size.
 
using facade::png::AlphaTrueColorPixel16Bit = AlphaTrueColorPixel< Sample16Bit >
 An facade::png::AlphaTrueColorPixel with a 16-bit facade::png::Sample size.
 
using facade::png::Pixel = std::variant< GrayscalePixel1Bit, GrayscalePixel2Bit, GrayscalePixel4Bit, GrayscalePixel8Bit, GrayscalePixel16Bit, TrueColorPixel8Bit, TrueColorPixel16Bit, PalettePixel1Bit, PalettePixel2Bit, PalettePixel4Bit, PalettePixel8Bit, AlphaGrayscalePixel8Bit, AlphaGrayscalePixel16Bit, AlphaTrueColorPixel8Bit, AlphaTrueColorPixel16Bit >
 The variant type corresponding to all known pixel types for PNG images.
 
template<typename PixelType >
using facade::png::PixelRow = std::vector< PixelSpan< PixelType > >
 A vector of a facade::png::PixelSpan of the given pixel type.
 
using facade::png::GrayscaleScanline1Bit = ScanlineBase< GrayscalePixel1Bit >
 A 1-bit grayscale scanline, using facade::png::GrayscalePixel1Bit as a pixel base.
 
using facade::png::GrayscaleScanline2Bit = ScanlineBase< GrayscalePixel2Bit >
 A 2-bit grayscale scanline, using facade::png::GrayscalePixel2Bit as a pixel base.
 
using facade::png::GrayscaleScanline4Bit = ScanlineBase< GrayscalePixel4Bit >
 A 4-bit grayscale scanline, using facade::png::GrayscalePixel4Bit as a pixel base.
 
using facade::png::GrayscaleScanline8Bit = ScanlineBase< GrayscalePixel8Bit >
 An 8-bit grayscale scanline, using facade::png::GrayscalePixel8Bit as a pixel base.
 
using facade::png::GrayscaleScanline16Bit = ScanlineBase< GrayscalePixel16Bit >
 A 16-bit grayscale scanline, using facade::png::GrayscalePixel16Bit as a pixel base.
 
using facade::png::TrueColorScanline8Bit = ScanlineBase< TrueColorPixel8Bit >
 An 8-bit RGB scanline, using facade::png::TrueColorPixel8Bit as a pixel base.
 
using facade::png::TrueColorScanline16Bit = ScanlineBase< TrueColorPixel16Bit >
 A 16-bit RGB scanline, using facade::png::TrueColorPixel16Bit as a pixel base.
 
using facade::png::PaletteScanline1Bit = ScanlineBase< PalettePixel1Bit >
 A 1-bit palette scanline, using facade::png::PalettePixel1Bit as a pixel base.
 
using facade::png::PaletteScanline2Bit = ScanlineBase< PalettePixel2Bit >
 A 2-bit palette scanline, using facade::png::PalettePixel2Bit as a pixel base.
 
using facade::png::PaletteScanline4Bit = ScanlineBase< PalettePixel4Bit >
 A 4-bit palette scanline, using facade::png::PalettePixel4Bit as a pixel base.
 
using facade::png::PaletteScanline8Bit = ScanlineBase< PalettePixel8Bit >
 An 8-bit palette scanline, using facade::png::PalettePixel8Bit as a pixel base.
 
using facade::png::AlphaGrayscaleScanline8Bit = ScanlineBase< AlphaGrayscalePixel8Bit >
 An 8-bit grayscale scanline with alpha channel, using facade::png::AlphaGrayscalePixel8Bit as a pixel base.
 
using facade::png::AlphaGrayscaleScanline16Bit = ScanlineBase< AlphaGrayscalePixel16Bit >
 A 16-bit grayscale scanline with alpha channel, using facade::png::AlphaGrayscalePixel16Bit as a pixel base.
 
using facade::png::AlphaTrueColorScanline8Bit = ScanlineBase< AlphaTrueColorPixel8Bit >
 An 8-bit RGB scanline with alpha channel, using facade::png::AlphaTrueColorPixel8Bit as a pixel base.
 
using facade::png::AlphaTrueColorScanline16Bit = ScanlineBase< AlphaTrueColorPixel16Bit >
 A 16-bit RGB scanline with alpha channel, using facade::png::AlphaTrueColorPixel16Bit a pixel base.
 
using facade::png::ScanlineVariant = std::variant< GrayscaleScanline1Bit, GrayscaleScanline2Bit, GrayscaleScanline4Bit, GrayscaleScanline8Bit, GrayscaleScanline16Bit, TrueColorScanline8Bit, TrueColorScanline16Bit, PaletteScanline1Bit, PaletteScanline2Bit, PaletteScanline4Bit, PaletteScanline8Bit, AlphaGrayscaleScanline8Bit, AlphaGrayscaleScanline16Bit, AlphaTrueColorScanline8Bit, AlphaTrueColorScanline16Bit >
 A variant type containing all accepted scanline types.
 

Enumerations

enum  facade::png::ColorType {
  facade::png::GRAYSCALE = 0 , facade::png::TRUE_COLOR = 2 , facade::png::PALETTE = 3 , facade::png::ALPHA_GRAYSCALE = 4 ,
  facade::png::ALPHA_TRUE_COLOR = 6
}
 The color type represented in the PNG file. More...
 
enum  facade::png::PixelEnum {
  facade::png::GRAYSCALE_PIXEL_1BIT = 0 , facade::png::GRAYSCALE_PIXEL_2BIT , facade::png::GRAYSCALE_PIXEL_4BIT , facade::png::GRAYSCALE_PIXEL_8BIT ,
  facade::png::GRAYSCALE_PIXEL_16BIT , facade::png::TRUE_COLOR_PIXEL_8BIT , facade::png::TRUE_COLOR_PIXEL_16BIT , facade::png::PALETTE_PIXEL_1BIT ,
  facade::png::PALETTE_PIXEL_2BIT , facade::png::PALETTE_PIXEL_4BIT , facade::png::PALETTE_PIXEL_8BIT , facade::png::ALPHA_GRAYSCALE_PIXEL_8BIT ,
  facade::png::ALPHA_GRAYSCALE_PIXEL_16BIT , facade::png::ALPHA_TRUE_COLOR_PIXEL_8BIT , facade::png::ALPHA_TRUE_COLOR_PIXEL_16BIT
}
 An enum representing all available pixel types. More...
 
enum  facade::png::FilterType {
  facade::png::NONE = 0 , facade::png::SUB , facade::png::UP , facade::png::AVERAGE ,
  facade::png::PAETH
}
 The filter type to use for a given scanline. More...
 

Functions

template<typename PixelType >
EXPORT std::vector< std::uint8_t > facade::png::pixels_to_raw (const PixelRow< PixelType > &pixels)
 Convert a row of facade::png::PixelSpan of the given pixel type into a vector of bytes.
 

Detailed Description

Code functionality for dealing with PNG images.

This file contains everything you should need for interacting with a PNG file where it relates to arbitrary payloads.

Design Explanation

The library is specifically designed in mind to make things as easy as possible without drowning the user in repetitive typing of objects. There are many design challenges when attempting to create a library for PNG images.

It starts with five pixels types:

Already, we have five types to consider. Individual pixel values are composed of what are called samples. For example, a sample of a grayscale pixel value can be the following sizes:

This already provides one problem in particular with C++: we can't have references to pixels because their sample size could go under the byte-boundary threshhold. That means we can't directly bind an object to a location in memory because we would need access to bit boundaries, which is only really exposed through a byte interface of interacting with bits via masking and assignment. In other words, the present of sub 8-bit samples means we need to create an interface to accessing and assigning pixels.

In addition to creating this bit-access problem, the bit depth of provided pixels means we now have many, many more types to deal with:

In total, there are then 15 pixel types to deal with. This cascades down to what are called scanlines, which in turn, there are 15 types of scanlines as well (e.g., an AlphaTrueColor 8-bit scanline).

On top of the typing issue, there is the fact that we don't know what pixel type we're dealing with until we read the file. This means we can't just declare our image data as a certain type before the image is parsed. We can, however, set the type of pixel for our image data through the use of C++ variants. In short, a variant is a C++ version of a union in C. It intelligently keeps track of which type is active within the variant.

So to solve our problems from the pixel side of things, we have one variant type for pixels: facade::png::Pixel. This is a variant of all pixel types within a PNG image. To store our pixel data into scanlines, we also have a scanline variant, facade::png::Scanline. This way, a PNG image can be instantiated and loaded without the user needing to clarify ahead of time– and possibly incorrectly– what type of pixel the PNG contains.

To solve the problem of pixels with less than 8-bit samples, within a scanline, pixels are reduced to an object that is called a facade::png::PixelSpan. This is the raw interface to accessing pixels in memory. It is capable of both accessing pixel values at the bit level as well as pixel values that go well beyond a byte in size.

Usage

For the sake of saving memory when it isn't needed, only the PNG chunks are loaded in the image at first, not the image data. Not every operation on a given PNG image needs the image data, after all. This means a given PNG image can be in various states.

There are basically three steps to getting PNG image data:

You can opt to do this manually by calling facade::png::Image::decompress followed by facade::png::Image::reconstruct, or you could simply call facade::png::Image::load, which does those functions for you. The same process is important to do backwards when saving a file: before saving the file, you should call facade::png::Image::filter, followed by facade::png::Image::compress, followed by facade::png::Image::save.

This example demonstrates how to load an image, access its pixels, modify its pixels, and save the pixels to a new image.

#include <facade.hpp>
using namespace facade;
int main(int argc, char *argv[])
{
png::Image image;
// first, parse the image.
image.parse("../test/art.png");
// we could also just call image.load(), which does the same steps.
image.decompress();
image.reconstruct();
// get the header of the image.
png::Header &header = image.header();
// let's black out all the pixels in the image.
for (std::uint32_t y=0; y<header.height(); ++y)
{
for (std::uint32_t x=0; x<header.width(); ++x)
{
// get the pixel variant that holds our pixel type.
png::Pixel pixel_var = image[y][x];
// we already know the image we're dealing with is an AlphaTrueColor image,
// so get that pixel type.
png::AlphaTrueColorPixel8Bit &pixel = std::get<png::AlphaTrueColorPixel8Bit>(pixel_var);
// invert the pixels
pixel.red().set_value(0xFF - *pixel.red());
pixel.green().set_value(0xFF - *pixel.green());
pixel.blue().set_value(0xFF - *pixel.blue());
// reassign the pixel
image[y].set_pixel(pixel, x);
}
}
// filter the new image
image.filter();
// compress the new image
image.compress();
// save the new image
image.save("art.inverted.png");
return 0;
}
An RGB pixel with alpha channel.
Definition: png.hpp:607
A PNG header object.
Definition: png.hpp:816
std::uint32_t width() const
Get the width value of this header.
Definition: png.cpp:189
std::uint32_t height() const
Get the height value of this header.
Definition: png.cpp:199
A class for loading and manipulating PNG images.
Definition: png.hpp:1305
void filter()
Filter the image data to prepare it for compression.
Definition: png.cpp:1305
void compress(std::optional< std::size_t > chunk_size=8192, int level=-1)
Compress the image data into IDAT chunks.
Definition: png.cpp:1143
void save(const std::string &filename) const
Call facade::png::Image::to_file and save that file to disk.
Definition: png.cpp:1488
Header & header()
Get the header present in the PNG image.
Definition: png.cpp:999
void decompress()
Decompress the IDAT chunks in the image.
Definition: png.cpp:1038
void parse(const void *ptr, std::size_t size, bool validate=true)
Parse a given data buffer into its individual chunks for further processing.
Definition: png.cpp:935
void reconstruct()
Reconstruct the filtered image data into their raw, unfiltered form.
Definition: png.cpp:1172
Sample & blue()
Retrieve a reference to the blue channel.
Definition: png.hpp:511
Sample & red()
Retrieve a reference to the red channel.
Definition: png.hpp:497
Sample & green()
Retrieve a reference to the green channel.
Definition: png.hpp:504
std::variant< GrayscalePixel1Bit, GrayscalePixel2Bit, GrayscalePixel4Bit, GrayscalePixel8Bit, GrayscalePixel16Bit, TrueColorPixel8Bit, TrueColorPixel16Bit, PalettePixel1Bit, PalettePixel2Bit, PalettePixel4Bit, PalettePixel8Bit, AlphaGrayscalePixel8Bit, AlphaGrayscalePixel16Bit, AlphaTrueColorPixel8Bit, AlphaTrueColorPixel16Bit > Pixel
The variant type corresponding to all known pixel types for PNG images.
Definition: png.hpp:674
Definition: exception.hpp:14

Macro Definition Documentation

◆ ASSERT_PIXEL

#define ASSERT_PIXEL (   pixel)
Value:
static_assert(std::is_same<pixel, GrayscalePixel1Bit>::value || \
std::is_same<pixel, GrayscalePixel2Bit>::value || \
std::is_same<pixel, GrayscalePixel4Bit>::value || \
std::is_same<pixel, GrayscalePixel8Bit>::value || \
std::is_same<pixel, GrayscalePixel16Bit>::value || \
std::is_same<pixel, TrueColorPixel8Bit>::value || \
std::is_same<pixel, TrueColorPixel16Bit>::value || \
std::is_same<pixel, PalettePixel1Bit>::value || \
std::is_same<pixel, PalettePixel2Bit>::value || \
std::is_same<pixel, PalettePixel4Bit>::value || \
std::is_same<pixel, PalettePixel8Bit>::value || \
std::is_same<pixel, AlphaGrayscalePixel8Bit>::value || \
std::is_same<pixel, AlphaGrayscalePixel16Bit>::value || \
std::is_same<pixel, AlphaTrueColorPixel8Bit>::value || \
std::is_same<pixel, AlphaTrueColorPixel16Bit>::value, \
#pixel " is not a base pixel-type.")

Macro that creates a static_assert that the given argument class is a known base pixel type.