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# generated by Kaitai Struct depends on the C# runtime library. You have to install it before you can parse data.
The C# runtime library is available in the NuGet Gallery. Installation instructions can also be found there.
Parse a local file and get structure in memory:
var data = Png.FromFile("path/to/local/file.png");
Or parse structure from a byte array:
byte[] someArray = new byte[] { ... };
var data = new Png(new KaitaiStream(someArray));
After that, one can get various attributes from the structure by accessing properties like:
data.Magic // => get magic
// This is a generated file! Please edit source .ksy file and use kaitai-struct-compiler to rebuild
using System.Collections.Generic;
namespace Kaitai
{
/// <summary>
/// Test files for APNG can be found at the following locations:
///
/// * <https://philip.html5.org/tests/apng/tests.html>
/// * <http://littlesvr.ca/apng/>
/// </summary>
public partial class Png : KaitaiStruct
{
public static Png FromFile(string fileName)
{
return new Png(new KaitaiStream(fileName));
}
public enum PhysUnit
{
Unknown = 0,
Meter = 1,
}
public enum BlendOpValues
{
Source = 0,
Over = 1,
}
public enum CompressionMethods
{
Zlib = 0,
}
public enum DisposeOpValues
{
None = 0,
Background = 1,
Previous = 2,
}
public enum ColorType
{
Greyscale = 0,
Truecolor = 2,
Indexed = 3,
GreyscaleAlpha = 4,
TruecolorAlpha = 6,
}
public Png(KaitaiStream p__io, KaitaiStruct p__parent = null, Png p__root = null) : base(p__io)
{
m_parent = p__parent;
m_root = p__root ?? this;
_read();
}
private void _read()
{
_magic = m_io.ReadBytes(8);
if (!((KaitaiStream.ByteArrayCompare(Magic, new byte[] { 137, 80, 78, 71, 13, 10, 26, 10 }) == 0)))
{
throw new ValidationNotEqualError(new byte[] { 137, 80, 78, 71, 13, 10, 26, 10 }, Magic, M_Io, "/seq/0");
}
_ihdrLen = m_io.ReadU4be();
if (!(IhdrLen == 13))
{
throw new ValidationNotEqualError(13, IhdrLen, M_Io, "/seq/1");
}
_ihdrType = m_io.ReadBytes(4);
if (!((KaitaiStream.ByteArrayCompare(IhdrType, new byte[] { 73, 72, 68, 82 }) == 0)))
{
throw new ValidationNotEqualError(new byte[] { 73, 72, 68, 82 }, IhdrType, M_Io, "/seq/2");
}
_ihdr = new IhdrChunk(m_io, this, m_root);
_ihdrCrc = m_io.ReadBytes(4);
_chunks = new List<Chunk>();
{
var i = 0;
Chunk M_;
do {
M_ = new Chunk(m_io, this, m_root);
_chunks.Add(M_);
i++;
} while (!( ((M_.Type == "IEND") || (M_Io.IsEof)) ));
}
}
public partial class Rgb : KaitaiStruct
{
public static Rgb FromFile(string fileName)
{
return new Rgb(new KaitaiStream(fileName));
}
public Rgb(KaitaiStream p__io, Png.PlteChunk p__parent = null, Png p__root = null) : base(p__io)
{
m_parent = p__parent;
m_root = p__root;
_read();
}
private void _read()
{
_r = m_io.ReadU1();
_g = m_io.ReadU1();
_b = m_io.ReadU1();
}
private byte _r;
private byte _g;
private byte _b;
private Png m_root;
private Png.PlteChunk m_parent;
public byte R { get { return _r; } }
public byte G { get { return _g; } }
public byte B { get { return _b; } }
public Png M_Root { get { return m_root; } }
public Png.PlteChunk M_Parent { get { return m_parent; } }
}
public partial class Chunk : KaitaiStruct
{
public static Chunk FromFile(string fileName)
{
return new Chunk(new KaitaiStream(fileName));
}
public Chunk(KaitaiStream p__io, Png p__parent = null, Png p__root = null) : base(p__io)
{
m_parent = p__parent;
m_root = p__root;
_read();
}
private void _read()
{
_len = m_io.ReadU4be();
_type = System.Text.Encoding.GetEncoding("UTF-8").GetString(m_io.ReadBytes(4));
switch (Type) {
case "iTXt": {
__raw_body = m_io.ReadBytes(Len);
var io___raw_body = new KaitaiStream(__raw_body);
_body = new InternationalTextChunk(io___raw_body, this, m_root);
break;
}
case "gAMA": {
__raw_body = m_io.ReadBytes(Len);
var io___raw_body = new KaitaiStream(__raw_body);
_body = new GamaChunk(io___raw_body, this, m_root);
break;
}
case "tIME": {
__raw_body = m_io.ReadBytes(Len);
var io___raw_body = new KaitaiStream(__raw_body);
_body = new TimeChunk(io___raw_body, this, m_root);
break;
}
case "PLTE": {
__raw_body = m_io.ReadBytes(Len);
var io___raw_body = new KaitaiStream(__raw_body);
_body = new PlteChunk(io___raw_body, this, m_root);
break;
}
case "bKGD": {
__raw_body = m_io.ReadBytes(Len);
var io___raw_body = new KaitaiStream(__raw_body);
_body = new BkgdChunk(io___raw_body, this, m_root);
break;
}
case "pHYs": {
__raw_body = m_io.ReadBytes(Len);
var io___raw_body = new KaitaiStream(__raw_body);
_body = new PhysChunk(io___raw_body, this, m_root);
break;
}
case "fdAT": {
__raw_body = m_io.ReadBytes(Len);
var io___raw_body = new KaitaiStream(__raw_body);
_body = new FrameDataChunk(io___raw_body, this, m_root);
break;
}
case "tEXt": {
__raw_body = m_io.ReadBytes(Len);
var io___raw_body = new KaitaiStream(__raw_body);
_body = new TextChunk(io___raw_body, this, m_root);
break;
}
case "cHRM": {
__raw_body = m_io.ReadBytes(Len);
var io___raw_body = new KaitaiStream(__raw_body);
_body = new ChrmChunk(io___raw_body, this, m_root);
break;
}
case "acTL": {
__raw_body = m_io.ReadBytes(Len);
var io___raw_body = new KaitaiStream(__raw_body);
_body = new AnimationControlChunk(io___raw_body, this, m_root);
break;
}
case "sRGB": {
__raw_body = m_io.ReadBytes(Len);
var io___raw_body = new KaitaiStream(__raw_body);
_body = new SrgbChunk(io___raw_body, this, m_root);
break;
}
case "zTXt": {
__raw_body = m_io.ReadBytes(Len);
var io___raw_body = new KaitaiStream(__raw_body);
_body = new CompressedTextChunk(io___raw_body, this, m_root);
break;
}
case "fcTL": {
__raw_body = m_io.ReadBytes(Len);
var io___raw_body = new KaitaiStream(__raw_body);
_body = new FrameControlChunk(io___raw_body, this, m_root);
break;
}
default: {
_body = m_io.ReadBytes(Len);
break;
}
}
_crc = m_io.ReadBytes(4);
}
private uint _len;
private string _type;
private object _body;
private byte[] _crc;
private Png m_root;
private Png m_parent;
private byte[] __raw_body;
public uint Len { get { return _len; } }
public string Type { get { return _type; } }
public object Body { get { return _body; } }
public byte[] Crc { get { return _crc; } }
public Png M_Root { get { return m_root; } }
public Png M_Parent { get { return m_parent; } }
public byte[] M_RawBody { get { return __raw_body; } }
}
/// <summary>
/// Background chunk for images with indexed palette.
/// </summary>
public partial class BkgdIndexed : KaitaiStruct
{
public static BkgdIndexed FromFile(string fileName)
{
return new BkgdIndexed(new KaitaiStream(fileName));
}
public BkgdIndexed(KaitaiStream p__io, Png.BkgdChunk p__parent = null, Png p__root = null) : base(p__io)
{
m_parent = p__parent;
m_root = p__root;
_read();
}
private void _read()
{
_paletteIndex = m_io.ReadU1();
}
private byte _paletteIndex;
private Png m_root;
private Png.BkgdChunk m_parent;
public byte PaletteIndex { get { return _paletteIndex; } }
public Png M_Root { get { return m_root; } }
public Png.BkgdChunk M_Parent { get { return m_parent; } }
}
public partial class Point : KaitaiStruct
{
public static Point FromFile(string fileName)
{
return new Point(new KaitaiStream(fileName));
}
public Point(KaitaiStream p__io, Png.ChrmChunk p__parent = null, Png p__root = null) : base(p__io)
{
m_parent = p__parent;
m_root = p__root;
f_x = false;
f_y = false;
_read();
}
private void _read()
{
_xInt = m_io.ReadU4be();
_yInt = m_io.ReadU4be();
}
private bool f_x;
private double _x;
public double X
{
get
{
if (f_x)
return _x;
_x = (double) ((XInt / 100000.0));
f_x = true;
return _x;
}
}
private bool f_y;
private double _y;
public double Y
{
get
{
if (f_y)
return _y;
_y = (double) ((YInt / 100000.0));
f_y = true;
return _y;
}
}
private uint _xInt;
private uint _yInt;
private Png m_root;
private Png.ChrmChunk m_parent;
public uint XInt { get { return _xInt; } }
public uint YInt { get { return _yInt; } }
public Png M_Root { get { return m_root; } }
public Png.ChrmChunk M_Parent { get { return m_parent; } }
}
/// <summary>
/// Background chunk for greyscale images.
/// </summary>
public partial class BkgdGreyscale : KaitaiStruct
{
public static BkgdGreyscale FromFile(string fileName)
{
return new BkgdGreyscale(new KaitaiStream(fileName));
}
public BkgdGreyscale(KaitaiStream p__io, Png.BkgdChunk p__parent = null, Png p__root = null) : base(p__io)
{
m_parent = p__parent;
m_root = p__root;
_read();
}
private void _read()
{
_value = m_io.ReadU2be();
}
private ushort _value;
private Png m_root;
private Png.BkgdChunk m_parent;
public ushort Value { get { return _value; } }
public Png M_Root { get { return m_root; } }
public Png.BkgdChunk M_Parent { get { return m_parent; } }
}
/// <remarks>
/// Reference: <a href="https://www.w3.org/TR/png/#11cHRM">Source</a>
/// </remarks>
public partial class ChrmChunk : KaitaiStruct
{
public static ChrmChunk FromFile(string fileName)
{
return new ChrmChunk(new KaitaiStream(fileName));
}
public ChrmChunk(KaitaiStream p__io, Png.Chunk p__parent = null, Png p__root = null) : base(p__io)
{
m_parent = p__parent;
m_root = p__root;
_read();
}
private void _read()
{
_whitePoint = new Point(m_io, this, m_root);
_red = new Point(m_io, this, m_root);
_green = new Point(m_io, this, m_root);
_blue = new Point(m_io, this, m_root);
}
private Point _whitePoint;
private Point _red;
private Point _green;
private Point _blue;
private Png m_root;
private Png.Chunk m_parent;
public Point WhitePoint { get { return _whitePoint; } }
public Point Red { get { return _red; } }
public Point Green { get { return _green; } }
public Point Blue { get { return _blue; } }
public Png M_Root { get { return m_root; } }
public Png.Chunk M_Parent { get { return m_parent; } }
}
/// <remarks>
/// Reference: <a href="https://www.w3.org/TR/png/#11IHDR">Source</a>
/// </remarks>
public partial class IhdrChunk : KaitaiStruct
{
public static IhdrChunk FromFile(string fileName)
{
return new IhdrChunk(new KaitaiStream(fileName));
}
public IhdrChunk(KaitaiStream p__io, Png p__parent = null, Png p__root = null) : base(p__io)
{
m_parent = p__parent;
m_root = p__root;
_read();
}
private void _read()
{
_width = m_io.ReadU4be();
_height = m_io.ReadU4be();
_bitDepth = m_io.ReadU1();
_colorType = ((Png.ColorType) m_io.ReadU1());
_compressionMethod = m_io.ReadU1();
_filterMethod = m_io.ReadU1();
_interlaceMethod = m_io.ReadU1();
}
private uint _width;
private uint _height;
private byte _bitDepth;
private ColorType _colorType;
private byte _compressionMethod;
private byte _filterMethod;
private byte _interlaceMethod;
private Png m_root;
private Png m_parent;
public uint Width { get { return _width; } }
public uint Height { get { return _height; } }
public byte BitDepth { get { return _bitDepth; } }
public ColorType ColorType { get { return _colorType; } }
public byte CompressionMethod { get { return _compressionMethod; } }
public byte FilterMethod { get { return _filterMethod; } }
public byte InterlaceMethod { get { return _interlaceMethod; } }
public Png M_Root { get { return m_root; } }
public Png M_Parent { get { return m_parent; } }
}
/// <remarks>
/// Reference: <a href="https://www.w3.org/TR/png/#11PLTE">Source</a>
/// </remarks>
public partial class PlteChunk : KaitaiStruct
{
public static PlteChunk FromFile(string fileName)
{
return new PlteChunk(new KaitaiStream(fileName));
}
public PlteChunk(KaitaiStream p__io, Png.Chunk p__parent = null, Png p__root = null) : base(p__io)
{
m_parent = p__parent;
m_root = p__root;
_read();
}
private void _read()
{
_entries = new List<Rgb>();
{
var i = 0;
while (!m_io.IsEof) {
_entries.Add(new Rgb(m_io, this, m_root));
i++;
}
}
}
private List<Rgb> _entries;
private Png m_root;
private Png.Chunk m_parent;
public List<Rgb> Entries { get { return _entries; } }
public Png M_Root { get { return m_root; } }
public Png.Chunk M_Parent { get { return m_parent; } }
}
/// <remarks>
/// Reference: <a href="https://www.w3.org/TR/png/#11sRGB">Source</a>
/// </remarks>
public partial class SrgbChunk : KaitaiStruct
{
public static SrgbChunk FromFile(string fileName)
{
return new SrgbChunk(new KaitaiStream(fileName));
}
public enum Intent
{
Perceptual = 0,
RelativeColorimetric = 1,
Saturation = 2,
AbsoluteColorimetric = 3,
}
public SrgbChunk(KaitaiStream p__io, Png.Chunk p__parent = null, Png p__root = null) : base(p__io)
{
m_parent = p__parent;
m_root = p__root;
_read();
}
private void _read()
{
_renderIntent = ((Intent) m_io.ReadU1());
}
private Intent _renderIntent;
private Png m_root;
private Png.Chunk m_parent;
public Intent RenderIntent { get { return _renderIntent; } }
public Png M_Root { get { return m_root; } }
public Png.Chunk M_Parent { get { return m_parent; } }
}
/// <summary>
/// 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.
/// </summary>
/// <remarks>
/// Reference: <a href="https://www.w3.org/TR/png/#11zTXt">Source</a>
/// </remarks>
public partial class CompressedTextChunk : KaitaiStruct
{
public static CompressedTextChunk FromFile(string fileName)
{
return new CompressedTextChunk(new KaitaiStream(fileName));
}
public CompressedTextChunk(KaitaiStream p__io, Png.Chunk p__parent = null, Png p__root = null) : base(p__io)
{
m_parent = p__parent;
m_root = p__root;
_read();
}
private void _read()
{
_keyword = System.Text.Encoding.GetEncoding("UTF-8").GetString(m_io.ReadBytesTerm(0, false, true, true));
_compressionMethod = ((Png.CompressionMethods) m_io.ReadU1());
__raw_textDatastream = m_io.ReadBytesFull();
_textDatastream = m_io.ProcessZlib(__raw_textDatastream);
}
private string _keyword;
private CompressionMethods _compressionMethod;
private byte[] _textDatastream;
private Png m_root;
private Png.Chunk m_parent;
private byte[] __raw_textDatastream;
/// <summary>
/// Indicates purpose of the following text data.
/// </summary>
public string Keyword { get { return _keyword; } }
public CompressionMethods CompressionMethod { get { return _compressionMethod; } }
public byte[] TextDatastream { get { return _textDatastream; } }
public Png M_Root { get { return m_root; } }
public Png.Chunk M_Parent { get { return m_parent; } }
public byte[] M_RawTextDatastream { get { return __raw_textDatastream; } }
}
/// <remarks>
/// Reference: <a href="https://wiki.mozilla.org/APNG_Specification#.60fdAT.60:_The_Frame_Data_Chunk">Source</a>
/// </remarks>
public partial class FrameDataChunk : KaitaiStruct
{
public static FrameDataChunk FromFile(string fileName)
{
return new FrameDataChunk(new KaitaiStream(fileName));
}
public FrameDataChunk(KaitaiStream p__io, Png.Chunk p__parent = null, Png p__root = null) : base(p__io)
{
m_parent = p__parent;
m_root = p__root;
_read();
}
private void _read()
{
_sequenceNumber = m_io.ReadU4be();
_frameData = m_io.ReadBytesFull();
}
private uint _sequenceNumber;
private byte[] _frameData;
private Png m_root;
private Png.Chunk m_parent;
/// <summary>
/// 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.
/// </summary>
public uint SequenceNumber { get { return _sequenceNumber; } }
/// <summary>
/// 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.
/// </summary>
public byte[] FrameData { get { return _frameData; } }
public Png M_Root { get { return m_root; } }
public Png.Chunk M_Parent { get { return m_parent; } }
}
/// <summary>
/// Background chunk for truecolor images.
/// </summary>
public partial class BkgdTruecolor : KaitaiStruct
{
public static BkgdTruecolor FromFile(string fileName)
{
return new BkgdTruecolor(new KaitaiStream(fileName));
}
public BkgdTruecolor(KaitaiStream p__io, Png.BkgdChunk p__parent = null, Png p__root = null) : base(p__io)
{
m_parent = p__parent;
m_root = p__root;
_read();
}
private void _read()
{
_red = m_io.ReadU2be();
_green = m_io.ReadU2be();
_blue = m_io.ReadU2be();
}
private ushort _red;
private ushort _green;
private ushort _blue;
private Png m_root;
private Png.BkgdChunk m_parent;
public ushort Red { get { return _red; } }
public ushort Green { get { return _green; } }
public ushort Blue { get { return _blue; } }
public Png M_Root { get { return m_root; } }
public Png.BkgdChunk M_Parent { get { return m_parent; } }
}
/// <remarks>
/// Reference: <a href="https://www.w3.org/TR/png/#11gAMA">Source</a>
/// </remarks>
public partial class GamaChunk : KaitaiStruct
{
public static GamaChunk FromFile(string fileName)
{
return new GamaChunk(new KaitaiStream(fileName));
}
public GamaChunk(KaitaiStream p__io, Png.Chunk p__parent = null, Png p__root = null) : base(p__io)
{
m_parent = p__parent;
m_root = p__root;
f_gammaRatio = false;
_read();
}
private void _read()
{
_gammaInt = m_io.ReadU4be();
}
private bool f_gammaRatio;
private double _gammaRatio;
public double GammaRatio
{
get
{
if (f_gammaRatio)
return _gammaRatio;
_gammaRatio = (double) ((100000.0 / GammaInt));
f_gammaRatio = true;
return _gammaRatio;
}
}
private uint _gammaInt;
private Png m_root;
private Png.Chunk m_parent;
public uint GammaInt { get { return _gammaInt; } }
public Png M_Root { get { return m_root; } }
public Png.Chunk M_Parent { get { return m_parent; } }
}
/// <summary>
/// Background chunk stores default background color to display this
/// image against. Contents depend on `color_type` of the image.
/// </summary>
/// <remarks>
/// Reference: <a href="https://www.w3.org/TR/png/#11bKGD">Source</a>
/// </remarks>
public partial class BkgdChunk : KaitaiStruct
{
public static BkgdChunk FromFile(string fileName)
{
return new BkgdChunk(new KaitaiStream(fileName));
}
public BkgdChunk(KaitaiStream p__io, Png.Chunk p__parent = null, Png p__root = null) : base(p__io)
{
m_parent = p__parent;
m_root = p__root;
_read();
}
private void _read()
{
switch (M_Root.Ihdr.ColorType) {
case Png.ColorType.Indexed: {
_bkgd = new BkgdIndexed(m_io, this, m_root);
break;
}
case Png.ColorType.TruecolorAlpha: {
_bkgd = new BkgdTruecolor(m_io, this, m_root);
break;
}
case Png.ColorType.GreyscaleAlpha: {
_bkgd = new BkgdGreyscale(m_io, this, m_root);
break;
}
case Png.ColorType.Truecolor: {
_bkgd = new BkgdTruecolor(m_io, this, m_root);
break;
}
case Png.ColorType.Greyscale: {
_bkgd = new BkgdGreyscale(m_io, this, m_root);
break;
}
}
}
private KaitaiStruct _bkgd;
private Png m_root;
private Png.Chunk m_parent;
public KaitaiStruct Bkgd { get { return _bkgd; } }
public Png M_Root { get { return m_root; } }
public Png.Chunk M_Parent { get { return m_parent; } }
}
/// <summary>
/// "Physical size" chunk stores data that allows to translate
/// logical pixels into physical units (meters, etc) and vice-versa.
/// </summary>
/// <remarks>
/// Reference: <a href="https://www.w3.org/TR/png/#11pHYs">Source</a>
/// </remarks>
public partial class PhysChunk : KaitaiStruct
{
public static PhysChunk FromFile(string fileName)
{
return new PhysChunk(new KaitaiStream(fileName));
}
public PhysChunk(KaitaiStream p__io, Png.Chunk p__parent = null, Png p__root = null) : base(p__io)
{
m_parent = p__parent;
m_root = p__root;
_read();
}
private void _read()
{
_pixelsPerUnitX = m_io.ReadU4be();
_pixelsPerUnitY = m_io.ReadU4be();
_unit = ((Png.PhysUnit) m_io.ReadU1());
}
private uint _pixelsPerUnitX;
private uint _pixelsPerUnitY;
private PhysUnit _unit;
private Png m_root;
private Png.Chunk m_parent;
/// <summary>
/// Number of pixels per physical unit (typically, 1 meter) by X
/// axis.
/// </summary>
public uint PixelsPerUnitX { get { return _pixelsPerUnitX; } }
/// <summary>
/// Number of pixels per physical unit (typically, 1 meter) by Y
/// axis.
/// </summary>
public uint PixelsPerUnitY { get { return _pixelsPerUnitY; } }
public PhysUnit Unit { get { return _unit; } }
public Png M_Root { get { return m_root; } }
public Png.Chunk M_Parent { get { return m_parent; } }
}
/// <remarks>
/// Reference: <a href="https://wiki.mozilla.org/APNG_Specification#.60fcTL.60:_The_Frame_Control_Chunk">Source</a>
/// </remarks>
public partial class FrameControlChunk : KaitaiStruct
{
public static FrameControlChunk FromFile(string fileName)
{
return new FrameControlChunk(new KaitaiStream(fileName));
}
public FrameControlChunk(KaitaiStream p__io, Png.Chunk p__parent = null, Png p__root = null) : base(p__io)
{
m_parent = p__parent;
m_root = p__root;
f_delay = false;
_read();
}
private void _read()
{
_sequenceNumber = m_io.ReadU4be();
_width = m_io.ReadU4be();
if (!(Width >= 1))
{
throw new ValidationLessThanError(1, Width, M_Io, "/types/frame_control_chunk/seq/1");
}
if (!(Width <= M_Root.Ihdr.Width))
{
throw new ValidationGreaterThanError(M_Root.Ihdr.Width, Width, M_Io, "/types/frame_control_chunk/seq/1");
}
_height = m_io.ReadU4be();
if (!(Height >= 1))
{
throw new ValidationLessThanError(1, Height, M_Io, "/types/frame_control_chunk/seq/2");
}
if (!(Height <= M_Root.Ihdr.Height))
{
throw new ValidationGreaterThanError(M_Root.Ihdr.Height, Height, M_Io, "/types/frame_control_chunk/seq/2");
}
_xOffset = m_io.ReadU4be();
if (!(XOffset <= (M_Root.Ihdr.Width - Width)))
{
throw new ValidationGreaterThanError((M_Root.Ihdr.Width - Width), XOffset, M_Io, "/types/frame_control_chunk/seq/3");
}
_yOffset = m_io.ReadU4be();
if (!(YOffset <= (M_Root.Ihdr.Height - Height)))
{
throw new ValidationGreaterThanError((M_Root.Ihdr.Height - Height), YOffset, M_Io, "/types/frame_control_chunk/seq/4");
}
_delayNum = m_io.ReadU2be();
_delayDen = m_io.ReadU2be();
_disposeOp = ((Png.DisposeOpValues) m_io.ReadU1());
_blendOp = ((Png.BlendOpValues) m_io.ReadU1());
}
private bool f_delay;
private double _delay;
/// <summary>
/// Time to display this frame, in seconds
/// </summary>
public double Delay
{
get
{
if (f_delay)
return _delay;
_delay = (double) ((DelayNum / (DelayDen == 0 ? 100.0 : DelayDen)));
f_delay = true;
return _delay;
}
}
private uint _sequenceNumber;
private uint _width;
private uint _height;
private uint _xOffset;
private uint _yOffset;
private ushort _delayNum;
private ushort _delayDen;
private DisposeOpValues _disposeOp;
private BlendOpValues _blendOp;
private Png m_root;
private Png.Chunk m_parent;
/// <summary>
/// Sequence number of the animation chunk
/// </summary>
public uint SequenceNumber { get { return _sequenceNumber; } }
/// <summary>
/// Width of the following frame
/// </summary>
public uint Width { get { return _width; } }
/// <summary>
/// Height of the following frame
/// </summary>
public uint Height { get { return _height; } }
/// <summary>
/// X position at which to render the following frame
/// </summary>
public uint XOffset { get { return _xOffset; } }
/// <summary>
/// Y position at which to render the following frame
/// </summary>
public uint YOffset { get { return _yOffset; } }
/// <summary>
/// Frame delay fraction numerator
/// </summary>
public ushort DelayNum { get { return _delayNum; } }
/// <summary>
/// Frame delay fraction denominator
/// </summary>
public ushort DelayDen { get { return _delayDen; } }
/// <summary>
/// Type of frame area disposal to be done after rendering this frame
/// </summary>
public DisposeOpValues DisposeOp { get { return _disposeOp; } }
/// <summary>
/// Type of frame area rendering for this frame
/// </summary>
public BlendOpValues BlendOp { get { return _blendOp; } }
public Png M_Root { get { return m_root; } }
public Png.Chunk M_Parent { get { return m_parent; } }
}
/// <summary>
/// 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.
/// </summary>
/// <remarks>
/// Reference: <a href="https://www.w3.org/TR/png/#11iTXt">Source</a>
/// </remarks>
public partial class InternationalTextChunk : KaitaiStruct
{
public static InternationalTextChunk FromFile(string fileName)
{
return new InternationalTextChunk(new KaitaiStream(fileName));
}
public InternationalTextChunk(KaitaiStream p__io, Png.Chunk p__parent = null, Png p__root = null) : base(p__io)
{
m_parent = p__parent;
m_root = p__root;
_read();
}
private void _read()
{
_keyword = System.Text.Encoding.GetEncoding("UTF-8").GetString(m_io.ReadBytesTerm(0, false, true, true));
_compressionFlag = m_io.ReadU1();
_compressionMethod = ((Png.CompressionMethods) m_io.ReadU1());
_languageTag = System.Text.Encoding.GetEncoding("ASCII").GetString(m_io.ReadBytesTerm(0, false, true, true));
_translatedKeyword = System.Text.Encoding.GetEncoding("UTF-8").GetString(m_io.ReadBytesTerm(0, false, true, true));
_text = System.Text.Encoding.GetEncoding("UTF-8").GetString(m_io.ReadBytesFull());
}
private string _keyword;
private byte _compressionFlag;
private CompressionMethods _compressionMethod;
private string _languageTag;
private string _translatedKeyword;
private string _text;
private Png m_root;
private Png.Chunk m_parent;
/// <summary>
/// Indicates purpose of the following text data.
/// </summary>
public string Keyword { get { return _keyword; } }
/// <summary>
/// 0 = text is uncompressed, 1 = text is compressed with a
/// method specified in `compression_method`.
/// </summary>
public byte CompressionFlag { get { return _compressionFlag; } }
public CompressionMethods CompressionMethod { get { return _compressionMethod; } }
/// <summary>
/// Human language used in `translated_keyword` and `text`
/// attributes - should be a language code conforming to ISO
/// 646.IRV:1991.
/// </summary>
public string LanguageTag { get { return _languageTag; } }
/// <summary>
/// Keyword translated into language specified in
/// `language_tag`. Line breaks are not allowed.
/// </summary>
public string TranslatedKeyword { get { return _translatedKeyword; } }
/// <summary>
/// Text contents ("value" of this key-value pair), written in
/// language specified in `language_tag`. Line breaks are
/// allowed.
/// </summary>
public string Text { get { return _text; } }
public Png M_Root { get { return m_root; } }
public Png.Chunk M_Parent { get { return m_parent; } }
}
/// <summary>
/// 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.
/// </summary>
/// <remarks>
/// Reference: <a href="https://www.w3.org/TR/png/#11tEXt">Source</a>
/// </remarks>
public partial class TextChunk : KaitaiStruct
{
public static TextChunk FromFile(string fileName)
{
return new TextChunk(new KaitaiStream(fileName));
}
public TextChunk(KaitaiStream p__io, Png.Chunk p__parent = null, Png p__root = null) : base(p__io)
{
m_parent = p__parent;
m_root = p__root;
_read();
}
private void _read()
{
_keyword = System.Text.Encoding.GetEncoding("iso8859-1").GetString(m_io.ReadBytesTerm(0, false, true, true));
_text = System.Text.Encoding.GetEncoding("iso8859-1").GetString(m_io.ReadBytesFull());
}
private string _keyword;
private string _text;
private Png m_root;
private Png.Chunk m_parent;
/// <summary>
/// Indicates purpose of the following text data.
/// </summary>
public string Keyword { get { return _keyword; } }
public string Text { get { return _text; } }
public Png M_Root { get { return m_root; } }
public Png.Chunk M_Parent { get { return m_parent; } }
}
/// <remarks>
/// Reference: <a href="https://wiki.mozilla.org/APNG_Specification#.60acTL.60:_The_Animation_Control_Chunk">Source</a>
/// </remarks>
public partial class AnimationControlChunk : KaitaiStruct
{
public static AnimationControlChunk FromFile(string fileName)
{
return new AnimationControlChunk(new KaitaiStream(fileName));
}
public AnimationControlChunk(KaitaiStream p__io, Png.Chunk p__parent = null, Png p__root = null) : base(p__io)
{
m_parent = p__parent;
m_root = p__root;
_read();
}
private void _read()
{
_numFrames = m_io.ReadU4be();
_numPlays = m_io.ReadU4be();
}
private uint _numFrames;
private uint _numPlays;
private Png m_root;
private Png.Chunk m_parent;
/// <summary>
/// Number of frames, must be equal to the number of `frame_control_chunk`s
/// </summary>
public uint NumFrames { get { return _numFrames; } }
/// <summary>
/// Number of times to loop, 0 indicates infinite looping.
/// </summary>
public uint NumPlays { get { return _numPlays; } }
public Png M_Root { get { return m_root; } }
public Png.Chunk M_Parent { get { return m_parent; } }
}
/// <summary>
/// Time chunk stores time stamp of last modification of this image,
/// up to 1 second precision in UTC timezone.
/// </summary>
/// <remarks>
/// Reference: <a href="https://www.w3.org/TR/png/#11tIME">Source</a>
/// </remarks>
public partial class TimeChunk : KaitaiStruct
{
public static TimeChunk FromFile(string fileName)
{
return new TimeChunk(new KaitaiStream(fileName));
}
public TimeChunk(KaitaiStream p__io, Png.Chunk p__parent = null, Png p__root = null) : base(p__io)
{
m_parent = p__parent;
m_root = p__root;
_read();
}
private void _read()
{
_year = m_io.ReadU2be();
_month = m_io.ReadU1();
_day = m_io.ReadU1();
_hour = m_io.ReadU1();
_minute = m_io.ReadU1();
_second = m_io.ReadU1();
}
private ushort _year;
private byte _month;
private byte _day;
private byte _hour;
private byte _minute;
private byte _second;
private Png m_root;
private Png.Chunk m_parent;
public ushort Year { get { return _year; } }
public byte Month { get { return _month; } }
public byte Day { get { return _day; } }
public byte Hour { get { return _hour; } }
public byte Minute { get { return _minute; } }
public byte Second { get { return _second; } }
public Png M_Root { get { return m_root; } }
public Png.Chunk M_Parent { get { return m_parent; } }
}
private byte[] _magic;
private uint _ihdrLen;
private byte[] _ihdrType;
private IhdrChunk _ihdr;
private byte[] _ihdrCrc;
private List<Chunk> _chunks;
private Png m_root;
private KaitaiStruct m_parent;
public byte[] Magic { get { return _magic; } }
public uint IhdrLen { get { return _ihdrLen; } }
public byte[] IhdrType { get { return _ihdrType; } }
public IhdrChunk Ihdr { get { return _ihdr; } }
public byte[] IhdrCrc { get { return _ihdrCrc; } }
public List<Chunk> Chunks { get { return _chunks; } }
public Png M_Root { get { return m_root; } }
public KaitaiStruct M_Parent { get { return m_parent; } }
}
}