Test files for APNG can be found at the following locations:
This page hosts a formal specification of PNG (Portable Network Graphics) file using Kaitai Struct. This specification can be automatically translated into a variety of programming languages to get a parsing library.
All parsing code for C++98/STL generated by Kaitai Struct depends on the C++/STL runtime library. You have to install it before you can parse data.
For C++, the easiest way is to clone the runtime library sources and build them along with your project.
Using Kaitai Struct in C++/STL usually consists of 3 steps.
std::istream
). One can open local file for that, or use existing std::string
or char*
buffer.
#include <fstream>
std::ifstream is("path/to/local/file.png", std::ifstream::binary);
#include <sstream>
std::istringstream is(str);
#include <sstream>
const char buf[] = { ... };
std::string str(buf, sizeof buf);
std::istringstream is(str);
#include "kaitai/kaitaistream.h"
kaitai::kstream ks(&is);
png_t data(&ks);
After that, one can get various attributes from the structure by invoking getter methods like:
data.magic() // => get magic
#ifndef PNG_H_
#define PNG_H_
// This is a generated file! Please edit source .ksy file and use kaitai-struct-compiler to rebuild
#include "kaitai/kaitaistruct.h"
#include <stdint.h>
#include <vector>
#if KAITAI_STRUCT_VERSION < 9000L
#error "Incompatible Kaitai Struct C++/STL API: version 0.9 or later is required"
#endif
/**
* Test files for APNG can be found at the following locations:
*
* * <https://philip.html5.org/tests/apng/tests.html>
* * <http://littlesvr.ca/apng/>
*/
class png_t : public kaitai::kstruct {
public:
class rgb_t;
class chunk_t;
class bkgd_indexed_t;
class point_t;
class bkgd_greyscale_t;
class chrm_chunk_t;
class ihdr_chunk_t;
class plte_chunk_t;
class srgb_chunk_t;
class compressed_text_chunk_t;
class frame_data_chunk_t;
class bkgd_truecolor_t;
class gama_chunk_t;
class bkgd_chunk_t;
class phys_chunk_t;
class frame_control_chunk_t;
class international_text_chunk_t;
class text_chunk_t;
class animation_control_chunk_t;
class time_chunk_t;
enum phys_unit_t {
PHYS_UNIT_UNKNOWN = 0,
PHYS_UNIT_METER = 1
};
enum blend_op_values_t {
BLEND_OP_VALUES_SOURCE = 0,
BLEND_OP_VALUES_OVER = 1
};
enum compression_methods_t {
COMPRESSION_METHODS_ZLIB = 0
};
enum dispose_op_values_t {
DISPOSE_OP_VALUES_NONE = 0,
DISPOSE_OP_VALUES_BACKGROUND = 1,
DISPOSE_OP_VALUES_PREVIOUS = 2
};
enum color_type_t {
COLOR_TYPE_GREYSCALE = 0,
COLOR_TYPE_TRUECOLOR = 2,
COLOR_TYPE_INDEXED = 3,
COLOR_TYPE_GREYSCALE_ALPHA = 4,
COLOR_TYPE_TRUECOLOR_ALPHA = 6
};
png_t(kaitai::kstream* p__io, kaitai::kstruct* p__parent = 0, png_t* p__root = 0);
private:
void _read();
void _clean_up();
public:
~png_t();
class rgb_t : public kaitai::kstruct {
public:
rgb_t(kaitai::kstream* p__io, png_t::plte_chunk_t* p__parent = 0, png_t* p__root = 0);
private:
void _read();
void _clean_up();
public:
~rgb_t();
private:
uint8_t m_r;
uint8_t m_g;
uint8_t m_b;
png_t* m__root;
png_t::plte_chunk_t* m__parent;
public:
uint8_t r() const { return m_r; }
uint8_t g() const { return m_g; }
uint8_t b() const { return m_b; }
png_t* _root() const { return m__root; }
png_t::plte_chunk_t* _parent() const { return m__parent; }
};
class chunk_t : public kaitai::kstruct {
public:
chunk_t(kaitai::kstream* p__io, png_t* p__parent = 0, png_t* p__root = 0);
private:
void _read();
void _clean_up();
public:
~chunk_t();
private:
uint32_t m_len;
std::string m_type;
kaitai::kstruct* m_body;
bool n_body;
public:
bool _is_null_body() { body(); return n_body; };
private:
std::string m_crc;
png_t* m__root;
png_t* m__parent;
std::string m__raw_body;
kaitai::kstream* m__io__raw_body;
public:
uint32_t len() const { return m_len; }
std::string type() const { return m_type; }
kaitai::kstruct* body() const { return m_body; }
std::string crc() const { return m_crc; }
png_t* _root() const { return m__root; }
png_t* _parent() const { return m__parent; }
std::string _raw_body() const { return m__raw_body; }
kaitai::kstream* _io__raw_body() const { return m__io__raw_body; }
};
/**
* Background chunk for images with indexed palette.
*/
class bkgd_indexed_t : public kaitai::kstruct {
public:
bkgd_indexed_t(kaitai::kstream* p__io, png_t::bkgd_chunk_t* p__parent = 0, png_t* p__root = 0);
private:
void _read();
void _clean_up();
public:
~bkgd_indexed_t();
private:
uint8_t m_palette_index;
png_t* m__root;
png_t::bkgd_chunk_t* m__parent;
public:
uint8_t palette_index() const { return m_palette_index; }
png_t* _root() const { return m__root; }
png_t::bkgd_chunk_t* _parent() const { return m__parent; }
};
class point_t : public kaitai::kstruct {
public:
point_t(kaitai::kstream* p__io, png_t::chrm_chunk_t* p__parent = 0, png_t* p__root = 0);
private:
void _read();
void _clean_up();
public:
~point_t();
private:
bool f_x;
double m_x;
public:
double x();
private:
bool f_y;
double m_y;
public:
double y();
private:
uint32_t m_x_int;
uint32_t m_y_int;
png_t* m__root;
png_t::chrm_chunk_t* m__parent;
public:
uint32_t x_int() const { return m_x_int; }
uint32_t y_int() const { return m_y_int; }
png_t* _root() const { return m__root; }
png_t::chrm_chunk_t* _parent() const { return m__parent; }
};
/**
* Background chunk for greyscale images.
*/
class bkgd_greyscale_t : public kaitai::kstruct {
public:
bkgd_greyscale_t(kaitai::kstream* p__io, png_t::bkgd_chunk_t* p__parent = 0, png_t* p__root = 0);
private:
void _read();
void _clean_up();
public:
~bkgd_greyscale_t();
private:
uint16_t m_value;
png_t* m__root;
png_t::bkgd_chunk_t* m__parent;
public:
uint16_t value() const { return m_value; }
png_t* _root() const { return m__root; }
png_t::bkgd_chunk_t* _parent() const { return m__parent; }
};
/**
* \sa https://www.w3.org/TR/png/#11cHRM Source
*/
class chrm_chunk_t : public kaitai::kstruct {
public:
chrm_chunk_t(kaitai::kstream* p__io, png_t::chunk_t* p__parent = 0, png_t* p__root = 0);
private:
void _read();
void _clean_up();
public:
~chrm_chunk_t();
private:
point_t* m_white_point;
point_t* m_red;
point_t* m_green;
point_t* m_blue;
png_t* m__root;
png_t::chunk_t* m__parent;
public:
point_t* white_point() const { return m_white_point; }
point_t* red() const { return m_red; }
point_t* green() const { return m_green; }
point_t* blue() const { return m_blue; }
png_t* _root() const { return m__root; }
png_t::chunk_t* _parent() const { return m__parent; }
};
/**
* \sa https://www.w3.org/TR/png/#11IHDR Source
*/
class ihdr_chunk_t : public kaitai::kstruct {
public:
ihdr_chunk_t(kaitai::kstream* p__io, png_t* p__parent = 0, png_t* p__root = 0);
private:
void _read();
void _clean_up();
public:
~ihdr_chunk_t();
private:
uint32_t m_width;
uint32_t m_height;
uint8_t m_bit_depth;
color_type_t m_color_type;
uint8_t m_compression_method;
uint8_t m_filter_method;
uint8_t m_interlace_method;
png_t* m__root;
png_t* m__parent;
public:
uint32_t width() const { return m_width; }
uint32_t height() const { return m_height; }
uint8_t bit_depth() const { return m_bit_depth; }
color_type_t color_type() const { return m_color_type; }
uint8_t compression_method() const { return m_compression_method; }
uint8_t filter_method() const { return m_filter_method; }
uint8_t interlace_method() const { return m_interlace_method; }
png_t* _root() const { return m__root; }
png_t* _parent() const { return m__parent; }
};
/**
* \sa https://www.w3.org/TR/png/#11PLTE Source
*/
class plte_chunk_t : public kaitai::kstruct {
public:
plte_chunk_t(kaitai::kstream* p__io, png_t::chunk_t* p__parent = 0, png_t* p__root = 0);
private:
void _read();
void _clean_up();
public:
~plte_chunk_t();
private:
std::vector<rgb_t*>* m_entries;
png_t* m__root;
png_t::chunk_t* m__parent;
public:
std::vector<rgb_t*>* entries() const { return m_entries; }
png_t* _root() const { return m__root; }
png_t::chunk_t* _parent() const { return m__parent; }
};
/**
* \sa https://www.w3.org/TR/png/#11sRGB Source
*/
class srgb_chunk_t : public kaitai::kstruct {
public:
enum intent_t {
INTENT_PERCEPTUAL = 0,
INTENT_RELATIVE_COLORIMETRIC = 1,
INTENT_SATURATION = 2,
INTENT_ABSOLUTE_COLORIMETRIC = 3
};
srgb_chunk_t(kaitai::kstream* p__io, png_t::chunk_t* p__parent = 0, png_t* p__root = 0);
private:
void _read();
void _clean_up();
public:
~srgb_chunk_t();
private:
intent_t m_render_intent;
png_t* m__root;
png_t::chunk_t* m__parent;
public:
intent_t render_intent() const { return m_render_intent; }
png_t* _root() const { return m__root; }
png_t::chunk_t* _parent() const { return m__parent; }
};
/**
* Compressed text chunk effectively allows to store key-value
* string pairs in PNG container, compressing "value" part (which
* can be quite lengthy) with zlib compression.
* \sa https://www.w3.org/TR/png/#11zTXt Source
*/
class compressed_text_chunk_t : public kaitai::kstruct {
public:
compressed_text_chunk_t(kaitai::kstream* p__io, png_t::chunk_t* p__parent = 0, png_t* p__root = 0);
private:
void _read();
void _clean_up();
public:
~compressed_text_chunk_t();
private:
std::string m_keyword;
compression_methods_t m_compression_method;
std::string m_text_datastream;
png_t* m__root;
png_t::chunk_t* m__parent;
std::string m__raw_text_datastream;
kaitai::kstream* m__io_text_datastream;
public:
/**
* Indicates purpose of the following text data.
*/
std::string keyword() const { return m_keyword; }
compression_methods_t compression_method() const { return m_compression_method; }
std::string text_datastream() const { return m_text_datastream; }
png_t* _root() const { return m__root; }
png_t::chunk_t* _parent() const { return m__parent; }
std::string _raw_text_datastream() const { return m__raw_text_datastream; }
kaitai::kstream* _io_text_datastream() const { return m__io_text_datastream; }
};
/**
* \sa https://wiki.mozilla.org/APNG_Specification#.60fdAT.60:_The_Frame_Data_Chunk Source
*/
class frame_data_chunk_t : public kaitai::kstruct {
public:
frame_data_chunk_t(kaitai::kstream* p__io, png_t::chunk_t* p__parent = 0, png_t* p__root = 0);
private:
void _read();
void _clean_up();
public:
~frame_data_chunk_t();
private:
uint32_t m_sequence_number;
std::string m_frame_data;
png_t* m__root;
png_t::chunk_t* m__parent;
public:
/**
* Sequence number of the animation chunk. The fcTL and fdAT chunks
* have a 4 byte sequence number. Both chunk types share the sequence.
* The first fcTL chunk must contain sequence number 0, and the sequence
* numbers in the remaining fcTL and fdAT chunks must be in order, with
* no gaps or duplicates.
*/
uint32_t sequence_number() const { return m_sequence_number; }
/**
* Frame data for the frame. At least one fdAT chunk is required for
* each frame. The compressed datastream is the concatenation of the
* contents of the data fields of all the fdAT chunks within a frame.
*/
std::string frame_data() const { return m_frame_data; }
png_t* _root() const { return m__root; }
png_t::chunk_t* _parent() const { return m__parent; }
};
/**
* Background chunk for truecolor images.
*/
class bkgd_truecolor_t : public kaitai::kstruct {
public:
bkgd_truecolor_t(kaitai::kstream* p__io, png_t::bkgd_chunk_t* p__parent = 0, png_t* p__root = 0);
private:
void _read();
void _clean_up();
public:
~bkgd_truecolor_t();
private:
uint16_t m_red;
uint16_t m_green;
uint16_t m_blue;
png_t* m__root;
png_t::bkgd_chunk_t* m__parent;
public:
uint16_t red() const { return m_red; }
uint16_t green() const { return m_green; }
uint16_t blue() const { return m_blue; }
png_t* _root() const { return m__root; }
png_t::bkgd_chunk_t* _parent() const { return m__parent; }
};
/**
* \sa https://www.w3.org/TR/png/#11gAMA Source
*/
class gama_chunk_t : public kaitai::kstruct {
public:
gama_chunk_t(kaitai::kstream* p__io, png_t::chunk_t* p__parent = 0, png_t* p__root = 0);
private:
void _read();
void _clean_up();
public:
~gama_chunk_t();
private:
bool f_gamma_ratio;
double m_gamma_ratio;
public:
double gamma_ratio();
private:
uint32_t m_gamma_int;
png_t* m__root;
png_t::chunk_t* m__parent;
public:
uint32_t gamma_int() const { return m_gamma_int; }
png_t* _root() const { return m__root; }
png_t::chunk_t* _parent() const { return m__parent; }
};
/**
* Background chunk stores default background color to display this
* image against. Contents depend on `color_type` of the image.
* \sa https://www.w3.org/TR/png/#11bKGD Source
*/
class bkgd_chunk_t : public kaitai::kstruct {
public:
bkgd_chunk_t(kaitai::kstream* p__io, png_t::chunk_t* p__parent = 0, png_t* p__root = 0);
private:
void _read();
void _clean_up();
public:
~bkgd_chunk_t();
private:
kaitai::kstruct* m_bkgd;
bool n_bkgd;
public:
bool _is_null_bkgd() { bkgd(); return n_bkgd; };
private:
png_t* m__root;
png_t::chunk_t* m__parent;
public:
kaitai::kstruct* bkgd() const { return m_bkgd; }
png_t* _root() const { return m__root; }
png_t::chunk_t* _parent() const { return m__parent; }
};
/**
* "Physical size" chunk stores data that allows to translate
* logical pixels into physical units (meters, etc) and vice-versa.
* \sa https://www.w3.org/TR/png/#11pHYs Source
*/
class phys_chunk_t : public kaitai::kstruct {
public:
phys_chunk_t(kaitai::kstream* p__io, png_t::chunk_t* p__parent = 0, png_t* p__root = 0);
private:
void _read();
void _clean_up();
public:
~phys_chunk_t();
private:
uint32_t m_pixels_per_unit_x;
uint32_t m_pixels_per_unit_y;
phys_unit_t m_unit;
png_t* m__root;
png_t::chunk_t* m__parent;
public:
/**
* Number of pixels per physical unit (typically, 1 meter) by X
* axis.
*/
uint32_t pixels_per_unit_x() const { return m_pixels_per_unit_x; }
/**
* Number of pixels per physical unit (typically, 1 meter) by Y
* axis.
*/
uint32_t pixels_per_unit_y() const { return m_pixels_per_unit_y; }
phys_unit_t unit() const { return m_unit; }
png_t* _root() const { return m__root; }
png_t::chunk_t* _parent() const { return m__parent; }
};
/**
* \sa https://wiki.mozilla.org/APNG_Specification#.60fcTL.60:_The_Frame_Control_Chunk Source
*/
class frame_control_chunk_t : public kaitai::kstruct {
public:
frame_control_chunk_t(kaitai::kstream* p__io, png_t::chunk_t* p__parent = 0, png_t* p__root = 0);
private:
void _read();
void _clean_up();
public:
~frame_control_chunk_t();
private:
bool f_delay;
double m_delay;
public:
/**
* Time to display this frame, in seconds
*/
double delay();
private:
uint32_t m_sequence_number;
uint32_t m_width;
uint32_t m_height;
uint32_t m_x_offset;
uint32_t m_y_offset;
uint16_t m_delay_num;
uint16_t m_delay_den;
dispose_op_values_t m_dispose_op;
blend_op_values_t m_blend_op;
png_t* m__root;
png_t::chunk_t* m__parent;
public:
/**
* Sequence number of the animation chunk
*/
uint32_t sequence_number() const { return m_sequence_number; }
/**
* Width of the following frame
*/
uint32_t width() const { return m_width; }
/**
* Height of the following frame
*/
uint32_t height() const { return m_height; }
/**
* X position at which to render the following frame
*/
uint32_t x_offset() const { return m_x_offset; }
/**
* Y position at which to render the following frame
*/
uint32_t y_offset() const { return m_y_offset; }
/**
* Frame delay fraction numerator
*/
uint16_t delay_num() const { return m_delay_num; }
/**
* Frame delay fraction denominator
*/
uint16_t delay_den() const { return m_delay_den; }
/**
* Type of frame area disposal to be done after rendering this frame
*/
dispose_op_values_t dispose_op() const { return m_dispose_op; }
/**
* Type of frame area rendering for this frame
*/
blend_op_values_t blend_op() const { return m_blend_op; }
png_t* _root() const { return m__root; }
png_t::chunk_t* _parent() const { return m__parent; }
};
/**
* International text chunk effectively allows to store key-value string pairs in
* PNG container. Both "key" (keyword) and "value" (text) parts are
* given in pre-defined subset of iso8859-1 without control
* characters.
* \sa https://www.w3.org/TR/png/#11iTXt Source
*/
class international_text_chunk_t : public kaitai::kstruct {
public:
international_text_chunk_t(kaitai::kstream* p__io, png_t::chunk_t* p__parent = 0, png_t* p__root = 0);
private:
void _read();
void _clean_up();
public:
~international_text_chunk_t();
private:
std::string m_keyword;
uint8_t m_compression_flag;
compression_methods_t m_compression_method;
std::string m_language_tag;
std::string m_translated_keyword;
std::string m_text;
png_t* m__root;
png_t::chunk_t* m__parent;
public:
/**
* Indicates purpose of the following text data.
*/
std::string keyword() const { return m_keyword; }
/**
* 0 = text is uncompressed, 1 = text is compressed with a
* method specified in `compression_method`.
*/
uint8_t compression_flag() const { return m_compression_flag; }
compression_methods_t compression_method() const { return m_compression_method; }
/**
* Human language used in `translated_keyword` and `text`
* attributes - should be a language code conforming to ISO
* 646.IRV:1991.
*/
std::string language_tag() const { return m_language_tag; }
/**
* Keyword translated into language specified in
* `language_tag`. Line breaks are not allowed.
*/
std::string translated_keyword() const { return m_translated_keyword; }
/**
* Text contents ("value" of this key-value pair), written in
* language specified in `language_tag`. Line breaks are
* allowed.
*/
std::string text() const { return m_text; }
png_t* _root() const { return m__root; }
png_t::chunk_t* _parent() const { return m__parent; }
};
/**
* Text chunk effectively allows to store key-value string pairs in
* PNG container. Both "key" (keyword) and "value" (text) parts are
* given in pre-defined subset of iso8859-1 without control
* characters.
* \sa https://www.w3.org/TR/png/#11tEXt Source
*/
class text_chunk_t : public kaitai::kstruct {
public:
text_chunk_t(kaitai::kstream* p__io, png_t::chunk_t* p__parent = 0, png_t* p__root = 0);
private:
void _read();
void _clean_up();
public:
~text_chunk_t();
private:
std::string m_keyword;
std::string m_text;
png_t* m__root;
png_t::chunk_t* m__parent;
public:
/**
* Indicates purpose of the following text data.
*/
std::string keyword() const { return m_keyword; }
std::string text() const { return m_text; }
png_t* _root() const { return m__root; }
png_t::chunk_t* _parent() const { return m__parent; }
};
/**
* \sa https://wiki.mozilla.org/APNG_Specification#.60acTL.60:_The_Animation_Control_Chunk Source
*/
class animation_control_chunk_t : public kaitai::kstruct {
public:
animation_control_chunk_t(kaitai::kstream* p__io, png_t::chunk_t* p__parent = 0, png_t* p__root = 0);
private:
void _read();
void _clean_up();
public:
~animation_control_chunk_t();
private:
uint32_t m_num_frames;
uint32_t m_num_plays;
png_t* m__root;
png_t::chunk_t* m__parent;
public:
/**
* Number of frames, must be equal to the number of `frame_control_chunk`s
*/
uint32_t num_frames() const { return m_num_frames; }
/**
* Number of times to loop, 0 indicates infinite looping.
*/
uint32_t num_plays() const { return m_num_plays; }
png_t* _root() const { return m__root; }
png_t::chunk_t* _parent() const { return m__parent; }
};
/**
* Time chunk stores time stamp of last modification of this image,
* up to 1 second precision in UTC timezone.
* \sa https://www.w3.org/TR/png/#11tIME Source
*/
class time_chunk_t : public kaitai::kstruct {
public:
time_chunk_t(kaitai::kstream* p__io, png_t::chunk_t* p__parent = 0, png_t* p__root = 0);
private:
void _read();
void _clean_up();
public:
~time_chunk_t();
private:
uint16_t m_year;
uint8_t m_month;
uint8_t m_day;
uint8_t m_hour;
uint8_t m_minute;
uint8_t m_second;
png_t* m__root;
png_t::chunk_t* m__parent;
public:
uint16_t year() const { return m_year; }
uint8_t month() const { return m_month; }
uint8_t day() const { return m_day; }
uint8_t hour() const { return m_hour; }
uint8_t minute() const { return m_minute; }
uint8_t second() const { return m_second; }
png_t* _root() const { return m__root; }
png_t::chunk_t* _parent() const { return m__parent; }
};
private:
std::string m_magic;
uint32_t m_ihdr_len;
std::string m_ihdr_type;
ihdr_chunk_t* m_ihdr;
std::string m_ihdr_crc;
std::vector<chunk_t*>* m_chunks;
png_t* m__root;
kaitai::kstruct* m__parent;
public:
std::string magic() const { return m_magic; }
uint32_t ihdr_len() const { return m_ihdr_len; }
std::string ihdr_type() const { return m_ihdr_type; }
ihdr_chunk_t* ihdr() const { return m_ihdr; }
std::string ihdr_crc() const { return m_ihdr_crc; }
std::vector<chunk_t*>* chunks() const { return m_chunks; }
png_t* _root() const { return m__root; }
kaitai::kstruct* _parent() const { return m__parent; }
};
#endif // PNG_H_
// This is a generated file! Please edit source .ksy file and use kaitai-struct-compiler to rebuild
#include "png.h"
#include "kaitai/exceptions.h"
png_t::png_t(kaitai::kstream* p__io, kaitai::kstruct* p__parent, png_t* p__root) : kaitai::kstruct(p__io) {
m__parent = p__parent;
m__root = this;
m_ihdr = 0;
m_chunks = 0;
try {
_read();
} catch(...) {
_clean_up();
throw;
}
}
void png_t::_read() {
m_magic = m__io->read_bytes(8);
if (!(magic() == std::string("\x89\x50\x4E\x47\x0D\x0A\x1A\x0A", 8))) {
throw kaitai::validation_not_equal_error<std::string>(std::string("\x89\x50\x4E\x47\x0D\x0A\x1A\x0A", 8), magic(), _io(), std::string("/seq/0"));
}
m_ihdr_len = m__io->read_u4be();
if (!(ihdr_len() == 13)) {
throw kaitai::validation_not_equal_error<uint32_t>(13, ihdr_len(), _io(), std::string("/seq/1"));
}
m_ihdr_type = m__io->read_bytes(4);
if (!(ihdr_type() == std::string("\x49\x48\x44\x52", 4))) {
throw kaitai::validation_not_equal_error<std::string>(std::string("\x49\x48\x44\x52", 4), ihdr_type(), _io(), std::string("/seq/2"));
}
m_ihdr = new ihdr_chunk_t(m__io, this, m__root);
m_ihdr_crc = m__io->read_bytes(4);
m_chunks = new std::vector<chunk_t*>();
{
int i = 0;
chunk_t* _;
do {
_ = new chunk_t(m__io, this, m__root);
m_chunks->push_back(_);
i++;
} while (!( ((_->type() == (std::string("IEND"))) || (_io()->is_eof())) ));
}
}
png_t::~png_t() {
_clean_up();
}
void png_t::_clean_up() {
if (m_ihdr) {
delete m_ihdr; m_ihdr = 0;
}
if (m_chunks) {
for (std::vector<chunk_t*>::iterator it = m_chunks->begin(); it != m_chunks->end(); ++it) {
delete *it;
}
delete m_chunks; m_chunks = 0;
}
}
png_t::rgb_t::rgb_t(kaitai::kstream* p__io, png_t::plte_chunk_t* p__parent, png_t* p__root) : kaitai::kstruct(p__io) {
m__parent = p__parent;
m__root = p__root;
try {
_read();
} catch(...) {
_clean_up();
throw;
}
}
void png_t::rgb_t::_read() {
m_r = m__io->read_u1();
m_g = m__io->read_u1();
m_b = m__io->read_u1();
}
png_t::rgb_t::~rgb_t() {
_clean_up();
}
void png_t::rgb_t::_clean_up() {
}
png_t::chunk_t::chunk_t(kaitai::kstream* p__io, png_t* p__parent, png_t* p__root) : kaitai::kstruct(p__io) {
m__parent = p__parent;
m__root = p__root;
m__io__raw_body = 0;
try {
_read();
} catch(...) {
_clean_up();
throw;
}
}
void png_t::chunk_t::_read() {
m_len = m__io->read_u4be();
m_type = kaitai::kstream::bytes_to_str(m__io->read_bytes(4), std::string("UTF-8"));
n_body = true;
{
std::string on = type();
if (on == std::string("iTXt")) {
n_body = false;
m__raw_body = m__io->read_bytes(len());
m__io__raw_body = new kaitai::kstream(m__raw_body);
m_body = new international_text_chunk_t(m__io__raw_body, this, m__root);
}
else if (on == std::string("gAMA")) {
n_body = false;
m__raw_body = m__io->read_bytes(len());
m__io__raw_body = new kaitai::kstream(m__raw_body);
m_body = new gama_chunk_t(m__io__raw_body, this, m__root);
}
else if (on == std::string("tIME")) {
n_body = false;
m__raw_body = m__io->read_bytes(len());
m__io__raw_body = new kaitai::kstream(m__raw_body);
m_body = new time_chunk_t(m__io__raw_body, this, m__root);
}
else if (on == std::string("PLTE")) {
n_body = false;
m__raw_body = m__io->read_bytes(len());
m__io__raw_body = new kaitai::kstream(m__raw_body);
m_body = new plte_chunk_t(m__io__raw_body, this, m__root);
}
else if (on == std::string("bKGD")) {
n_body = false;
m__raw_body = m__io->read_bytes(len());
m__io__raw_body = new kaitai::kstream(m__raw_body);
m_body = new bkgd_chunk_t(m__io__raw_body, this, m__root);
}
else if (on == std::string("pHYs")) {
n_body = false;
m__raw_body = m__io->read_bytes(len());
m__io__raw_body = new kaitai::kstream(m__raw_body);
m_body = new phys_chunk_t(m__io__raw_body, this, m__root);
}
else if (on == std::string("fdAT")) {
n_body = false;
m__raw_body = m__io->read_bytes(len());
m__io__raw_body = new kaitai::kstream(m__raw_body);
m_body = new frame_data_chunk_t(m__io__raw_body, this, m__root);
}
else if (on == std::string("tEXt")) {
n_body = false;
m__raw_body = m__io->read_bytes(len());
m__io__raw_body = new kaitai::kstream(m__raw_body);
m_body = new text_chunk_t(m__io__raw_body, this, m__root);
}
else if (on == std::string("cHRM")) {
n_body = false;
m__raw_body = m__io->read_bytes(len());
m__io__raw_body = new kaitai::kstream(m__raw_body);
m_body = new chrm_chunk_t(m__io__raw_body, this, m__root);
}
else if (on == std::string("acTL")) {
n_body = false;
m__raw_body = m__io->read_bytes(len());
m__io__raw_body = new kaitai::kstream(m__raw_body);
m_body = new animation_control_chunk_t(m__io__raw_body, this, m__root);
}
else if (on == std::string("sRGB")) {
n_body = false;
m__raw_body = m__io->read_bytes(len());
m__io__raw_body = new kaitai::kstream(m__raw_body);
m_body = new srgb_chunk_t(m__io__raw_body, this, m__root);
}
else if (on == std::string("zTXt")) {
n_body = false;
m__raw_body = m__io->read_bytes(len());
m__io__raw_body = new kaitai::kstream(m__raw_body);
m_body = new compressed_text_chunk_t(m__io__raw_body, this, m__root);
}
else if (on == std::string("fcTL")) {
n_body = false;
m__raw_body = m__io->read_bytes(len());
m__io__raw_body = new kaitai::kstream(m__raw_body);
m_body = new frame_control_chunk_t(m__io__raw_body, this, m__root);
}
else {
m__raw_body = m__io->read_bytes(len());
}
}
m_crc = m__io->read_bytes(4);
}
png_t::chunk_t::~chunk_t() {
_clean_up();
}
void png_t::chunk_t::_clean_up() {
if (!n_body) {
if (m__io__raw_body) {
delete m__io__raw_body; m__io__raw_body = 0;
}
if (m_body) {
delete m_body; m_body = 0;
}
}
}
png_t::bkgd_indexed_t::bkgd_indexed_t(kaitai::kstream* p__io, png_t::bkgd_chunk_t* p__parent, png_t* p__root) : kaitai::kstruct(p__io) {
m__parent = p__parent;
m__root = p__root;
try {
_read();
} catch(...) {
_clean_up();
throw;
}
}
void png_t::bkgd_indexed_t::_read() {
m_palette_index = m__io->read_u1();
}
png_t::bkgd_indexed_t::~bkgd_indexed_t() {
_clean_up();
}
void png_t::bkgd_indexed_t::_clean_up() {
}
png_t::point_t::point_t(kaitai::kstream* p__io, png_t::chrm_chunk_t* p__parent, png_t* p__root) : kaitai::kstruct(p__io) {
m__parent = p__parent;
m__root = p__root;
f_x = false;
f_y = false;
try {
_read();
} catch(...) {
_clean_up();
throw;
}
}
void png_t::point_t::_read() {
m_x_int = m__io->read_u4be();
m_y_int = m__io->read_u4be();
}
png_t::point_t::~point_t() {
_clean_up();
}
void png_t::point_t::_clean_up() {
}
double png_t::point_t::x() {
if (f_x)
return m_x;
m_x = (x_int() / 100000.0);
f_x = true;
return m_x;
}
double png_t::point_t::y() {
if (f_y)
return m_y;
m_y = (y_int() / 100000.0);
f_y = true;
return m_y;
}
png_t::bkgd_greyscale_t::bkgd_greyscale_t(kaitai::kstream* p__io, png_t::bkgd_chunk_t* p__parent, png_t* p__root) : kaitai::kstruct(p__io) {
m__parent = p__parent;
m__root = p__root;
try {
_read();
} catch(...) {
_clean_up();
throw;
}
}
void png_t::bkgd_greyscale_t::_read() {
m_value = m__io->read_u2be();
}
png_t::bkgd_greyscale_t::~bkgd_greyscale_t() {
_clean_up();
}
void png_t::bkgd_greyscale_t::_clean_up() {
}
png_t::chrm_chunk_t::chrm_chunk_t(kaitai::kstream* p__io, png_t::chunk_t* p__parent, png_t* p__root) : kaitai::kstruct(p__io) {
m__parent = p__parent;
m__root = p__root;
m_white_point = 0;
m_red = 0;
m_green = 0;
m_blue = 0;
try {
_read();
} catch(...) {
_clean_up();
throw;
}
}
void png_t::chrm_chunk_t::_read() {
m_white_point = new point_t(m__io, this, m__root);
m_red = new point_t(m__io, this, m__root);
m_green = new point_t(m__io, this, m__root);
m_blue = new point_t(m__io, this, m__root);
}
png_t::chrm_chunk_t::~chrm_chunk_t() {
_clean_up();
}
void png_t::chrm_chunk_t::_clean_up() {
if (m_white_point) {
delete m_white_point; m_white_point = 0;
}
if (m_red) {
delete m_red; m_red = 0;
}
if (m_green) {
delete m_green; m_green = 0;
}
if (m_blue) {
delete m_blue; m_blue = 0;
}
}
png_t::ihdr_chunk_t::ihdr_chunk_t(kaitai::kstream* p__io, png_t* p__parent, png_t* p__root) : kaitai::kstruct(p__io) {
m__parent = p__parent;
m__root = p__root;
try {
_read();
} catch(...) {
_clean_up();
throw;
}
}
void png_t::ihdr_chunk_t::_read() {
m_width = m__io->read_u4be();
m_height = m__io->read_u4be();
m_bit_depth = m__io->read_u1();
m_color_type = static_cast<png_t::color_type_t>(m__io->read_u1());
m_compression_method = m__io->read_u1();
m_filter_method = m__io->read_u1();
m_interlace_method = m__io->read_u1();
}
png_t::ihdr_chunk_t::~ihdr_chunk_t() {
_clean_up();
}
void png_t::ihdr_chunk_t::_clean_up() {
}
png_t::plte_chunk_t::plte_chunk_t(kaitai::kstream* p__io, png_t::chunk_t* p__parent, png_t* p__root) : kaitai::kstruct(p__io) {
m__parent = p__parent;
m__root = p__root;
m_entries = 0;
try {
_read();
} catch(...) {
_clean_up();
throw;
}
}
void png_t::plte_chunk_t::_read() {
m_entries = new std::vector<rgb_t*>();
{
int i = 0;
while (!m__io->is_eof()) {
m_entries->push_back(new rgb_t(m__io, this, m__root));
i++;
}
}
}
png_t::plte_chunk_t::~plte_chunk_t() {
_clean_up();
}
void png_t::plte_chunk_t::_clean_up() {
if (m_entries) {
for (std::vector<rgb_t*>::iterator it = m_entries->begin(); it != m_entries->end(); ++it) {
delete *it;
}
delete m_entries; m_entries = 0;
}
}
png_t::srgb_chunk_t::srgb_chunk_t(kaitai::kstream* p__io, png_t::chunk_t* p__parent, png_t* p__root) : kaitai::kstruct(p__io) {
m__parent = p__parent;
m__root = p__root;
try {
_read();
} catch(...) {
_clean_up();
throw;
}
}
void png_t::srgb_chunk_t::_read() {
m_render_intent = static_cast<png_t::srgb_chunk_t::intent_t>(m__io->read_u1());
}
png_t::srgb_chunk_t::~srgb_chunk_t() {
_clean_up();
}
void png_t::srgb_chunk_t::_clean_up() {
}
png_t::compressed_text_chunk_t::compressed_text_chunk_t(kaitai::kstream* p__io, png_t::chunk_t* p__parent, png_t* p__root) : kaitai::kstruct(p__io) {
m__parent = p__parent;
m__root = p__root;
m__io_text_datastream = 0;
try {
_read();
} catch(...) {
_clean_up();
throw;
}
}
void png_t::compressed_text_chunk_t::_read() {
m_keyword = kaitai::kstream::bytes_to_str(m__io->read_bytes_term(0, false, true, true), std::string("UTF-8"));
m_compression_method = static_cast<png_t::compression_methods_t>(m__io->read_u1());
m__raw_text_datastream = m__io->read_bytes_full();
m_text_datastream = kaitai::kstream::process_zlib(m__raw_text_datastream);
}
png_t::compressed_text_chunk_t::~compressed_text_chunk_t() {
_clean_up();
}
void png_t::compressed_text_chunk_t::_clean_up() {
}
png_t::frame_data_chunk_t::frame_data_chunk_t(kaitai::kstream* p__io, png_t::chunk_t* p__parent, png_t* p__root) : kaitai::kstruct(p__io) {
m__parent = p__parent;
m__root = p__root;
try {
_read();
} catch(...) {
_clean_up();
throw;
}
}
void png_t::frame_data_chunk_t::_read() {
m_sequence_number = m__io->read_u4be();
m_frame_data = m__io->read_bytes_full();
}
png_t::frame_data_chunk_t::~frame_data_chunk_t() {
_clean_up();
}
void png_t::frame_data_chunk_t::_clean_up() {
}
png_t::bkgd_truecolor_t::bkgd_truecolor_t(kaitai::kstream* p__io, png_t::bkgd_chunk_t* p__parent, png_t* p__root) : kaitai::kstruct(p__io) {
m__parent = p__parent;
m__root = p__root;
try {
_read();
} catch(...) {
_clean_up();
throw;
}
}
void png_t::bkgd_truecolor_t::_read() {
m_red = m__io->read_u2be();
m_green = m__io->read_u2be();
m_blue = m__io->read_u2be();
}
png_t::bkgd_truecolor_t::~bkgd_truecolor_t() {
_clean_up();
}
void png_t::bkgd_truecolor_t::_clean_up() {
}
png_t::gama_chunk_t::gama_chunk_t(kaitai::kstream* p__io, png_t::chunk_t* p__parent, png_t* p__root) : kaitai::kstruct(p__io) {
m__parent = p__parent;
m__root = p__root;
f_gamma_ratio = false;
try {
_read();
} catch(...) {
_clean_up();
throw;
}
}
void png_t::gama_chunk_t::_read() {
m_gamma_int = m__io->read_u4be();
}
png_t::gama_chunk_t::~gama_chunk_t() {
_clean_up();
}
void png_t::gama_chunk_t::_clean_up() {
}
double png_t::gama_chunk_t::gamma_ratio() {
if (f_gamma_ratio)
return m_gamma_ratio;
m_gamma_ratio = (100000.0 / gamma_int());
f_gamma_ratio = true;
return m_gamma_ratio;
}
png_t::bkgd_chunk_t::bkgd_chunk_t(kaitai::kstream* p__io, png_t::chunk_t* p__parent, png_t* p__root) : kaitai::kstruct(p__io) {
m__parent = p__parent;
m__root = p__root;
try {
_read();
} catch(...) {
_clean_up();
throw;
}
}
void png_t::bkgd_chunk_t::_read() {
n_bkgd = true;
switch (_root()->ihdr()->color_type()) {
case png_t::COLOR_TYPE_INDEXED: {
n_bkgd = false;
m_bkgd = new bkgd_indexed_t(m__io, this, m__root);
break;
}
case png_t::COLOR_TYPE_TRUECOLOR_ALPHA: {
n_bkgd = false;
m_bkgd = new bkgd_truecolor_t(m__io, this, m__root);
break;
}
case png_t::COLOR_TYPE_GREYSCALE_ALPHA: {
n_bkgd = false;
m_bkgd = new bkgd_greyscale_t(m__io, this, m__root);
break;
}
case png_t::COLOR_TYPE_TRUECOLOR: {
n_bkgd = false;
m_bkgd = new bkgd_truecolor_t(m__io, this, m__root);
break;
}
case png_t::COLOR_TYPE_GREYSCALE: {
n_bkgd = false;
m_bkgd = new bkgd_greyscale_t(m__io, this, m__root);
break;
}
}
}
png_t::bkgd_chunk_t::~bkgd_chunk_t() {
_clean_up();
}
void png_t::bkgd_chunk_t::_clean_up() {
if (!n_bkgd) {
if (m_bkgd) {
delete m_bkgd; m_bkgd = 0;
}
}
}
png_t::phys_chunk_t::phys_chunk_t(kaitai::kstream* p__io, png_t::chunk_t* p__parent, png_t* p__root) : kaitai::kstruct(p__io) {
m__parent = p__parent;
m__root = p__root;
try {
_read();
} catch(...) {
_clean_up();
throw;
}
}
void png_t::phys_chunk_t::_read() {
m_pixels_per_unit_x = m__io->read_u4be();
m_pixels_per_unit_y = m__io->read_u4be();
m_unit = static_cast<png_t::phys_unit_t>(m__io->read_u1());
}
png_t::phys_chunk_t::~phys_chunk_t() {
_clean_up();
}
void png_t::phys_chunk_t::_clean_up() {
}
png_t::frame_control_chunk_t::frame_control_chunk_t(kaitai::kstream* p__io, png_t::chunk_t* p__parent, png_t* p__root) : kaitai::kstruct(p__io) {
m__parent = p__parent;
m__root = p__root;
f_delay = false;
try {
_read();
} catch(...) {
_clean_up();
throw;
}
}
void png_t::frame_control_chunk_t::_read() {
m_sequence_number = m__io->read_u4be();
m_width = m__io->read_u4be();
if (!(width() >= 1)) {
throw kaitai::validation_less_than_error<uint32_t>(1, width(), _io(), std::string("/types/frame_control_chunk/seq/1"));
}
if (!(width() <= _root()->ihdr()->width())) {
throw kaitai::validation_greater_than_error<uint32_t>(_root()->ihdr()->width(), width(), _io(), std::string("/types/frame_control_chunk/seq/1"));
}
m_height = m__io->read_u4be();
if (!(height() >= 1)) {
throw kaitai::validation_less_than_error<uint32_t>(1, height(), _io(), std::string("/types/frame_control_chunk/seq/2"));
}
if (!(height() <= _root()->ihdr()->height())) {
throw kaitai::validation_greater_than_error<uint32_t>(_root()->ihdr()->height(), height(), _io(), std::string("/types/frame_control_chunk/seq/2"));
}
m_x_offset = m__io->read_u4be();
if (!(x_offset() <= (_root()->ihdr()->width() - width()))) {
throw kaitai::validation_greater_than_error<uint32_t>((_root()->ihdr()->width() - width()), x_offset(), _io(), std::string("/types/frame_control_chunk/seq/3"));
}
m_y_offset = m__io->read_u4be();
if (!(y_offset() <= (_root()->ihdr()->height() - height()))) {
throw kaitai::validation_greater_than_error<uint32_t>((_root()->ihdr()->height() - height()), y_offset(), _io(), std::string("/types/frame_control_chunk/seq/4"));
}
m_delay_num = m__io->read_u2be();
m_delay_den = m__io->read_u2be();
m_dispose_op = static_cast<png_t::dispose_op_values_t>(m__io->read_u1());
m_blend_op = static_cast<png_t::blend_op_values_t>(m__io->read_u1());
}
png_t::frame_control_chunk_t::~frame_control_chunk_t() {
_clean_up();
}
void png_t::frame_control_chunk_t::_clean_up() {
}
double png_t::frame_control_chunk_t::delay() {
if (f_delay)
return m_delay;
m_delay = (delay_num() / ((delay_den() == 0) ? (100.0) : (delay_den())));
f_delay = true;
return m_delay;
}
png_t::international_text_chunk_t::international_text_chunk_t(kaitai::kstream* p__io, png_t::chunk_t* p__parent, png_t* p__root) : kaitai::kstruct(p__io) {
m__parent = p__parent;
m__root = p__root;
try {
_read();
} catch(...) {
_clean_up();
throw;
}
}
void png_t::international_text_chunk_t::_read() {
m_keyword = kaitai::kstream::bytes_to_str(m__io->read_bytes_term(0, false, true, true), std::string("UTF-8"));
m_compression_flag = m__io->read_u1();
m_compression_method = static_cast<png_t::compression_methods_t>(m__io->read_u1());
m_language_tag = kaitai::kstream::bytes_to_str(m__io->read_bytes_term(0, false, true, true), std::string("ASCII"));
m_translated_keyword = kaitai::kstream::bytes_to_str(m__io->read_bytes_term(0, false, true, true), std::string("UTF-8"));
m_text = kaitai::kstream::bytes_to_str(m__io->read_bytes_full(), std::string("UTF-8"));
}
png_t::international_text_chunk_t::~international_text_chunk_t() {
_clean_up();
}
void png_t::international_text_chunk_t::_clean_up() {
}
png_t::text_chunk_t::text_chunk_t(kaitai::kstream* p__io, png_t::chunk_t* p__parent, png_t* p__root) : kaitai::kstruct(p__io) {
m__parent = p__parent;
m__root = p__root;
try {
_read();
} catch(...) {
_clean_up();
throw;
}
}
void png_t::text_chunk_t::_read() {
m_keyword = kaitai::kstream::bytes_to_str(m__io->read_bytes_term(0, false, true, true), std::string("iso8859-1"));
m_text = kaitai::kstream::bytes_to_str(m__io->read_bytes_full(), std::string("iso8859-1"));
}
png_t::text_chunk_t::~text_chunk_t() {
_clean_up();
}
void png_t::text_chunk_t::_clean_up() {
}
png_t::animation_control_chunk_t::animation_control_chunk_t(kaitai::kstream* p__io, png_t::chunk_t* p__parent, png_t* p__root) : kaitai::kstruct(p__io) {
m__parent = p__parent;
m__root = p__root;
try {
_read();
} catch(...) {
_clean_up();
throw;
}
}
void png_t::animation_control_chunk_t::_read() {
m_num_frames = m__io->read_u4be();
m_num_plays = m__io->read_u4be();
}
png_t::animation_control_chunk_t::~animation_control_chunk_t() {
_clean_up();
}
void png_t::animation_control_chunk_t::_clean_up() {
}
png_t::time_chunk_t::time_chunk_t(kaitai::kstream* p__io, png_t::chunk_t* p__parent, png_t* p__root) : kaitai::kstruct(p__io) {
m__parent = p__parent;
m__root = p__root;
try {
_read();
} catch(...) {
_clean_up();
throw;
}
}
void png_t::time_chunk_t::_read() {
m_year = m__io->read_u2be();
m_month = m__io->read_u1();
m_day = m__io->read_u1();
m_hour = m__io->read_u1();
m_minute = m__io->read_u1();
m_second = m__io->read_u1();
}
png_t::time_chunk_t::~time_chunk_t() {
_clean_up();
}
void png_t::time_chunk_t::_clean_up() {
}