libfacade 1.1
A library for manipulating PNG images with payloads.
|
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. | |
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. | |
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.
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.
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:
IDAT
chunk which contains image data and the IHDR
chunk, which contains PNG header information for this image.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.
#define ASSERT_PIXEL | ( | pixel | ) |
Macro that creates a static_assert that the given argument class is a known base pixel type.