PNG (Portable Network Graphics) file: Python (read-write) parsing library

NOTICE: Many of the documentation comments (or docstrings) in this file were copied from or derived from the Portable Network Graphics (PNG) Specification (Third Edition). Copyright © 1996-2025 World Wide Web Consortium. https://www.w3.org/copyright/software-license-2023/

The full text of the license for the original W3C PNG specification is provided below:

Software and Document license - 2023 version

This work is being provided by the copyright holders under the following license.

License

By obtaining and/or copying this work, you (the licensee) agree that you have read, understood, and will comply with the following terms and conditions.

Permission to copy, modify, and distribute this work, with or without modification, for any purpose and without fee or royalty is hereby granted, provided that you include the following on ALL copies of the work or portions thereof, including modifications:

  • The full text of this NOTICE in a location viewable to users of the redistributed or derivative work.
  • Any pre-existing intellectual property disclaimers, notices, or terms and conditions. If none exist, the W3C software and document short notice should be included.
  • Notice of any changes or modifications, through a copyright statement on the new code or document such as "This software or document includes material copied from or derived from [title and URI of the W3C document]. Copyright © [$year-of-document] World Wide Web Consortium. https://www.w3.org/copyright/software-license-2023/"

Disclaimers

THIS WORK IS PROVIDED "AS IS," AND COPYRIGHT HOLDERS MAKE NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF THE SOFTWARE OR DOCUMENT WILL NOT INFRINGE ANY THIRD PARTY PATENTS, COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS.

COPYRIGHT HOLDERS WILL NOT BE LIABLE FOR ANY DIRECT, INDIRECT, SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF ANY USE OF THE SOFTWARE OR DOCUMENT.

The name and trademarks of copyright holders may NOT be used in advertising or publicity pertaining to the work without specific, written prior permission. Title to copyright in this work will at all times remain with copyright holders.


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.

Python (read-write) source code to parse PNG (Portable Network Graphics) file

png.py

# This is a generated file! Please edit source .ksy file and use kaitai-struct-compiler to rebuild
# type: ignore

import kaitaistruct
from kaitaistruct import ReadWriteKaitaiStruct, KaitaiStream, BytesIO
import exif
import icc_4
from enum import IntEnum
import zlib


if getattr(kaitaistruct, 'API_VERSION', (0, 9)) < (0, 11):
    raise Exception("Incompatible Kaitai Struct Python API: 0.11 or later is required, but you have %s" % (kaitaistruct.__version__))

class Png(ReadWriteKaitaiStruct):
    """NOTICE: Many of the documentation comments (or docstrings) in this file were
    copied from or derived from the [Portable Network Graphics (PNG) Specification
    (Third Edition)](https://www.w3.org/TR/2025/REC-png-3-20250624/).
    Copyright © 1996-2025 [World Wide Web Consortium](https://www.w3.org/).
    <https://www.w3.org/copyright/software-license-2023/>
    
    The full text of the license for the original W3C PNG specification is
    provided below:
    
    > ## Software and Document license - 2023 version
    >
    > This work is being provided by the copyright holders under the following
    > license.
    >
    > ### License
    >
    > By obtaining and/or copying this work, you (the licensee) agree that you
    > have read, understood, and will comply with the following terms and
    > conditions.
    >
    > Permission to copy, modify, and distribute this work, with or without
    > modification, for any purpose and without fee or royalty is hereby granted,
    > provided that you include the following on ALL copies of the work or
    > portions thereof, including modifications:
    >
    > * The full text of this NOTICE in a location viewable to users of the
    >   redistributed or derivative work.
    > * Any pre-existing intellectual property disclaimers, notices, or terms and
    >   conditions. If none exist, the [W3C software and document short
    >   notice](https://www.w3.org/Consortium/Legal/2023/copyright-software-short-notice.html)
    >   should be included.
    > * Notice of any changes or modifications, through a copyright statement on
    >   the new code or document such as "This software or document includes
    >   material copied from or derived from [title and URI of the W3C document].
    >   Copyright © [$year-of-document] [World Wide Web
    >   Consortium](https://www.w3.org/).
    >   <https://www.w3.org/copyright/software-license-2023/>"
    >
    > ### Disclaimers
    >
    > THIS WORK IS PROVIDED "AS IS," AND COPYRIGHT HOLDERS MAKE NO REPRESENTATIONS
    > OR WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO, WARRANTIES
    > OF MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF
    > THE SOFTWARE OR DOCUMENT WILL NOT INFRINGE ANY THIRD PARTY PATENTS,
    > COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS.
    >
    > COPYRIGHT HOLDERS WILL NOT BE LIABLE FOR ANY DIRECT, INDIRECT, SPECIAL OR
    > CONSEQUENTIAL DAMAGES ARISING OUT OF ANY USE OF THE SOFTWARE OR DOCUMENT.
    >
    > The name and trademarks of copyright holders may NOT be used in advertising
    > or publicity pertaining to the work without specific, written prior
    > permission. Title to copyright in this work will at all times remain with
    > copyright holders.
    
    ---
    
    Test files for APNG can be found at the following locations:
    
      * <https://philip.html5.org/tests/apng/tests.html>
      * <http://littlesvr.ca/apng/>
    """

    class BlendOpValues(IntEnum):
        source = 0
        over = 1

    class ColorType(IntEnum):
        greyscale = 0
        truecolor = 2
        indexed = 3
        greyscale_alpha = 4
        truecolor_alpha = 6

    class CompressionMethods(IntEnum):
        zlib = 0

    class DisposeOpValues(IntEnum):
        none = 0
        background = 1
        previous = 2

    class FilterMethod(IntEnum):
        base = 0

    class InterlaceMethod(IntEnum):
        none = 0
        adam7 = 1

    class PhysUnit(IntEnum):
        unknown = 0
        meter = 1
    def __init__(self, _io=None, _parent=None, _root=None):
        super(Png, self).__init__(_io)
        self._parent = _parent
        self._root = _root or self

    def _read(self):
        self.magic = self._io.read_bytes(8)
        if not self.magic == b"\x89\x50\x4E\x47\x0D\x0A\x1A\x0A":
            raise kaitaistruct.ValidationNotEqualError(b"\x89\x50\x4E\x47\x0D\x0A\x1A\x0A", self.magic, self._io, u"/seq/0")
        self.ihdr_len = self._io.read_u4be()
        if not self.ihdr_len == 13:
            raise kaitaistruct.ValidationNotEqualError(13, self.ihdr_len, self._io, u"/seq/1")
        self.ihdr_type = self._io.read_bytes(4)
        if not self.ihdr_type == b"\x49\x48\x44\x52":
            raise kaitaistruct.ValidationNotEqualError(b"\x49\x48\x44\x52", self.ihdr_type, self._io, u"/seq/2")
        self.ihdr = Png.IhdrChunk(self._io, self, self._root)
        self.ihdr._read()
        self.ihdr_crc = self._io.read_u4be()
        self.chunks = []
        i = 0
        while True:
            _t_chunks = Png.Chunk(self._io, self, self._root)
            try:
                _t_chunks._read()
            finally:
                _ = _t_chunks
                self.chunks.append(_)
            if  ((_.type == u"IEND") or (self._io.is_eof())) :
                break
            i += 1
        self._dirty = False


    def _fetch_instances(self):
        pass
        self.ihdr._fetch_instances()
        for i in range(len(self.chunks)):
            pass
            self.chunks[i]._fetch_instances()



    def _write__seq(self, io=None):
        super(Png, self)._write__seq(io)
        self._io.write_bytes(self.magic)
        self._io.write_u4be(self.ihdr_len)
        self._io.write_bytes(self.ihdr_type)
        self.ihdr._write__seq(self._io)
        self._io.write_u4be(self.ihdr_crc)
        for i in range(len(self.chunks)):
            pass
            self.chunks[i]._write__seq(self._io)
            _ = self.chunks[i]
            if  ((_.type == u"IEND") or (self._io.is_eof()))  != (i == len(self.chunks) - 1):
                raise kaitaistruct.ConsistencyError(u"chunks", i == len(self.chunks) - 1,  ((_.type == u"IEND") or (self._io.is_eof())) )



    def _check(self):
        if len(self.magic) != 8:
            raise kaitaistruct.ConsistencyError(u"magic", 8, len(self.magic))
        if not self.magic == b"\x89\x50\x4E\x47\x0D\x0A\x1A\x0A":
            raise kaitaistruct.ValidationNotEqualError(b"\x89\x50\x4E\x47\x0D\x0A\x1A\x0A", self.magic, None, u"/seq/0")
        if not self.ihdr_len == 13:
            raise kaitaistruct.ValidationNotEqualError(13, self.ihdr_len, None, u"/seq/1")
        if len(self.ihdr_type) != 4:
            raise kaitaistruct.ConsistencyError(u"ihdr_type", 4, len(self.ihdr_type))
        if not self.ihdr_type == b"\x49\x48\x44\x52":
            raise kaitaistruct.ValidationNotEqualError(b"\x49\x48\x44\x52", self.ihdr_type, None, u"/seq/2")
        if self.ihdr._root != self._root:
            raise kaitaistruct.ConsistencyError(u"ihdr", self._root, self.ihdr._root)
        if self.ihdr._parent != self:
            raise kaitaistruct.ConsistencyError(u"ihdr", self, self.ihdr._parent)
        if len(self.chunks) == 0:
            raise kaitaistruct.ConsistencyError(u"chunks", 0, len(self.chunks))
        for i in range(len(self.chunks)):
            pass
            if self.chunks[i]._root != self._root:
                raise kaitaistruct.ConsistencyError(u"chunks", self._root, self.chunks[i]._root)
            if self.chunks[i]._parent != self:
                raise kaitaistruct.ConsistencyError(u"chunks", self, self.chunks[i]._parent)

        self._dirty = False

    class AdobeFireworksChunk(ReadWriteKaitaiStruct):
        """
        .. seealso::
           Source - https://stackoverflow.com/questions/4242402/the-fireworks-png-format-any-insight-any-libs/51683285#51683285
        """
        def __init__(self, _io=None, _parent=None, _root=None):
            super(Png.AdobeFireworksChunk, self).__init__(_io)
            self._parent = _parent
            self._root = _root

        def _read(self):
            self._raw_preview_data = self._io.read_bytes_full()
            self.preview_data = zlib.decompress(self._raw_preview_data)
            self._dirty = False


        def _fetch_instances(self):
            pass


        def _write__seq(self, io=None):
            super(Png.AdobeFireworksChunk, self)._write__seq(io)
            self._raw_preview_data = zlib.compress(self.preview_data)
            self._io.write_bytes(self._raw_preview_data)
            if not self._io.is_eof():
                raise kaitaistruct.ConsistencyError(u"preview_data", 0, self._io.size() - self._io.pos())


        def _check(self):
            self._dirty = False


    class AnimationControlChunk(ReadWriteKaitaiStruct):
        """
        .. seealso::
           Source - https://www.w3.org/TR/png/#acTL-chunk
        """
        def __init__(self, _io=None, _parent=None, _root=None):
            super(Png.AnimationControlChunk, self).__init__(_io)
            self._parent = _parent
            self._root = _root

        def _read(self):
            self.num_frames = self._io.read_u4be()
            self.num_plays = self._io.read_u4be()
            self._dirty = False


        def _fetch_instances(self):
            pass


        def _write__seq(self, io=None):
            super(Png.AnimationControlChunk, self)._write__seq(io)
            self._io.write_u4be(self.num_frames)
            self._io.write_u4be(self.num_plays)


        def _check(self):
            self._dirty = False


    class AtchChunk(ReadWriteKaitaiStruct):
        """
        .. seealso::
           Source - https://github.com/skeeto/scratch/tree/58470254f4a95cdf7a53888e405c851c21eb2cae/pngattach
        
        
        .. seealso::
           A new protocol and tool for PNG file attachments - https://nullprogram.com/blog/2021/12/31/
        """

        class CompressionAttachMethods(IntEnum):
            none = 0
            zlib = 1
        def __init__(self, _io=None, _parent=None, _root=None):
            super(Png.AtchChunk, self).__init__(_io)
            self._parent = _parent
            self._root = _root

        def _read(self):
            self.file_name = (self._io.read_bytes_term(0, False, True, True)).decode(u"UTF-8")
            _ = self.file_name
            if not  ((len(_) != 0) and (_[0:1] != u".")) :
                raise kaitaistruct.ValidationExprError(self.file_name, self._io, u"/types/atch_chunk/seq/0")
            self.compression = KaitaiStream.resolve_enum(Png.AtchChunk.CompressionAttachMethods, self._io.read_u1())
            if not isinstance(self.compression, Png.AtchChunk.CompressionAttachMethods):
                raise kaitaistruct.ValidationNotInEnumError(self.compression, self._io, u"/types/atch_chunk/seq/1")
            if self.compression == Png.AtchChunk.CompressionAttachMethods.none:
                pass
                self.data_plain = self._io.read_bytes_full()

            if self.compression == Png.AtchChunk.CompressionAttachMethods.zlib:
                pass
                self._raw_data_zlib = self._io.read_bytes_full()
                self.data_zlib = zlib.decompress(self._raw_data_zlib)

            self._dirty = False


        def _fetch_instances(self):
            pass
            if self.compression == Png.AtchChunk.CompressionAttachMethods.none:
                pass

            if self.compression == Png.AtchChunk.CompressionAttachMethods.zlib:
                pass



        def _write__seq(self, io=None):
            super(Png.AtchChunk, self)._write__seq(io)
            self._io.write_bytes((self.file_name).encode(u"UTF-8"))
            self._io.write_u1(0)
            self._io.write_u1(int(self.compression))
            if self.compression == Png.AtchChunk.CompressionAttachMethods.none:
                pass
                self._io.write_bytes(self.data_plain)
                if not self._io.is_eof():
                    raise kaitaistruct.ConsistencyError(u"data_plain", 0, self._io.size() - self._io.pos())

            if self.compression == Png.AtchChunk.CompressionAttachMethods.zlib:
                pass
                self._raw_data_zlib = zlib.compress(self.data_zlib)
                self._io.write_bytes(self._raw_data_zlib)
                if not self._io.is_eof():
                    raise kaitaistruct.ConsistencyError(u"data_zlib", 0, self._io.size() - self._io.pos())



        def _check(self):
            if KaitaiStream.byte_array_index_of((self.file_name).encode(u"UTF-8"), 0) != -1:
                raise kaitaistruct.ConsistencyError(u"file_name", -1, KaitaiStream.byte_array_index_of((self.file_name).encode(u"UTF-8"), 0))
            _ = self.file_name
            if not  ((len(_) != 0) and (_[0:1] != u".")) :
                raise kaitaistruct.ValidationExprError(self.file_name, None, u"/types/atch_chunk/seq/0")
            if not isinstance(self.compression, Png.AtchChunk.CompressionAttachMethods):
                raise kaitaistruct.ValidationNotInEnumError(self.compression, None, u"/types/atch_chunk/seq/1")
            if self.compression == Png.AtchChunk.CompressionAttachMethods.none:
                pass

            if self.compression == Png.AtchChunk.CompressionAttachMethods.zlib:
                pass

            self._dirty = False

        @property
        def data(self):
            if hasattr(self, '_m_data'):
                return self._m_data

            self._m_data = (self.data_plain if self.compression == Png.AtchChunk.CompressionAttachMethods.none else self.data_zlib)
            return getattr(self, '_m_data', None)

        def _invalidate_data(self):
            del self._m_data

    class BkgdChunk(ReadWriteKaitaiStruct):
        """Background chunk stores default background color to display this
        image against. Contents depend on `color_type` of the image.
        
        .. seealso::
           Source - https://www.w3.org/TR/png/#11bKGD
        """
        def __init__(self, _io=None, _parent=None, _root=None):
            super(Png.BkgdChunk, self).__init__(_io)
            self._parent = _parent
            self._root = _root

        def _read(self):
            _on = self._root.ihdr.color_type
            if _on == Png.ColorType.greyscale:
                pass
                self.bkgd = Png.BkgdGreyscale(self._io, self, self._root)
                self.bkgd._read()
            elif _on == Png.ColorType.greyscale_alpha:
                pass
                self.bkgd = Png.BkgdGreyscale(self._io, self, self._root)
                self.bkgd._read()
            elif _on == Png.ColorType.indexed:
                pass
                self.bkgd = Png.BkgdIndexed(self._io, self, self._root)
                self.bkgd._read()
            elif _on == Png.ColorType.truecolor:
                pass
                self.bkgd = Png.BkgdTruecolor(self._io, self, self._root)
                self.bkgd._read()
            elif _on == Png.ColorType.truecolor_alpha:
                pass
                self.bkgd = Png.BkgdTruecolor(self._io, self, self._root)
                self.bkgd._read()
            self._dirty = False


        def _fetch_instances(self):
            pass
            _on = self._root.ihdr.color_type
            if _on == Png.ColorType.greyscale:
                pass
                self.bkgd._fetch_instances()
            elif _on == Png.ColorType.greyscale_alpha:
                pass
                self.bkgd._fetch_instances()
            elif _on == Png.ColorType.indexed:
                pass
                self.bkgd._fetch_instances()
            elif _on == Png.ColorType.truecolor:
                pass
                self.bkgd._fetch_instances()
            elif _on == Png.ColorType.truecolor_alpha:
                pass
                self.bkgd._fetch_instances()


        def _write__seq(self, io=None):
            super(Png.BkgdChunk, self)._write__seq(io)
            _on = self._root.ihdr.color_type
            if _on == Png.ColorType.greyscale:
                pass
                self.bkgd._write__seq(self._io)
            elif _on == Png.ColorType.greyscale_alpha:
                pass
                self.bkgd._write__seq(self._io)
            elif _on == Png.ColorType.indexed:
                pass
                self.bkgd._write__seq(self._io)
            elif _on == Png.ColorType.truecolor:
                pass
                self.bkgd._write__seq(self._io)
            elif _on == Png.ColorType.truecolor_alpha:
                pass
                self.bkgd._write__seq(self._io)


        def _check(self):
            _on = self._root.ihdr.color_type
            if _on == Png.ColorType.greyscale:
                pass
                if self.bkgd._root != self._root:
                    raise kaitaistruct.ConsistencyError(u"bkgd", self._root, self.bkgd._root)
                if self.bkgd._parent != self:
                    raise kaitaistruct.ConsistencyError(u"bkgd", self, self.bkgd._parent)
            elif _on == Png.ColorType.greyscale_alpha:
                pass
                if self.bkgd._root != self._root:
                    raise kaitaistruct.ConsistencyError(u"bkgd", self._root, self.bkgd._root)
                if self.bkgd._parent != self:
                    raise kaitaistruct.ConsistencyError(u"bkgd", self, self.bkgd._parent)
            elif _on == Png.ColorType.indexed:
                pass
                if self.bkgd._root != self._root:
                    raise kaitaistruct.ConsistencyError(u"bkgd", self._root, self.bkgd._root)
                if self.bkgd._parent != self:
                    raise kaitaistruct.ConsistencyError(u"bkgd", self, self.bkgd._parent)
            elif _on == Png.ColorType.truecolor:
                pass
                if self.bkgd._root != self._root:
                    raise kaitaistruct.ConsistencyError(u"bkgd", self._root, self.bkgd._root)
                if self.bkgd._parent != self:
                    raise kaitaistruct.ConsistencyError(u"bkgd", self, self.bkgd._parent)
            elif _on == Png.ColorType.truecolor_alpha:
                pass
                if self.bkgd._root != self._root:
                    raise kaitaistruct.ConsistencyError(u"bkgd", self._root, self.bkgd._root)
                if self.bkgd._parent != self:
                    raise kaitaistruct.ConsistencyError(u"bkgd", self, self.bkgd._parent)
            self._dirty = False


    class BkgdGreyscale(ReadWriteKaitaiStruct):
        """Background chunk for greyscale images."""
        def __init__(self, _io=None, _parent=None, _root=None):
            super(Png.BkgdGreyscale, self).__init__(_io)
            self._parent = _parent
            self._root = _root

        def _read(self):
            self.value = self._io.read_u2be()
            self._dirty = False


        def _fetch_instances(self):
            pass


        def _write__seq(self, io=None):
            super(Png.BkgdGreyscale, self)._write__seq(io)
            self._io.write_u2be(self.value)


        def _check(self):
            self._dirty = False


    class BkgdIndexed(ReadWriteKaitaiStruct):
        """Background chunk for images with indexed palette."""
        def __init__(self, _io=None, _parent=None, _root=None):
            super(Png.BkgdIndexed, self).__init__(_io)
            self._parent = _parent
            self._root = _root

        def _read(self):
            self.palette_index = self._io.read_u1()
            self._dirty = False


        def _fetch_instances(self):
            pass


        def _write__seq(self, io=None):
            super(Png.BkgdIndexed, self)._write__seq(io)
            self._io.write_u1(self.palette_index)


        def _check(self):
            self._dirty = False


    class BkgdTruecolor(ReadWriteKaitaiStruct):
        """Background chunk for truecolor images."""
        def __init__(self, _io=None, _parent=None, _root=None):
            super(Png.BkgdTruecolor, self).__init__(_io)
            self._parent = _parent
            self._root = _root

        def _read(self):
            self.red = self._io.read_u2be()
            self.green = self._io.read_u2be()
            self.blue = self._io.read_u2be()
            self._dirty = False


        def _fetch_instances(self):
            pass


        def _write__seq(self, io=None):
            super(Png.BkgdTruecolor, self)._write__seq(io)
            self._io.write_u2be(self.red)
            self._io.write_u2be(self.green)
            self._io.write_u2be(self.blue)


        def _check(self):
            self._dirty = False


    class ChrmChromaticity(ReadWriteKaitaiStruct):
        def __init__(self, _io=None, _parent=None, _root=None):
            super(Png.ChrmChromaticity, self).__init__(_io)
            self._parent = _parent
            self._root = _root

        def _read(self):
            self.x_int = self._io.read_u4be()
            self.y_int = self._io.read_u4be()
            self._dirty = False


        def _fetch_instances(self):
            pass


        def _write__seq(self, io=None):
            super(Png.ChrmChromaticity, self)._write__seq(io)
            self._io.write_u4be(self.x_int)
            self._io.write_u4be(self.y_int)


        def _check(self):
            self._dirty = False

        @property
        def x(self):
            if hasattr(self, '_m_x'):
                return self._m_x

            self._m_x = self.x_int / 100000.0
            return getattr(self, '_m_x', None)

        def _invalidate_x(self):
            del self._m_x
        @property
        def y(self):
            if hasattr(self, '_m_y'):
                return self._m_y

            self._m_y = self.y_int / 100000.0
            return getattr(self, '_m_y', None)

        def _invalidate_y(self):
            del self._m_y

    class ChrmChunk(ReadWriteKaitaiStruct):
        """
        .. seealso::
           Source - https://www.w3.org/TR/png/#11cHRM
        """
        def __init__(self, _io=None, _parent=None, _root=None):
            super(Png.ChrmChunk, self).__init__(_io)
            self._parent = _parent
            self._root = _root

        def _read(self):
            self.white_point = Png.ChrmChromaticity(self._io, self, self._root)
            self.white_point._read()
            self.red = Png.ChrmChromaticity(self._io, self, self._root)
            self.red._read()
            self.green = Png.ChrmChromaticity(self._io, self, self._root)
            self.green._read()
            self.blue = Png.ChrmChromaticity(self._io, self, self._root)
            self.blue._read()
            self._dirty = False


        def _fetch_instances(self):
            pass
            self.white_point._fetch_instances()
            self.red._fetch_instances()
            self.green._fetch_instances()
            self.blue._fetch_instances()


        def _write__seq(self, io=None):
            super(Png.ChrmChunk, self)._write__seq(io)
            self.white_point._write__seq(self._io)
            self.red._write__seq(self._io)
            self.green._write__seq(self._io)
            self.blue._write__seq(self._io)


        def _check(self):
            if self.white_point._root != self._root:
                raise kaitaistruct.ConsistencyError(u"white_point", self._root, self.white_point._root)
            if self.white_point._parent != self:
                raise kaitaistruct.ConsistencyError(u"white_point", self, self.white_point._parent)
            if self.red._root != self._root:
                raise kaitaistruct.ConsistencyError(u"red", self._root, self.red._root)
            if self.red._parent != self:
                raise kaitaistruct.ConsistencyError(u"red", self, self.red._parent)
            if self.green._root != self._root:
                raise kaitaistruct.ConsistencyError(u"green", self._root, self.green._root)
            if self.green._parent != self:
                raise kaitaistruct.ConsistencyError(u"green", self, self.green._parent)
            if self.blue._root != self._root:
                raise kaitaistruct.ConsistencyError(u"blue", self._root, self.blue._root)
            if self.blue._parent != self:
                raise kaitaistruct.ConsistencyError(u"blue", self, self.blue._parent)
            self._dirty = False


    class Chunk(ReadWriteKaitaiStruct):
        def __init__(self, _io=None, _parent=None, _root=None):
            super(Png.Chunk, self).__init__(_io)
            self._parent = _parent
            self._root = _root

        def _read(self):
            self.len = self._io.read_u4be()
            self.type_raw = self._io.read_bytes(4)
            _ = self.type_raw
            if not  (( (( ((KaitaiStream.byte_array_index(_, 0) >= 65) and (KaitaiStream.byte_array_index(_, 0) <= 90)) ) or ( ((KaitaiStream.byte_array_index(_, 0) >= 97) and (KaitaiStream.byte_array_index(_, 0) <= 122)) )) ) and ( (( ((KaitaiStream.byte_array_index(_, 1) >= 65) and (KaitaiStream.byte_array_index(_, 1) <= 90)) ) or ( ((KaitaiStream.byte_array_index(_, 1) >= 97) and (KaitaiStream.byte_array_index(_, 1) <= 122)) )) ) and ( (( ((KaitaiStream.byte_array_index(_, 2) >= 65) and (KaitaiStream.byte_array_index(_, 2) <= 90)) ) or ( ((KaitaiStream.byte_array_index(_, 2) >= 97) and (KaitaiStream.byte_array_index(_, 2) <= 122)) )) ) and ( (( ((KaitaiStream.byte_array_index(_, 3) >= 65) and (KaitaiStream.byte_array_index(_, 3) <= 90)) ) or ( ((KaitaiStream.byte_array_index(_, 3) >= 97) and (KaitaiStream.byte_array_index(_, 3) <= 122)) )) )) :
                raise kaitaistruct.ValidationExprError(self.type_raw, self._io, u"/types/chunk/seq/1")
            _on = self.type
            if _on == u"PLTE":
                pass
                self._raw_body = self._io.read_bytes(self.len)
                _io__raw_body = KaitaiStream(BytesIO(self._raw_body))
                self.body = Png.PlteChunk(_io__raw_body, self, self._root)
                self.body._read()
            elif _on == u"acTL":
                pass
                self._raw_body = self._io.read_bytes(self.len)
                _io__raw_body = KaitaiStream(BytesIO(self._raw_body))
                self.body = Png.AnimationControlChunk(_io__raw_body, self, self._root)
                self.body._read()
            elif _on == u"atCh":
                pass
                self._raw_body = self._io.read_bytes(self.len)
                _io__raw_body = KaitaiStream(BytesIO(self._raw_body))
                self.body = Png.AtchChunk(_io__raw_body, self, self._root)
                self.body._read()
            elif _on == u"bKGD":
                pass
                self._raw_body = self._io.read_bytes(self.len)
                _io__raw_body = KaitaiStream(BytesIO(self._raw_body))
                self.body = Png.BkgdChunk(_io__raw_body, self, self._root)
                self.body._read()
            elif _on == u"cHRM":
                pass
                self._raw_body = self._io.read_bytes(self.len)
                _io__raw_body = KaitaiStream(BytesIO(self._raw_body))
                self.body = Png.ChrmChunk(_io__raw_body, self, self._root)
                self.body._read()
            elif _on == u"cICP":
                pass
                self._raw_body = self._io.read_bytes(self.len)
                _io__raw_body = KaitaiStream(BytesIO(self._raw_body))
                self.body = Png.CicpChunk(_io__raw_body, self, self._root)
                self.body._read()
            elif _on == u"cLLI":
                pass
                self._raw_body = self._io.read_bytes(self.len)
                _io__raw_body = KaitaiStream(BytesIO(self._raw_body))
                self.body = Png.ClliChunk(_io__raw_body, self, self._root)
                self.body._read()
            elif _on == u"eXIf":
                pass
                self._raw_body = self._io.read_bytes(self.len)
                _io__raw_body = KaitaiStream(BytesIO(self._raw_body))
                self.body = Png.ExifChunk(_io__raw_body, self, self._root)
                self.body._read()
            elif _on == u"fcTL":
                pass
                self._raw_body = self._io.read_bytes(self.len)
                _io__raw_body = KaitaiStream(BytesIO(self._raw_body))
                self.body = Png.FrameControlChunk(_io__raw_body, self, self._root)
                self.body._read()
            elif _on == u"fdAT":
                pass
                self._raw_body = self._io.read_bytes(self.len)
                _io__raw_body = KaitaiStream(BytesIO(self._raw_body))
                self.body = Png.FrameDataChunk(_io__raw_body, self, self._root)
                self.body._read()
            elif _on == u"gAMA":
                pass
                self._raw_body = self._io.read_bytes(self.len)
                _io__raw_body = KaitaiStream(BytesIO(self._raw_body))
                self.body = Png.GamaChunk(_io__raw_body, self, self._root)
                self.body._read()
            elif _on == u"hIST":
                pass
                self._raw_body = self._io.read_bytes(self.len)
                _io__raw_body = KaitaiStream(BytesIO(self._raw_body))
                self.body = Png.HistChunk(_io__raw_body, self, self._root)
                self.body._read()
            elif _on == u"iCCP":
                pass
                self._raw_body = self._io.read_bytes(self.len)
                _io__raw_body = KaitaiStream(BytesIO(self._raw_body))
                self.body = Png.IccpChunk(_io__raw_body, self, self._root)
                self.body._read()
            elif _on == u"iTXt":
                pass
                self._raw_body = self._io.read_bytes(self.len)
                _io__raw_body = KaitaiStream(BytesIO(self._raw_body))
                self.body = Png.InternationalTextChunk(_io__raw_body, self, self._root)
                self.body._read()
            elif _on == u"mDCV":
                pass
                self._raw_body = self._io.read_bytes(self.len)
                _io__raw_body = KaitaiStream(BytesIO(self._raw_body))
                self.body = Png.MdcvChunk(_io__raw_body, self, self._root)
                self.body._read()
            elif _on == u"mkBS":
                pass
                self._raw_body = self._io.read_bytes(self.len)
                _io__raw_body = KaitaiStream(BytesIO(self._raw_body))
                self.body = Png.AdobeFireworksChunk(_io__raw_body, self, self._root)
                self.body._read()
            elif _on == u"mkTS":
                pass
                self._raw_body = self._io.read_bytes(self.len)
                _io__raw_body = KaitaiStream(BytesIO(self._raw_body))
                self.body = Png.AdobeFireworksChunk(_io__raw_body, self, self._root)
                self.body._read()
            elif _on == u"pHYs":
                pass
                self._raw_body = self._io.read_bytes(self.len)
                _io__raw_body = KaitaiStream(BytesIO(self._raw_body))
                self.body = Png.PhysChunk(_io__raw_body, self, self._root)
                self.body._read()
            elif _on == u"prVW":
                pass
                self._raw_body = self._io.read_bytes(self.len)
                _io__raw_body = KaitaiStream(BytesIO(self._raw_body))
                self.body = Png.AdobeFireworksChunk(_io__raw_body, self, self._root)
                self.body._read()
            elif _on == u"sBIT":
                pass
                self._raw_body = self._io.read_bytes(self.len)
                _io__raw_body = KaitaiStream(BytesIO(self._raw_body))
                self.body = Png.SbitChunk(_io__raw_body, self, self._root)
                self.body._read()
            elif _on == u"sPLT":
                pass
                self._raw_body = self._io.read_bytes(self.len)
                _io__raw_body = KaitaiStream(BytesIO(self._raw_body))
                self.body = Png.SpltChunk(_io__raw_body, self, self._root)
                self.body._read()
            elif _on == u"sRGB":
                pass
                self._raw_body = self._io.read_bytes(self.len)
                _io__raw_body = KaitaiStream(BytesIO(self._raw_body))
                self.body = Png.SrgbChunk(_io__raw_body, self, self._root)
                self.body._read()
            elif _on == u"skMf":
                pass
                self._raw_body = self._io.read_bytes(self.len)
                _io__raw_body = KaitaiStream(BytesIO(self._raw_body))
                self.body = Png.EvernoteSkmfChunk(_io__raw_body, self, self._root)
                self.body._read()
            elif _on == u"skRf":
                pass
                self._raw_body = self._io.read_bytes(self.len)
                _io__raw_body = KaitaiStream(BytesIO(self._raw_body))
                self.body = Png.EvernoteSkrfChunk(_io__raw_body, self, self._root)
                self.body._read()
            elif _on == u"tEXt":
                pass
                self._raw_body = self._io.read_bytes(self.len)
                _io__raw_body = KaitaiStream(BytesIO(self._raw_body))
                self.body = Png.TextChunk(_io__raw_body, self, self._root)
                self.body._read()
            elif _on == u"tIME":
                pass
                self._raw_body = self._io.read_bytes(self.len)
                _io__raw_body = KaitaiStream(BytesIO(self._raw_body))
                self.body = Png.TimeChunk(_io__raw_body, self, self._root)
                self.body._read()
            elif _on == u"tRNS":
                pass
                self._raw_body = self._io.read_bytes(self.len)
                _io__raw_body = KaitaiStream(BytesIO(self._raw_body))
                self.body = Png.TrnsChunk(_io__raw_body, self, self._root)
                self.body._read()
            elif _on == u"zTXt":
                pass
                self._raw_body = self._io.read_bytes(self.len)
                _io__raw_body = KaitaiStream(BytesIO(self._raw_body))
                self.body = Png.CompressedTextChunk(_io__raw_body, self, self._root)
                self.body._read()
            else:
                pass
                self.body = self._io.read_bytes(self.len)
            self.crc = self._io.read_u4be()
            self._dirty = False


        def _fetch_instances(self):
            pass
            _on = self.type
            if _on == u"PLTE":
                pass
                self.body._fetch_instances()
            elif _on == u"acTL":
                pass
                self.body._fetch_instances()
            elif _on == u"atCh":
                pass
                self.body._fetch_instances()
            elif _on == u"bKGD":
                pass
                self.body._fetch_instances()
            elif _on == u"cHRM":
                pass
                self.body._fetch_instances()
            elif _on == u"cICP":
                pass
                self.body._fetch_instances()
            elif _on == u"cLLI":
                pass
                self.body._fetch_instances()
            elif _on == u"eXIf":
                pass
                self.body._fetch_instances()
            elif _on == u"fcTL":
                pass
                self.body._fetch_instances()
            elif _on == u"fdAT":
                pass
                self.body._fetch_instances()
            elif _on == u"gAMA":
                pass
                self.body._fetch_instances()
            elif _on == u"hIST":
                pass
                self.body._fetch_instances()
            elif _on == u"iCCP":
                pass
                self.body._fetch_instances()
            elif _on == u"iTXt":
                pass
                self.body._fetch_instances()
            elif _on == u"mDCV":
                pass
                self.body._fetch_instances()
            elif _on == u"mkBS":
                pass
                self.body._fetch_instances()
            elif _on == u"mkTS":
                pass
                self.body._fetch_instances()
            elif _on == u"pHYs":
                pass
                self.body._fetch_instances()
            elif _on == u"prVW":
                pass
                self.body._fetch_instances()
            elif _on == u"sBIT":
                pass
                self.body._fetch_instances()
            elif _on == u"sPLT":
                pass
                self.body._fetch_instances()
            elif _on == u"sRGB":
                pass
                self.body._fetch_instances()
            elif _on == u"skMf":
                pass
                self.body._fetch_instances()
            elif _on == u"skRf":
                pass
                self.body._fetch_instances()
            elif _on == u"tEXt":
                pass
                self.body._fetch_instances()
            elif _on == u"tIME":
                pass
                self.body._fetch_instances()
            elif _on == u"tRNS":
                pass
                self.body._fetch_instances()
            elif _on == u"zTXt":
                pass
                self.body._fetch_instances()
            else:
                pass


        def _write__seq(self, io=None):
            super(Png.Chunk, self)._write__seq(io)
            self._io.write_u4be(self.len)
            self._io.write_bytes(self.type_raw)
            _on = self.type
            if _on == u"PLTE":
                pass
                _io__raw_body = KaitaiStream(BytesIO(bytearray(self.len)))
                self._io.add_child_stream(_io__raw_body)
                _pos2 = self._io.pos()
                self._io.seek(self._io.pos() + (self.len))
                def handler(parent, _io__raw_body=_io__raw_body):
                    self._raw_body = _io__raw_body.to_byte_array()
                    if len(self._raw_body) != self.len:
                        raise kaitaistruct.ConsistencyError(u"raw(body)", self.len, len(self._raw_body))
                    parent.write_bytes(self._raw_body)
                _io__raw_body.write_back_handler = KaitaiStream.WriteBackHandler(_pos2, handler)
                self.body._write__seq(_io__raw_body)
            elif _on == u"acTL":
                pass
                _io__raw_body = KaitaiStream(BytesIO(bytearray(self.len)))
                self._io.add_child_stream(_io__raw_body)
                _pos2 = self._io.pos()
                self._io.seek(self._io.pos() + (self.len))
                def handler(parent, _io__raw_body=_io__raw_body):
                    self._raw_body = _io__raw_body.to_byte_array()
                    if len(self._raw_body) != self.len:
                        raise kaitaistruct.ConsistencyError(u"raw(body)", self.len, len(self._raw_body))
                    parent.write_bytes(self._raw_body)
                _io__raw_body.write_back_handler = KaitaiStream.WriteBackHandler(_pos2, handler)
                self.body._write__seq(_io__raw_body)
            elif _on == u"atCh":
                pass
                _io__raw_body = KaitaiStream(BytesIO(bytearray(self.len)))
                self._io.add_child_stream(_io__raw_body)
                _pos2 = self._io.pos()
                self._io.seek(self._io.pos() + (self.len))
                def handler(parent, _io__raw_body=_io__raw_body):
                    self._raw_body = _io__raw_body.to_byte_array()
                    if len(self._raw_body) != self.len:
                        raise kaitaistruct.ConsistencyError(u"raw(body)", self.len, len(self._raw_body))
                    parent.write_bytes(self._raw_body)
                _io__raw_body.write_back_handler = KaitaiStream.WriteBackHandler(_pos2, handler)
                self.body._write__seq(_io__raw_body)
            elif _on == u"bKGD":
                pass
                _io__raw_body = KaitaiStream(BytesIO(bytearray(self.len)))
                self._io.add_child_stream(_io__raw_body)
                _pos2 = self._io.pos()
                self._io.seek(self._io.pos() + (self.len))
                def handler(parent, _io__raw_body=_io__raw_body):
                    self._raw_body = _io__raw_body.to_byte_array()
                    if len(self._raw_body) != self.len:
                        raise kaitaistruct.ConsistencyError(u"raw(body)", self.len, len(self._raw_body))
                    parent.write_bytes(self._raw_body)
                _io__raw_body.write_back_handler = KaitaiStream.WriteBackHandler(_pos2, handler)
                self.body._write__seq(_io__raw_body)
            elif _on == u"cHRM":
                pass
                _io__raw_body = KaitaiStream(BytesIO(bytearray(self.len)))
                self._io.add_child_stream(_io__raw_body)
                _pos2 = self._io.pos()
                self._io.seek(self._io.pos() + (self.len))
                def handler(parent, _io__raw_body=_io__raw_body):
                    self._raw_body = _io__raw_body.to_byte_array()
                    if len(self._raw_body) != self.len:
                        raise kaitaistruct.ConsistencyError(u"raw(body)", self.len, len(self._raw_body))
                    parent.write_bytes(self._raw_body)
                _io__raw_body.write_back_handler = KaitaiStream.WriteBackHandler(_pos2, handler)
                self.body._write__seq(_io__raw_body)
            elif _on == u"cICP":
                pass
                _io__raw_body = KaitaiStream(BytesIO(bytearray(self.len)))
                self._io.add_child_stream(_io__raw_body)
                _pos2 = self._io.pos()
                self._io.seek(self._io.pos() + (self.len))
                def handler(parent, _io__raw_body=_io__raw_body):
                    self._raw_body = _io__raw_body.to_byte_array()
                    if len(self._raw_body) != self.len:
                        raise kaitaistruct.ConsistencyError(u"raw(body)", self.len, len(self._raw_body))
                    parent.write_bytes(self._raw_body)
                _io__raw_body.write_back_handler = KaitaiStream.WriteBackHandler(_pos2, handler)
                self.body._write__seq(_io__raw_body)
            elif _on == u"cLLI":
                pass
                _io__raw_body = KaitaiStream(BytesIO(bytearray(self.len)))
                self._io.add_child_stream(_io__raw_body)
                _pos2 = self._io.pos()
                self._io.seek(self._io.pos() + (self.len))
                def handler(parent, _io__raw_body=_io__raw_body):
                    self._raw_body = _io__raw_body.to_byte_array()
                    if len(self._raw_body) != self.len:
                        raise kaitaistruct.ConsistencyError(u"raw(body)", self.len, len(self._raw_body))
                    parent.write_bytes(self._raw_body)
                _io__raw_body.write_back_handler = KaitaiStream.WriteBackHandler(_pos2, handler)
                self.body._write__seq(_io__raw_body)
            elif _on == u"eXIf":
                pass
                _io__raw_body = KaitaiStream(BytesIO(bytearray(self.len)))
                self._io.add_child_stream(_io__raw_body)
                _pos2 = self._io.pos()
                self._io.seek(self._io.pos() + (self.len))
                def handler(parent, _io__raw_body=_io__raw_body):
                    self._raw_body = _io__raw_body.to_byte_array()
                    if len(self._raw_body) != self.len:
                        raise kaitaistruct.ConsistencyError(u"raw(body)", self.len, len(self._raw_body))
                    parent.write_bytes(self._raw_body)
                _io__raw_body.write_back_handler = KaitaiStream.WriteBackHandler(_pos2, handler)
                self.body._write__seq(_io__raw_body)
            elif _on == u"fcTL":
                pass
                _io__raw_body = KaitaiStream(BytesIO(bytearray(self.len)))
                self._io.add_child_stream(_io__raw_body)
                _pos2 = self._io.pos()
                self._io.seek(self._io.pos() + (self.len))
                def handler(parent, _io__raw_body=_io__raw_body):
                    self._raw_body = _io__raw_body.to_byte_array()
                    if len(self._raw_body) != self.len:
                        raise kaitaistruct.ConsistencyError(u"raw(body)", self.len, len(self._raw_body))
                    parent.write_bytes(self._raw_body)
                _io__raw_body.write_back_handler = KaitaiStream.WriteBackHandler(_pos2, handler)
                self.body._write__seq(_io__raw_body)
            elif _on == u"fdAT":
                pass
                _io__raw_body = KaitaiStream(BytesIO(bytearray(self.len)))
                self._io.add_child_stream(_io__raw_body)
                _pos2 = self._io.pos()
                self._io.seek(self._io.pos() + (self.len))
                def handler(parent, _io__raw_body=_io__raw_body):
                    self._raw_body = _io__raw_body.to_byte_array()
                    if len(self._raw_body) != self.len:
                        raise kaitaistruct.ConsistencyError(u"raw(body)", self.len, len(self._raw_body))
                    parent.write_bytes(self._raw_body)
                _io__raw_body.write_back_handler = KaitaiStream.WriteBackHandler(_pos2, handler)
                self.body._write__seq(_io__raw_body)
            elif _on == u"gAMA":
                pass
                _io__raw_body = KaitaiStream(BytesIO(bytearray(self.len)))
                self._io.add_child_stream(_io__raw_body)
                _pos2 = self._io.pos()
                self._io.seek(self._io.pos() + (self.len))
                def handler(parent, _io__raw_body=_io__raw_body):
                    self._raw_body = _io__raw_body.to_byte_array()
                    if len(self._raw_body) != self.len:
                        raise kaitaistruct.ConsistencyError(u"raw(body)", self.len, len(self._raw_body))
                    parent.write_bytes(self._raw_body)
                _io__raw_body.write_back_handler = KaitaiStream.WriteBackHandler(_pos2, handler)
                self.body._write__seq(_io__raw_body)
            elif _on == u"hIST":
                pass
                _io__raw_body = KaitaiStream(BytesIO(bytearray(self.len)))
                self._io.add_child_stream(_io__raw_body)
                _pos2 = self._io.pos()
                self._io.seek(self._io.pos() + (self.len))
                def handler(parent, _io__raw_body=_io__raw_body):
                    self._raw_body = _io__raw_body.to_byte_array()
                    if len(self._raw_body) != self.len:
                        raise kaitaistruct.ConsistencyError(u"raw(body)", self.len, len(self._raw_body))
                    parent.write_bytes(self._raw_body)
                _io__raw_body.write_back_handler = KaitaiStream.WriteBackHandler(_pos2, handler)
                self.body._write__seq(_io__raw_body)
            elif _on == u"iCCP":
                pass
                _io__raw_body = KaitaiStream(BytesIO(bytearray(self.len)))
                self._io.add_child_stream(_io__raw_body)
                _pos2 = self._io.pos()
                self._io.seek(self._io.pos() + (self.len))
                def handler(parent, _io__raw_body=_io__raw_body):
                    self._raw_body = _io__raw_body.to_byte_array()
                    if len(self._raw_body) != self.len:
                        raise kaitaistruct.ConsistencyError(u"raw(body)", self.len, len(self._raw_body))
                    parent.write_bytes(self._raw_body)
                _io__raw_body.write_back_handler = KaitaiStream.WriteBackHandler(_pos2, handler)
                self.body._write__seq(_io__raw_body)
            elif _on == u"iTXt":
                pass
                _io__raw_body = KaitaiStream(BytesIO(bytearray(self.len)))
                self._io.add_child_stream(_io__raw_body)
                _pos2 = self._io.pos()
                self._io.seek(self._io.pos() + (self.len))
                def handler(parent, _io__raw_body=_io__raw_body):
                    self._raw_body = _io__raw_body.to_byte_array()
                    if len(self._raw_body) != self.len:
                        raise kaitaistruct.ConsistencyError(u"raw(body)", self.len, len(self._raw_body))
                    parent.write_bytes(self._raw_body)
                _io__raw_body.write_back_handler = KaitaiStream.WriteBackHandler(_pos2, handler)
                self.body._write__seq(_io__raw_body)
            elif _on == u"mDCV":
                pass
                _io__raw_body = KaitaiStream(BytesIO(bytearray(self.len)))
                self._io.add_child_stream(_io__raw_body)
                _pos2 = self._io.pos()
                self._io.seek(self._io.pos() + (self.len))
                def handler(parent, _io__raw_body=_io__raw_body):
                    self._raw_body = _io__raw_body.to_byte_array()
                    if len(self._raw_body) != self.len:
                        raise kaitaistruct.ConsistencyError(u"raw(body)", self.len, len(self._raw_body))
                    parent.write_bytes(self._raw_body)
                _io__raw_body.write_back_handler = KaitaiStream.WriteBackHandler(_pos2, handler)
                self.body._write__seq(_io__raw_body)
            elif _on == u"mkBS":
                pass
                _io__raw_body = KaitaiStream(BytesIO(bytearray(self.len)))
                self._io.add_child_stream(_io__raw_body)
                _pos2 = self._io.pos()
                self._io.seek(self._io.pos() + (self.len))
                def handler(parent, _io__raw_body=_io__raw_body):
                    self._raw_body = _io__raw_body.to_byte_array()
                    if len(self._raw_body) != self.len:
                        raise kaitaistruct.ConsistencyError(u"raw(body)", self.len, len(self._raw_body))
                    parent.write_bytes(self._raw_body)
                _io__raw_body.write_back_handler = KaitaiStream.WriteBackHandler(_pos2, handler)
                self.body._write__seq(_io__raw_body)
            elif _on == u"mkTS":
                pass
                _io__raw_body = KaitaiStream(BytesIO(bytearray(self.len)))
                self._io.add_child_stream(_io__raw_body)
                _pos2 = self._io.pos()
                self._io.seek(self._io.pos() + (self.len))
                def handler(parent, _io__raw_body=_io__raw_body):
                    self._raw_body = _io__raw_body.to_byte_array()
                    if len(self._raw_body) != self.len:
                        raise kaitaistruct.ConsistencyError(u"raw(body)", self.len, len(self._raw_body))
                    parent.write_bytes(self._raw_body)
                _io__raw_body.write_back_handler = KaitaiStream.WriteBackHandler(_pos2, handler)
                self.body._write__seq(_io__raw_body)
            elif _on == u"pHYs":
                pass
                _io__raw_body = KaitaiStream(BytesIO(bytearray(self.len)))
                self._io.add_child_stream(_io__raw_body)
                _pos2 = self._io.pos()
                self._io.seek(self._io.pos() + (self.len))
                def handler(parent, _io__raw_body=_io__raw_body):
                    self._raw_body = _io__raw_body.to_byte_array()
                    if len(self._raw_body) != self.len:
                        raise kaitaistruct.ConsistencyError(u"raw(body)", self.len, len(self._raw_body))
                    parent.write_bytes(self._raw_body)
                _io__raw_body.write_back_handler = KaitaiStream.WriteBackHandler(_pos2, handler)
                self.body._write__seq(_io__raw_body)
            elif _on == u"prVW":
                pass
                _io__raw_body = KaitaiStream(BytesIO(bytearray(self.len)))
                self._io.add_child_stream(_io__raw_body)
                _pos2 = self._io.pos()
                self._io.seek(self._io.pos() + (self.len))
                def handler(parent, _io__raw_body=_io__raw_body):
                    self._raw_body = _io__raw_body.to_byte_array()
                    if len(self._raw_body) != self.len:
                        raise kaitaistruct.ConsistencyError(u"raw(body)", self.len, len(self._raw_body))
                    parent.write_bytes(self._raw_body)
                _io__raw_body.write_back_handler = KaitaiStream.WriteBackHandler(_pos2, handler)
                self.body._write__seq(_io__raw_body)
            elif _on == u"sBIT":
                pass
                _io__raw_body = KaitaiStream(BytesIO(bytearray(self.len)))
                self._io.add_child_stream(_io__raw_body)
                _pos2 = self._io.pos()
                self._io.seek(self._io.pos() + (self.len))
                def handler(parent, _io__raw_body=_io__raw_body):
                    self._raw_body = _io__raw_body.to_byte_array()
                    if len(self._raw_body) != self.len:
                        raise kaitaistruct.ConsistencyError(u"raw(body)", self.len, len(self._raw_body))
                    parent.write_bytes(self._raw_body)
                _io__raw_body.write_back_handler = KaitaiStream.WriteBackHandler(_pos2, handler)
                self.body._write__seq(_io__raw_body)
            elif _on == u"sPLT":
                pass
                _io__raw_body = KaitaiStream(BytesIO(bytearray(self.len)))
                self._io.add_child_stream(_io__raw_body)
                _pos2 = self._io.pos()
                self._io.seek(self._io.pos() + (self.len))
                def handler(parent, _io__raw_body=_io__raw_body):
                    self._raw_body = _io__raw_body.to_byte_array()
                    if len(self._raw_body) != self.len:
                        raise kaitaistruct.ConsistencyError(u"raw(body)", self.len, len(self._raw_body))
                    parent.write_bytes(self._raw_body)
                _io__raw_body.write_back_handler = KaitaiStream.WriteBackHandler(_pos2, handler)
                self.body._write__seq(_io__raw_body)
            elif _on == u"sRGB":
                pass
                _io__raw_body = KaitaiStream(BytesIO(bytearray(self.len)))
                self._io.add_child_stream(_io__raw_body)
                _pos2 = self._io.pos()
                self._io.seek(self._io.pos() + (self.len))
                def handler(parent, _io__raw_body=_io__raw_body):
                    self._raw_body = _io__raw_body.to_byte_array()
                    if len(self._raw_body) != self.len:
                        raise kaitaistruct.ConsistencyError(u"raw(body)", self.len, len(self._raw_body))
                    parent.write_bytes(self._raw_body)
                _io__raw_body.write_back_handler = KaitaiStream.WriteBackHandler(_pos2, handler)
                self.body._write__seq(_io__raw_body)
            elif _on == u"skMf":
                pass
                _io__raw_body = KaitaiStream(BytesIO(bytearray(self.len)))
                self._io.add_child_stream(_io__raw_body)
                _pos2 = self._io.pos()
                self._io.seek(self._io.pos() + (self.len))
                def handler(parent, _io__raw_body=_io__raw_body):
                    self._raw_body = _io__raw_body.to_byte_array()
                    if len(self._raw_body) != self.len:
                        raise kaitaistruct.ConsistencyError(u"raw(body)", self.len, len(self._raw_body))
                    parent.write_bytes(self._raw_body)
                _io__raw_body.write_back_handler = KaitaiStream.WriteBackHandler(_pos2, handler)
                self.body._write__seq(_io__raw_body)
            elif _on == u"skRf":
                pass
                _io__raw_body = KaitaiStream(BytesIO(bytearray(self.len)))
                self._io.add_child_stream(_io__raw_body)
                _pos2 = self._io.pos()
                self._io.seek(self._io.pos() + (self.len))
                def handler(parent, _io__raw_body=_io__raw_body):
                    self._raw_body = _io__raw_body.to_byte_array()
                    if len(self._raw_body) != self.len:
                        raise kaitaistruct.ConsistencyError(u"raw(body)", self.len, len(self._raw_body))
                    parent.write_bytes(self._raw_body)
                _io__raw_body.write_back_handler = KaitaiStream.WriteBackHandler(_pos2, handler)
                self.body._write__seq(_io__raw_body)
            elif _on == u"tEXt":
                pass
                _io__raw_body = KaitaiStream(BytesIO(bytearray(self.len)))
                self._io.add_child_stream(_io__raw_body)
                _pos2 = self._io.pos()
                self._io.seek(self._io.pos() + (self.len))
                def handler(parent, _io__raw_body=_io__raw_body):
                    self._raw_body = _io__raw_body.to_byte_array()
                    if len(self._raw_body) != self.len:
                        raise kaitaistruct.ConsistencyError(u"raw(body)", self.len, len(self._raw_body))
                    parent.write_bytes(self._raw_body)
                _io__raw_body.write_back_handler = KaitaiStream.WriteBackHandler(_pos2, handler)
                self.body._write__seq(_io__raw_body)
            elif _on == u"tIME":
                pass
                _io__raw_body = KaitaiStream(BytesIO(bytearray(self.len)))
                self._io.add_child_stream(_io__raw_body)
                _pos2 = self._io.pos()
                self._io.seek(self._io.pos() + (self.len))
                def handler(parent, _io__raw_body=_io__raw_body):
                    self._raw_body = _io__raw_body.to_byte_array()
                    if len(self._raw_body) != self.len:
                        raise kaitaistruct.ConsistencyError(u"raw(body)", self.len, len(self._raw_body))
                    parent.write_bytes(self._raw_body)
                _io__raw_body.write_back_handler = KaitaiStream.WriteBackHandler(_pos2, handler)
                self.body._write__seq(_io__raw_body)
            elif _on == u"tRNS":
                pass
                _io__raw_body = KaitaiStream(BytesIO(bytearray(self.len)))
                self._io.add_child_stream(_io__raw_body)
                _pos2 = self._io.pos()
                self._io.seek(self._io.pos() + (self.len))
                def handler(parent, _io__raw_body=_io__raw_body):
                    self._raw_body = _io__raw_body.to_byte_array()
                    if len(self._raw_body) != self.len:
                        raise kaitaistruct.ConsistencyError(u"raw(body)", self.len, len(self._raw_body))
                    parent.write_bytes(self._raw_body)
                _io__raw_body.write_back_handler = KaitaiStream.WriteBackHandler(_pos2, handler)
                self.body._write__seq(_io__raw_body)
            elif _on == u"zTXt":
                pass
                _io__raw_body = KaitaiStream(BytesIO(bytearray(self.len)))
                self._io.add_child_stream(_io__raw_body)
                _pos2 = self._io.pos()
                self._io.seek(self._io.pos() + (self.len))
                def handler(parent, _io__raw_body=_io__raw_body):
                    self._raw_body = _io__raw_body.to_byte_array()
                    if len(self._raw_body) != self.len:
                        raise kaitaistruct.ConsistencyError(u"raw(body)", self.len, len(self._raw_body))
                    parent.write_bytes(self._raw_body)
                _io__raw_body.write_back_handler = KaitaiStream.WriteBackHandler(_pos2, handler)
                self.body._write__seq(_io__raw_body)
            else:
                pass
                self._io.write_bytes(self.body)
            self._io.write_u4be(self.crc)


        def _check(self):
            if len(self.type_raw) != 4:
                raise kaitaistruct.ConsistencyError(u"type_raw", 4, len(self.type_raw))
            _ = self.type_raw
            if not  (( (( ((KaitaiStream.byte_array_index(_, 0) >= 65) and (KaitaiStream.byte_array_index(_, 0) <= 90)) ) or ( ((KaitaiStream.byte_array_index(_, 0) >= 97) and (KaitaiStream.byte_array_index(_, 0) <= 122)) )) ) and ( (( ((KaitaiStream.byte_array_index(_, 1) >= 65) and (KaitaiStream.byte_array_index(_, 1) <= 90)) ) or ( ((KaitaiStream.byte_array_index(_, 1) >= 97) and (KaitaiStream.byte_array_index(_, 1) <= 122)) )) ) and ( (( ((KaitaiStream.byte_array_index(_, 2) >= 65) and (KaitaiStream.byte_array_index(_, 2) <= 90)) ) or ( ((KaitaiStream.byte_array_index(_, 2) >= 97) and (KaitaiStream.byte_array_index(_, 2) <= 122)) )) ) and ( (( ((KaitaiStream.byte_array_index(_, 3) >= 65) and (KaitaiStream.byte_array_index(_, 3) <= 90)) ) or ( ((KaitaiStream.byte_array_index(_, 3) >= 97) and (KaitaiStream.byte_array_index(_, 3) <= 122)) )) )) :
                raise kaitaistruct.ValidationExprError(self.type_raw, None, u"/types/chunk/seq/1")
            _on = self.type
            if _on == u"PLTE":
                pass
                if self.body._root != self._root:
                    raise kaitaistruct.ConsistencyError(u"body", self._root, self.body._root)
                if self.body._parent != self:
                    raise kaitaistruct.ConsistencyError(u"body", self, self.body._parent)
            elif _on == u"acTL":
                pass
                if self.body._root != self._root:
                    raise kaitaistruct.ConsistencyError(u"body", self._root, self.body._root)
                if self.body._parent != self:
                    raise kaitaistruct.ConsistencyError(u"body", self, self.body._parent)
            elif _on == u"atCh":
                pass
                if self.body._root != self._root:
                    raise kaitaistruct.ConsistencyError(u"body", self._root, self.body._root)
                if self.body._parent != self:
                    raise kaitaistruct.ConsistencyError(u"body", self, self.body._parent)
            elif _on == u"bKGD":
                pass
                if self.body._root != self._root:
                    raise kaitaistruct.ConsistencyError(u"body", self._root, self.body._root)
                if self.body._parent != self:
                    raise kaitaistruct.ConsistencyError(u"body", self, self.body._parent)
            elif _on == u"cHRM":
                pass
                if self.body._root != self._root:
                    raise kaitaistruct.ConsistencyError(u"body", self._root, self.body._root)
                if self.body._parent != self:
                    raise kaitaistruct.ConsistencyError(u"body", self, self.body._parent)
            elif _on == u"cICP":
                pass
                if self.body._root != self._root:
                    raise kaitaistruct.ConsistencyError(u"body", self._root, self.body._root)
                if self.body._parent != self:
                    raise kaitaistruct.ConsistencyError(u"body", self, self.body._parent)
            elif _on == u"cLLI":
                pass
                if self.body._root != self._root:
                    raise kaitaistruct.ConsistencyError(u"body", self._root, self.body._root)
                if self.body._parent != self:
                    raise kaitaistruct.ConsistencyError(u"body", self, self.body._parent)
            elif _on == u"eXIf":
                pass
                if self.body._root != self._root:
                    raise kaitaistruct.ConsistencyError(u"body", self._root, self.body._root)
                if self.body._parent != self:
                    raise kaitaistruct.ConsistencyError(u"body", self, self.body._parent)
            elif _on == u"fcTL":
                pass
                if self.body._root != self._root:
                    raise kaitaistruct.ConsistencyError(u"body", self._root, self.body._root)
                if self.body._parent != self:
                    raise kaitaistruct.ConsistencyError(u"body", self, self.body._parent)
            elif _on == u"fdAT":
                pass
                if self.body._root != self._root:
                    raise kaitaistruct.ConsistencyError(u"body", self._root, self.body._root)
                if self.body._parent != self:
                    raise kaitaistruct.ConsistencyError(u"body", self, self.body._parent)
            elif _on == u"gAMA":
                pass
                if self.body._root != self._root:
                    raise kaitaistruct.ConsistencyError(u"body", self._root, self.body._root)
                if self.body._parent != self:
                    raise kaitaistruct.ConsistencyError(u"body", self, self.body._parent)
            elif _on == u"hIST":
                pass
                if self.body._root != self._root:
                    raise kaitaistruct.ConsistencyError(u"body", self._root, self.body._root)
                if self.body._parent != self:
                    raise kaitaistruct.ConsistencyError(u"body", self, self.body._parent)
            elif _on == u"iCCP":
                pass
                if self.body._root != self._root:
                    raise kaitaistruct.ConsistencyError(u"body", self._root, self.body._root)
                if self.body._parent != self:
                    raise kaitaistruct.ConsistencyError(u"body", self, self.body._parent)
            elif _on == u"iTXt":
                pass
                if self.body._root != self._root:
                    raise kaitaistruct.ConsistencyError(u"body", self._root, self.body._root)
                if self.body._parent != self:
                    raise kaitaistruct.ConsistencyError(u"body", self, self.body._parent)
            elif _on == u"mDCV":
                pass
                if self.body._root != self._root:
                    raise kaitaistruct.ConsistencyError(u"body", self._root, self.body._root)
                if self.body._parent != self:
                    raise kaitaistruct.ConsistencyError(u"body", self, self.body._parent)
            elif _on == u"mkBS":
                pass
                if self.body._root != self._root:
                    raise kaitaistruct.ConsistencyError(u"body", self._root, self.body._root)
                if self.body._parent != self:
                    raise kaitaistruct.ConsistencyError(u"body", self, self.body._parent)
            elif _on == u"mkTS":
                pass
                if self.body._root != self._root:
                    raise kaitaistruct.ConsistencyError(u"body", self._root, self.body._root)
                if self.body._parent != self:
                    raise kaitaistruct.ConsistencyError(u"body", self, self.body._parent)
            elif _on == u"pHYs":
                pass
                if self.body._root != self._root:
                    raise kaitaistruct.ConsistencyError(u"body", self._root, self.body._root)
                if self.body._parent != self:
                    raise kaitaistruct.ConsistencyError(u"body", self, self.body._parent)
            elif _on == u"prVW":
                pass
                if self.body._root != self._root:
                    raise kaitaistruct.ConsistencyError(u"body", self._root, self.body._root)
                if self.body._parent != self:
                    raise kaitaistruct.ConsistencyError(u"body", self, self.body._parent)
            elif _on == u"sBIT":
                pass
                if self.body._root != self._root:
                    raise kaitaistruct.ConsistencyError(u"body", self._root, self.body._root)
                if self.body._parent != self:
                    raise kaitaistruct.ConsistencyError(u"body", self, self.body._parent)
            elif _on == u"sPLT":
                pass
                if self.body._root != self._root:
                    raise kaitaistruct.ConsistencyError(u"body", self._root, self.body._root)
                if self.body._parent != self:
                    raise kaitaistruct.ConsistencyError(u"body", self, self.body._parent)
            elif _on == u"sRGB":
                pass
                if self.body._root != self._root:
                    raise kaitaistruct.ConsistencyError(u"body", self._root, self.body._root)
                if self.body._parent != self:
                    raise kaitaistruct.ConsistencyError(u"body", self, self.body._parent)
            elif _on == u"skMf":
                pass
                if self.body._root != self._root:
                    raise kaitaistruct.ConsistencyError(u"body", self._root, self.body._root)
                if self.body._parent != self:
                    raise kaitaistruct.ConsistencyError(u"body", self, self.body._parent)
            elif _on == u"skRf":
                pass
                if self.body._root != self._root:
                    raise kaitaistruct.ConsistencyError(u"body", self._root, self.body._root)
                if self.body._parent != self:
                    raise kaitaistruct.ConsistencyError(u"body", self, self.body._parent)
            elif _on == u"tEXt":
                pass
                if self.body._root != self._root:
                    raise kaitaistruct.ConsistencyError(u"body", self._root, self.body._root)
                if self.body._parent != self:
                    raise kaitaistruct.ConsistencyError(u"body", self, self.body._parent)
            elif _on == u"tIME":
                pass
                if self.body._root != self._root:
                    raise kaitaistruct.ConsistencyError(u"body", self._root, self.body._root)
                if self.body._parent != self:
                    raise kaitaistruct.ConsistencyError(u"body", self, self.body._parent)
            elif _on == u"tRNS":
                pass
                if self.body._root != self._root:
                    raise kaitaistruct.ConsistencyError(u"body", self._root, self.body._root)
                if self.body._parent != self:
                    raise kaitaistruct.ConsistencyError(u"body", self, self.body._parent)
            elif _on == u"zTXt":
                pass
                if self.body._root != self._root:
                    raise kaitaistruct.ConsistencyError(u"body", self._root, self.body._root)
                if self.body._parent != self:
                    raise kaitaistruct.ConsistencyError(u"body", self, self.body._parent)
            else:
                pass
                if len(self.body) != self.len:
                    raise kaitaistruct.ConsistencyError(u"body", self.len, len(self.body))
            self._dirty = False

        @property
        def is_ancillary(self):
            """false = critical chunk, true = ancillary chunk
            """
            if hasattr(self, '_m_is_ancillary'):
                return self._m_is_ancillary

            self._m_is_ancillary = KaitaiStream.byte_array_index(self.type_raw, 0) & 32 != 0
            return getattr(self, '_m_is_ancillary', None)

        def _invalidate_is_ancillary(self):
            del self._m_is_ancillary
        @property
        def is_private(self):
            """false = public chunk (defined by the W3C), true = private chunk (can
            be defined by anyone)
            """
            if hasattr(self, '_m_is_private'):
                return self._m_is_private

            self._m_is_private = KaitaiStream.byte_array_index(self.type_raw, 1) & 32 != 0
            return getattr(self, '_m_is_private', None)

        def _invalidate_is_private(self):
            del self._m_is_private
        @property
        def is_safe_to_copy(self):
            """Defines whether the chunk may be copied if the image data (i.e.
            pixels) is modified. This tells PNG editors how to handle unknown
            chunks - see section [14.2 Behavior of PNG
            editors](https://www.w3.org/TR/2025/REC-png-3-20250624/#14Ordering) in
            the official specification.
            """
            if hasattr(self, '_m_is_safe_to_copy'):
                return self._m_is_safe_to_copy

            self._m_is_safe_to_copy = KaitaiStream.byte_array_index(self.type_raw, 3) & 32 != 0
            return getattr(self, '_m_is_safe_to_copy', None)

        def _invalidate_is_safe_to_copy(self):
            del self._m_is_safe_to_copy
        @property
        def reserved_bit(self):
            """Should be `false`, i.e. all chunk types should have uppercase third
            letters (the lowercase third letter is reserved for possible future
            extensions to the PNG standard)
            """
            if hasattr(self, '_m_reserved_bit'):
                return self._m_reserved_bit

            self._m_reserved_bit = KaitaiStream.byte_array_index(self.type_raw, 2) & 32 != 0
            return getattr(self, '_m_reserved_bit', None)

        def _invalidate_reserved_bit(self):
            del self._m_reserved_bit
        @property
        def type(self):
            if hasattr(self, '_m_type'):
                return self._m_type

            self._m_type = (self.type_raw).decode(u"ASCII")
            return getattr(self, '_m_type', None)

        def _invalidate_type(self):
            del self._m_type

    class CicpChunk(ReadWriteKaitaiStruct):
        """
        .. seealso::
           Source - https://www.w3.org/TR/png/#cICP-chunk
        
        
        .. seealso::
           Source - https://w3c.github.io/png/Implementation_Report_3e/#cicp
        """
        def __init__(self, _io=None, _parent=None, _root=None):
            super(Png.CicpChunk, self).__init__(_io)
            self._parent = _parent
            self._root = _root

        def _read(self):
            self.color_primaries = self._io.read_u1()
            self.transfer_function = self._io.read_u1()
            self.matrix_coefficients = self._io.read_u1()
            if not self.matrix_coefficients == 0:
                raise kaitaistruct.ValidationNotEqualError(0, self.matrix_coefficients, self._io, u"/types/cicp_chunk/seq/2")
            self.video_full_range_flag = self._io.read_u1()
            if not  ((self.video_full_range_flag == 0) or (self.video_full_range_flag == 1)) :
                raise kaitaistruct.ValidationNotAnyOfError(self.video_full_range_flag, self._io, u"/types/cicp_chunk/seq/3")
            self._dirty = False


        def _fetch_instances(self):
            pass


        def _write__seq(self, io=None):
            super(Png.CicpChunk, self)._write__seq(io)
            self._io.write_u1(self.color_primaries)
            self._io.write_u1(self.transfer_function)
            self._io.write_u1(self.matrix_coefficients)
            self._io.write_u1(self.video_full_range_flag)


        def _check(self):
            if not self.matrix_coefficients == 0:
                raise kaitaistruct.ValidationNotEqualError(0, self.matrix_coefficients, None, u"/types/cicp_chunk/seq/2")
            if not  ((self.video_full_range_flag == 0) or (self.video_full_range_flag == 1)) :
                raise kaitaistruct.ValidationNotAnyOfError(self.video_full_range_flag, None, u"/types/cicp_chunk/seq/3")
            self._dirty = False


    class ClliChunk(ReadWriteKaitaiStruct):
        """
        .. seealso::
           Source - https://www.w3.org/TR/png/#cLLI-chunk
        
        
        .. seealso::
           Source - https://w3c.github.io/png/Implementation_Report_3e/#light
        """
        def __init__(self, _io=None, _parent=None, _root=None):
            super(Png.ClliChunk, self).__init__(_io)
            self._parent = _parent
            self._root = _root

        def _read(self):
            self.max_content_light_level_int = self._io.read_u4be()
            self.max_frame_average_light_level_int = self._io.read_u4be()
            self._dirty = False


        def _fetch_instances(self):
            pass


        def _write__seq(self, io=None):
            super(Png.ClliChunk, self)._write__seq(io)
            self._io.write_u4be(self.max_content_light_level_int)
            self._io.write_u4be(self.max_frame_average_light_level_int)


        def _check(self):
            self._dirty = False

        @property
        def max_content_light_level(self):
            """Maximum Content Light Level (MaxCLL), in cd/m^2."""
            if hasattr(self, '_m_max_content_light_level'):
                return self._m_max_content_light_level

            self._m_max_content_light_level = self.max_content_light_level_int * 0.0001
            return getattr(self, '_m_max_content_light_level', None)

        def _invalidate_max_content_light_level(self):
            del self._m_max_content_light_level
        @property
        def max_frame_average_light_level(self):
            """Maximum Frame Average Light Level (MaxFALL), in cd/m^2."""
            if hasattr(self, '_m_max_frame_average_light_level'):
                return self._m_max_frame_average_light_level

            self._m_max_frame_average_light_level = self.max_frame_average_light_level_int * 0.0001
            return getattr(self, '_m_max_frame_average_light_level', None)

        def _invalidate_max_frame_average_light_level(self):
            del self._m_max_frame_average_light_level

    class CompressedText(ReadWriteKaitaiStruct):
        def __init__(self, _io=None, _parent=None, _root=None):
            super(Png.CompressedText, self).__init__(_io)
            self._parent = _parent
            self._root = _root

        def _read(self):
            self.value = (self._io.read_bytes_full()).decode(u"ISO-8859-1")
            self._dirty = False


        def _fetch_instances(self):
            pass


        def _write__seq(self, io=None):
            super(Png.CompressedText, self)._write__seq(io)
            self._io.write_bytes((self.value).encode(u"ISO-8859-1"))
            if not self._io.is_eof():
                raise kaitaistruct.ConsistencyError(u"value", 0, self._io.size() - self._io.pos())


        def _check(self):
            self._dirty = False


    class CompressedTextChunk(ReadWriteKaitaiStruct):
        """Compressed textual data (`zTXt`) chunk effectively allows you to store
        key-value string pairs in the PNG container, compressing the "value" part
        (which can be quite lengthy) with zlib compression.
        
        The `zTXt` and `tEXt` chunks are semantically equivalent, but the `zTXt`
        chunk is recommended for storing large blocks of text.
        
        .. seealso::
           Source - https://www.w3.org/TR/png/#11zTXt
        """
        def __init__(self, _io=None, _parent=None, _root=None):
            super(Png.CompressedTextChunk, self).__init__(_io)
            self._parent = _parent
            self._root = _root

        def _read(self):
            self.keyword = (self._io.read_bytes_term(0, False, True, True)).decode(u"ISO-8859-1")
            self.compression_method = KaitaiStream.resolve_enum(Png.CompressionMethods, self._io.read_u1())
            if not self.compression_method == Png.CompressionMethods.zlib:
                raise kaitaistruct.ValidationNotEqualError(Png.CompressionMethods.zlib, self.compression_method, self._io, u"/types/compressed_text_chunk/seq/1")
            self._raw__raw_text = self._io.read_bytes_full()
            self._raw_text = zlib.decompress(self._raw__raw_text)
            self.text__inner_size = len(self._raw_text)
            _io__raw_text = KaitaiStream(BytesIO(self._raw_text))
            self.text = Png.CompressedText(_io__raw_text, self, self._root)
            self.text._read()
            self._dirty = False


        def _fetch_instances(self):
            pass
            self.text._fetch_instances()


        def _write__seq(self, io=None):
            super(Png.CompressedTextChunk, self)._write__seq(io)
            self._io.write_bytes((self.keyword).encode(u"ISO-8859-1"))
            self._io.write_u1(0)
            self._io.write_u1(int(self.compression_method))
            _io__raw_text = KaitaiStream(BytesIO(bytearray(self.text__inner_size)))
            self._io.add_child_stream(_io__raw_text)
            _pos2 = self._io.pos()
            self._io.seek(self._io.pos() + (self._io.size() - self._io.pos()))
            def handler(parent, _io__raw_text=_io__raw_text):
                self._raw_text = _io__raw_text.to_byte_array()
                self._raw__raw_text = zlib.compress(self._raw_text)
                parent.write_bytes(self._raw__raw_text)
                if not parent.is_eof():
                    raise kaitaistruct.ConsistencyError(u"raw(text)", 0, parent.size() - parent.pos())
            _io__raw_text.write_back_handler = KaitaiStream.WriteBackHandler(_pos2, handler)
            self.text._write__seq(_io__raw_text)


        def _check(self):
            if KaitaiStream.byte_array_index_of((self.keyword).encode(u"ISO-8859-1"), 0) != -1:
                raise kaitaistruct.ConsistencyError(u"keyword", -1, KaitaiStream.byte_array_index_of((self.keyword).encode(u"ISO-8859-1"), 0))
            if not self.compression_method == Png.CompressionMethods.zlib:
                raise kaitaistruct.ValidationNotEqualError(Png.CompressionMethods.zlib, self.compression_method, None, u"/types/compressed_text_chunk/seq/1")
            if self.text._root != self._root:
                raise kaitaistruct.ConsistencyError(u"text", self._root, self.text._root)
            if self.text._parent != self:
                raise kaitaistruct.ConsistencyError(u"text", self, self.text._parent)
            self._dirty = False


    class EvernoteSkmfChunk(ReadWriteKaitaiStruct):
        """
        .. seealso::
           Source - https://web.archive.org/web/20210302212148/https://discussion.evernote.com/forums/topic/88532-how-to-extract-annotation-information-from-annotated-evernoteskitch-images/#comment-451501
        """
        def __init__(self, _io=None, _parent=None, _root=None):
            super(Png.EvernoteSkmfChunk, self).__init__(_io)
            self._parent = _parent
            self._root = _root

        def _read(self):
            self.json = (self._io.read_bytes_full()).decode(u"UTF-8")
            self._dirty = False


        def _fetch_instances(self):
            pass


        def _write__seq(self, io=None):
            super(Png.EvernoteSkmfChunk, self)._write__seq(io)
            self._io.write_bytes((self.json).encode(u"UTF-8"))
            if not self._io.is_eof():
                raise kaitaistruct.ConsistencyError(u"json", 0, self._io.size() - self._io.pos())


        def _check(self):
            self._dirty = False


    class EvernoteSkrfChunk(ReadWriteKaitaiStruct):
        """
        .. seealso::
           Source - https://web.archive.org/web/20210302212148/https://discussion.evernote.com/forums/topic/88532-how-to-extract-annotation-information-from-annotated-evernoteskitch-images/#comment-451501
        """
        def __init__(self, _io=None, _parent=None, _root=None):
            super(Png.EvernoteSkrfChunk, self).__init__(_io)
            self._parent = _parent
            self._root = _root

        def _read(self):
            self.uuid = self._io.read_bytes(16)
            self.orig_img = self._io.read_bytes_full()
            self._dirty = False


        def _fetch_instances(self):
            pass


        def _write__seq(self, io=None):
            super(Png.EvernoteSkrfChunk, self)._write__seq(io)
            self._io.write_bytes(self.uuid)
            self._io.write_bytes(self.orig_img)
            if not self._io.is_eof():
                raise kaitaistruct.ConsistencyError(u"orig_img", 0, self._io.size() - self._io.pos())


        def _check(self):
            if len(self.uuid) != 16:
                raise kaitaistruct.ConsistencyError(u"uuid", 16, len(self.uuid))
            self._dirty = False


    class ExifChunk(ReadWriteKaitaiStruct):
        """Exchangeable Image File (Exif) Profile (`eXIf`) chunk.
        
        Only one `eXIf` chunk is allowed in a PNG datastream.
        
        The `eXIf` chunk contains metadata concerning the original image data. If
        the image has been edited subsequent to creation of the Exif profile, this
        data might no longer apply to the PNG image data.
        
        .. seealso::
           Source - https://www.w3.org/TR/png/#eXIf
        """
        def __init__(self, _io=None, _parent=None, _root=None):
            super(Png.ExifChunk, self).__init__(_io)
            self._parent = _parent
            self._root = _root

        def _read(self):
            self.exif = exif.Exif(self._io)
            self.exif._read()
            self._dirty = False


        def _fetch_instances(self):
            pass
            self.exif._fetch_instances()


        def _write__seq(self, io=None):
            super(Png.ExifChunk, self)._write__seq(io)
            self.exif._write__seq(self._io)


        def _check(self):
            self._dirty = False


    class FrameControlChunk(ReadWriteKaitaiStruct):
        """
        .. seealso::
           Source - https://www.w3.org/TR/png/#fcTL-chunk
        """
        def __init__(self, _io=None, _parent=None, _root=None):
            super(Png.FrameControlChunk, self).__init__(_io)
            self._parent = _parent
            self._root = _root

        def _read(self):
            self.sequence_number = self._io.read_u4be()
            self.width = self._io.read_u4be()
            if not self.width >= 1:
                raise kaitaistruct.ValidationLessThanError(1, self.width, self._io, u"/types/frame_control_chunk/seq/1")
            if not self.width <= self._root.ihdr.width:
                raise kaitaistruct.ValidationGreaterThanError(self._root.ihdr.width, self.width, self._io, u"/types/frame_control_chunk/seq/1")
            self.height = self._io.read_u4be()
            if not self.height >= 1:
                raise kaitaistruct.ValidationLessThanError(1, self.height, self._io, u"/types/frame_control_chunk/seq/2")
            if not self.height <= self._root.ihdr.height:
                raise kaitaistruct.ValidationGreaterThanError(self._root.ihdr.height, self.height, self._io, u"/types/frame_control_chunk/seq/2")
            self.x_offset = self._io.read_u4be()
            if not self.x_offset <= self._root.ihdr.width - self.width:
                raise kaitaistruct.ValidationGreaterThanError(self._root.ihdr.width - self.width, self.x_offset, self._io, u"/types/frame_control_chunk/seq/3")
            self.y_offset = self._io.read_u4be()
            if not self.y_offset <= self._root.ihdr.height - self.height:
                raise kaitaistruct.ValidationGreaterThanError(self._root.ihdr.height - self.height, self.y_offset, self._io, u"/types/frame_control_chunk/seq/4")
            self.delay_num = self._io.read_u2be()
            self.delay_den = self._io.read_u2be()
            self.dispose_op = KaitaiStream.resolve_enum(Png.DisposeOpValues, self._io.read_u1())
            if not isinstance(self.dispose_op, Png.DisposeOpValues):
                raise kaitaistruct.ValidationNotInEnumError(self.dispose_op, self._io, u"/types/frame_control_chunk/seq/7")
            self.blend_op = KaitaiStream.resolve_enum(Png.BlendOpValues, self._io.read_u1())
            if not isinstance(self.blend_op, Png.BlendOpValues):
                raise kaitaistruct.ValidationNotInEnumError(self.blend_op, self._io, u"/types/frame_control_chunk/seq/8")
            self._dirty = False


        def _fetch_instances(self):
            pass


        def _write__seq(self, io=None):
            super(Png.FrameControlChunk, self)._write__seq(io)
            self._io.write_u4be(self.sequence_number)
            self._io.write_u4be(self.width)
            self._io.write_u4be(self.height)
            self._io.write_u4be(self.x_offset)
            self._io.write_u4be(self.y_offset)
            self._io.write_u2be(self.delay_num)
            self._io.write_u2be(self.delay_den)
            self._io.write_u1(int(self.dispose_op))
            self._io.write_u1(int(self.blend_op))


        def _check(self):
            if not self.width >= 1:
                raise kaitaistruct.ValidationLessThanError(1, self.width, None, u"/types/frame_control_chunk/seq/1")
            if not self.width <= self._root.ihdr.width:
                raise kaitaistruct.ValidationGreaterThanError(self._root.ihdr.width, self.width, None, u"/types/frame_control_chunk/seq/1")
            if not self.height >= 1:
                raise kaitaistruct.ValidationLessThanError(1, self.height, None, u"/types/frame_control_chunk/seq/2")
            if not self.height <= self._root.ihdr.height:
                raise kaitaistruct.ValidationGreaterThanError(self._root.ihdr.height, self.height, None, u"/types/frame_control_chunk/seq/2")
            if not self.x_offset <= self._root.ihdr.width - self.width:
                raise kaitaistruct.ValidationGreaterThanError(self._root.ihdr.width - self.width, self.x_offset, None, u"/types/frame_control_chunk/seq/3")
            if not self.y_offset <= self._root.ihdr.height - self.height:
                raise kaitaistruct.ValidationGreaterThanError(self._root.ihdr.height - self.height, self.y_offset, None, u"/types/frame_control_chunk/seq/4")
            if not isinstance(self.dispose_op, Png.DisposeOpValues):
                raise kaitaistruct.ValidationNotInEnumError(self.dispose_op, None, u"/types/frame_control_chunk/seq/7")
            if not isinstance(self.blend_op, Png.BlendOpValues):
                raise kaitaistruct.ValidationNotInEnumError(self.blend_op, None, u"/types/frame_control_chunk/seq/8")
            self._dirty = False

        @property
        def delay(self):
            """Time to display this frame, in seconds."""
            if hasattr(self, '_m_delay'):
                return self._m_delay

            self._m_delay = self.delay_num / (100.0 if self.delay_den == 0 else self.delay_den)
            return getattr(self, '_m_delay', None)

        def _invalidate_delay(self):
            del self._m_delay

    class FrameDataChunk(ReadWriteKaitaiStruct):
        """
        .. seealso::
           Source - https://www.w3.org/TR/png/#fdAT-chunk
        """
        def __init__(self, _io=None, _parent=None, _root=None):
            super(Png.FrameDataChunk, self).__init__(_io)
            self._parent = _parent
            self._root = _root

        def _read(self):
            self.sequence_number = self._io.read_u4be()
            self.frame_data = self._io.read_bytes_full()
            self._dirty = False


        def _fetch_instances(self):
            pass


        def _write__seq(self, io=None):
            super(Png.FrameDataChunk, self)._write__seq(io)
            self._io.write_u4be(self.sequence_number)
            self._io.write_bytes(self.frame_data)
            if not self._io.is_eof():
                raise kaitaistruct.ConsistencyError(u"frame_data", 0, self._io.size() - self._io.pos())


        def _check(self):
            self._dirty = False


    class GamaChunk(ReadWriteKaitaiStruct):
        """
        .. seealso::
           Source - https://www.w3.org/TR/png/#11gAMA
        """
        def __init__(self, _io=None, _parent=None, _root=None):
            super(Png.GamaChunk, self).__init__(_io)
            self._parent = _parent
            self._root = _root

        def _read(self):
            self.gamma_int = self._io.read_u4be()
            _ = self.gamma_int
            if not _ != 0:
                raise kaitaistruct.ValidationExprError(self.gamma_int, self._io, u"/types/gama_chunk/seq/0")
            self._dirty = False


        def _fetch_instances(self):
            pass


        def _write__seq(self, io=None):
            super(Png.GamaChunk, self)._write__seq(io)
            self._io.write_u4be(self.gamma_int)


        def _check(self):
            _ = self.gamma_int
            if not _ != 0:
                raise kaitaistruct.ValidationExprError(self.gamma_int, None, u"/types/gama_chunk/seq/0")
            self._dirty = False

        @property
        def gamma(self):
            """Image gamma, typically 0.45455 = 1/2.2."""
            if hasattr(self, '_m_gamma'):
                return self._m_gamma

            self._m_gamma = self.gamma_int / 100000.0
            return getattr(self, '_m_gamma', None)

        def _invalidate_gamma(self):
            del self._m_gamma
        @property
        def inv_gamma(self):
            """Inverse of the image gamma (1 / gamma), typically 2.2 (not considering
            rounding)
            """
            if hasattr(self, '_m_inv_gamma'):
                return self._m_inv_gamma

            self._m_inv_gamma = 100000.0 / self.gamma_int
            return getattr(self, '_m_inv_gamma', None)

        def _invalidate_inv_gamma(self):
            del self._m_inv_gamma

    class HistChunk(ReadWriteKaitaiStruct):
        """Image histogram (`hIST`) chunk gives the approximate usage frequency of
        each color in the palette. A histogram chunk can appear only when a `PLTE`
        chunk appears.
        
        .. seealso::
           Source - https://www.w3.org/TR/png/#11hIST
        """
        def __init__(self, _io=None, _parent=None, _root=None):
            super(Png.HistChunk, self).__init__(_io)
            self._parent = _parent
            self._root = _root

        def _read(self):
            self.usage_freqs = []
            i = 0
            while not self._io.is_eof():
                self.usage_freqs.append(self._io.read_u2be())
                i += 1

            self._dirty = False


        def _fetch_instances(self):
            pass
            for i in range(len(self.usage_freqs)):
                pass



        def _write__seq(self, io=None):
            super(Png.HistChunk, self)._write__seq(io)
            for i in range(len(self.usage_freqs)):
                pass
                if self._io.is_eof():
                    raise kaitaistruct.ConsistencyError(u"usage_freqs", 0, self._io.size() - self._io.pos())
                self._io.write_u2be(self.usage_freqs[i])

            if not self._io.is_eof():
                raise kaitaistruct.ConsistencyError(u"usage_freqs", 0, self._io.size() - self._io.pos())


        def _check(self):
            for i in range(len(self.usage_freqs)):
                pass

            self._dirty = False


    class IccpChunk(ReadWriteKaitaiStruct):
        """Embedded ICC profile (`iCCP`) chunk.
        
        If the `iCCP` chunk is present, the image samples conform to the color
        space represented by the embedded ICC profile as defined by the
        International Color Consortium.
        
        This chunk is ignored unless it is the [highest-precedence color
        chunk](https://www.w3.org/TR/png/#color-chunk-precendence) understood by
        the decoder. Unless a `cICP` chunk exists, a PNG datastream should contain
        at most one embedded profile, whether specified explicitly with an `iCCP`
        or implicitly with an `sRGB` chunk.
        
        It is recommended that the `sRGB` and `iCCP` chunks do not appear
        simultaneously in a PNG datastream.
        
        .. seealso::
           Source - https://www.w3.org/TR/png/#11iCCP
        """
        def __init__(self, _io=None, _parent=None, _root=None):
            super(Png.IccpChunk, self).__init__(_io)
            self._parent = _parent
            self._root = _root

        def _read(self):
            self.profile_name = (self._io.read_bytes_term(0, False, True, True)).decode(u"ISO-8859-1")
            self.compression_method = KaitaiStream.resolve_enum(Png.CompressionMethods, self._io.read_u1())
            if not self.compression_method == Png.CompressionMethods.zlib:
                raise kaitaistruct.ValidationNotEqualError(Png.CompressionMethods.zlib, self.compression_method, self._io, u"/types/iccp_chunk/seq/1")
            self._raw__raw_profile = self._io.read_bytes_full()
            self._raw_profile = zlib.decompress(self._raw__raw_profile)
            self.profile__inner_size = len(self._raw_profile)
            _io__raw_profile = KaitaiStream(BytesIO(self._raw_profile))
            self.profile = icc_4.Icc4(_io__raw_profile)
            self.profile._read()
            self._dirty = False


        def _fetch_instances(self):
            pass
            self.profile._fetch_instances()


        def _write__seq(self, io=None):
            super(Png.IccpChunk, self)._write__seq(io)
            self._io.write_bytes((self.profile_name).encode(u"ISO-8859-1"))
            self._io.write_u1(0)
            self._io.write_u1(int(self.compression_method))
            _io__raw_profile = KaitaiStream(BytesIO(bytearray(self.profile__inner_size)))
            self._io.add_child_stream(_io__raw_profile)
            _pos2 = self._io.pos()
            self._io.seek(self._io.pos() + (self._io.size() - self._io.pos()))
            def handler(parent, _io__raw_profile=_io__raw_profile):
                self._raw_profile = _io__raw_profile.to_byte_array()
                self._raw__raw_profile = zlib.compress(self._raw_profile)
                parent.write_bytes(self._raw__raw_profile)
                if not parent.is_eof():
                    raise kaitaistruct.ConsistencyError(u"raw(profile)", 0, parent.size() - parent.pos())
            _io__raw_profile.write_back_handler = KaitaiStream.WriteBackHandler(_pos2, handler)
            self.profile._write__seq(_io__raw_profile)


        def _check(self):
            if KaitaiStream.byte_array_index_of((self.profile_name).encode(u"ISO-8859-1"), 0) != -1:
                raise kaitaistruct.ConsistencyError(u"profile_name", -1, KaitaiStream.byte_array_index_of((self.profile_name).encode(u"ISO-8859-1"), 0))
            if not self.compression_method == Png.CompressionMethods.zlib:
                raise kaitaistruct.ValidationNotEqualError(Png.CompressionMethods.zlib, self.compression_method, None, u"/types/iccp_chunk/seq/1")
            self._dirty = False


    class IhdrChunk(ReadWriteKaitaiStruct):
        """
        .. seealso::
           Source - https://www.w3.org/TR/png/#11IHDR
        """
        def __init__(self, _io=None, _parent=None, _root=None):
            super(Png.IhdrChunk, self).__init__(_io)
            self._parent = _parent
            self._root = _root

        def _read(self):
            self.width = self._io.read_u4be()
            if not self.width >= 1:
                raise kaitaistruct.ValidationLessThanError(1, self.width, self._io, u"/types/ihdr_chunk/seq/0")
            self.height = self._io.read_u4be()
            if not self.height >= 1:
                raise kaitaistruct.ValidationLessThanError(1, self.height, self._io, u"/types/ihdr_chunk/seq/1")
            self.bit_depth = self._io.read_u1()
            if not  ((self.bit_depth == 1) or (self.bit_depth == 2) or (self.bit_depth == 4) or (self.bit_depth == 8) or (self.bit_depth == 16)) :
                raise kaitaistruct.ValidationNotAnyOfError(self.bit_depth, self._io, u"/types/ihdr_chunk/seq/2")
            self.color_type = KaitaiStream.resolve_enum(Png.ColorType, self._io.read_u1())
            if not isinstance(self.color_type, Png.ColorType):
                raise kaitaistruct.ValidationNotInEnumError(self.color_type, self._io, u"/types/ihdr_chunk/seq/3")
            self.compression_method = KaitaiStream.resolve_enum(Png.CompressionMethods, self._io.read_u1())
            if not isinstance(self.compression_method, Png.CompressionMethods):
                raise kaitaistruct.ValidationNotInEnumError(self.compression_method, self._io, u"/types/ihdr_chunk/seq/4")
            self.filter_method = KaitaiStream.resolve_enum(Png.FilterMethod, self._io.read_u1())
            if not isinstance(self.filter_method, Png.FilterMethod):
                raise kaitaistruct.ValidationNotInEnumError(self.filter_method, self._io, u"/types/ihdr_chunk/seq/5")
            self.interlace_method = KaitaiStream.resolve_enum(Png.InterlaceMethod, self._io.read_u1())
            if not isinstance(self.interlace_method, Png.InterlaceMethod):
                raise kaitaistruct.ValidationNotInEnumError(self.interlace_method, self._io, u"/types/ihdr_chunk/seq/6")
            self._dirty = False


        def _fetch_instances(self):
            pass


        def _write__seq(self, io=None):
            super(Png.IhdrChunk, self)._write__seq(io)
            self._io.write_u4be(self.width)
            self._io.write_u4be(self.height)
            self._io.write_u1(self.bit_depth)
            self._io.write_u1(int(self.color_type))
            self._io.write_u1(int(self.compression_method))
            self._io.write_u1(int(self.filter_method))
            self._io.write_u1(int(self.interlace_method))


        def _check(self):
            if not self.width >= 1:
                raise kaitaistruct.ValidationLessThanError(1, self.width, None, u"/types/ihdr_chunk/seq/0")
            if not self.height >= 1:
                raise kaitaistruct.ValidationLessThanError(1, self.height, None, u"/types/ihdr_chunk/seq/1")
            if not  ((self.bit_depth == 1) or (self.bit_depth == 2) or (self.bit_depth == 4) or (self.bit_depth == 8) or (self.bit_depth == 16)) :
                raise kaitaistruct.ValidationNotAnyOfError(self.bit_depth, None, u"/types/ihdr_chunk/seq/2")
            if not isinstance(self.color_type, Png.ColorType):
                raise kaitaistruct.ValidationNotInEnumError(self.color_type, None, u"/types/ihdr_chunk/seq/3")
            if not isinstance(self.compression_method, Png.CompressionMethods):
                raise kaitaistruct.ValidationNotInEnumError(self.compression_method, None, u"/types/ihdr_chunk/seq/4")
            if not isinstance(self.filter_method, Png.FilterMethod):
                raise kaitaistruct.ValidationNotInEnumError(self.filter_method, None, u"/types/ihdr_chunk/seq/5")
            if not isinstance(self.interlace_method, Png.InterlaceMethod):
                raise kaitaistruct.ValidationNotInEnumError(self.interlace_method, None, u"/types/ihdr_chunk/seq/6")
            self._dirty = False


    class InternationalText(ReadWriteKaitaiStruct):
        def __init__(self, _io=None, _parent=None, _root=None):
            super(Png.InternationalText, self).__init__(_io)
            self._parent = _parent
            self._root = _root

        def _read(self):
            self.value = (self._io.read_bytes_full()).decode(u"UTF-8")
            self._dirty = False


        def _fetch_instances(self):
            pass


        def _write__seq(self, io=None):
            super(Png.InternationalText, self)._write__seq(io)
            self._io.write_bytes((self.value).encode(u"UTF-8"))
            if not self._io.is_eof():
                raise kaitaistruct.ConsistencyError(u"value", 0, self._io.size() - self._io.pos())


        def _check(self):
            self._dirty = False


    class InternationalTextChunk(ReadWriteKaitaiStruct):
        """International textual data (`iTXt`) chunk effectively allows you to store
        key-value string pairs in the PNG container.
        
        The "key" part (`keyword`) is restricted to printable ISO-8859-1 (Latin-1)
        characters and spaces. The translated keyword and the "value" part
        (`text`) are stored in UTF-8 and thus can store text in any language -
        this language can be indicated via the language tag (`language_tag`).
        
        .. seealso::
           Source - https://www.w3.org/TR/png/#11iTXt
        """
        def __init__(self, _io=None, _parent=None, _root=None):
            super(Png.InternationalTextChunk, self).__init__(_io)
            self._parent = _parent
            self._root = _root

        def _read(self):
            self.keyword = (self._io.read_bytes_term(0, False, True, True)).decode(u"ISO-8859-1")
            self.compression_flag = self._io.read_u1()
            if not  ((self.compression_flag == 0) or (self.compression_flag == 1)) :
                raise kaitaistruct.ValidationNotAnyOfError(self.compression_flag, self._io, u"/types/international_text_chunk/seq/1")
            self.compression_method = KaitaiStream.resolve_enum(Png.CompressionMethods, self._io.read_u1())
            if not self.compression_method == (Png.CompressionMethods.zlib if self.compression_flag == 1 else self.compression_method):
                raise kaitaistruct.ValidationNotEqualError((Png.CompressionMethods.zlib if self.compression_flag == 1 else self.compression_method), self.compression_method, self._io, u"/types/international_text_chunk/seq/2")
            self.language_tag = (self._io.read_bytes_term(0, False, True, True)).decode(u"ASCII")
            self.translated_keyword = (self._io.read_bytes_term(0, False, True, True)).decode(u"UTF-8")
            if self.compression_flag == 0:
                pass
                self._raw_text_plain = self._io.read_bytes_full()
                _io__raw_text_plain = KaitaiStream(BytesIO(self._raw_text_plain))
                self.text_plain = Png.InternationalText(_io__raw_text_plain, self, self._root)
                self.text_plain._read()

            if self.compression_flag == 1:
                pass
                self._raw__raw_text_zlib = self._io.read_bytes_full()
                self._raw_text_zlib = zlib.decompress(self._raw__raw_text_zlib)
                self.text_zlib__inner_size = len(self._raw_text_zlib)
                _io__raw_text_zlib = KaitaiStream(BytesIO(self._raw_text_zlib))
                self.text_zlib = Png.InternationalText(_io__raw_text_zlib, self, self._root)
                self.text_zlib._read()

            self._dirty = False


        def _fetch_instances(self):
            pass
            if self.compression_flag == 0:
                pass
                self.text_plain._fetch_instances()

            if self.compression_flag == 1:
                pass
                self.text_zlib._fetch_instances()



        def _write__seq(self, io=None):
            super(Png.InternationalTextChunk, self)._write__seq(io)
            self._io.write_bytes((self.keyword).encode(u"ISO-8859-1"))
            self._io.write_u1(0)
            self._io.write_u1(self.compression_flag)
            self._io.write_u1(int(self.compression_method))
            self._io.write_bytes((self.language_tag).encode(u"ASCII"))
            self._io.write_u1(0)
            self._io.write_bytes((self.translated_keyword).encode(u"UTF-8"))
            self._io.write_u1(0)
            if self.compression_flag == 0:
                pass
                _io__raw_text_plain = KaitaiStream(BytesIO(bytearray(self._io.size() - self._io.pos())))
                self._io.add_child_stream(_io__raw_text_plain)
                _pos2 = self._io.pos()
                self._io.seek(self._io.pos() + (self._io.size() - self._io.pos()))
                def handler(parent, _io__raw_text_plain=_io__raw_text_plain):
                    self._raw_text_plain = _io__raw_text_plain.to_byte_array()
                    parent.write_bytes(self._raw_text_plain)
                    if not parent.is_eof():
                        raise kaitaistruct.ConsistencyError(u"raw(text_plain)", 0, parent.size() - parent.pos())
                _io__raw_text_plain.write_back_handler = KaitaiStream.WriteBackHandler(_pos2, handler)
                self.text_plain._write__seq(_io__raw_text_plain)

            if self.compression_flag == 1:
                pass
                _io__raw_text_zlib = KaitaiStream(BytesIO(bytearray(self.text_zlib__inner_size)))
                self._io.add_child_stream(_io__raw_text_zlib)
                _pos2 = self._io.pos()
                self._io.seek(self._io.pos() + (self._io.size() - self._io.pos()))
                def handler(parent, _io__raw_text_zlib=_io__raw_text_zlib):
                    self._raw_text_zlib = _io__raw_text_zlib.to_byte_array()
                    self._raw__raw_text_zlib = zlib.compress(self._raw_text_zlib)
                    parent.write_bytes(self._raw__raw_text_zlib)
                    if not parent.is_eof():
                        raise kaitaistruct.ConsistencyError(u"raw(text_zlib)", 0, parent.size() - parent.pos())
                _io__raw_text_zlib.write_back_handler = KaitaiStream.WriteBackHandler(_pos2, handler)
                self.text_zlib._write__seq(_io__raw_text_zlib)



        def _check(self):
            if KaitaiStream.byte_array_index_of((self.keyword).encode(u"ISO-8859-1"), 0) != -1:
                raise kaitaistruct.ConsistencyError(u"keyword", -1, KaitaiStream.byte_array_index_of((self.keyword).encode(u"ISO-8859-1"), 0))
            if not  ((self.compression_flag == 0) or (self.compression_flag == 1)) :
                raise kaitaistruct.ValidationNotAnyOfError(self.compression_flag, None, u"/types/international_text_chunk/seq/1")
            if not self.compression_method == (Png.CompressionMethods.zlib if self.compression_flag == 1 else self.compression_method):
                raise kaitaistruct.ValidationNotEqualError((Png.CompressionMethods.zlib if self.compression_flag == 1 else self.compression_method), self.compression_method, None, u"/types/international_text_chunk/seq/2")
            if KaitaiStream.byte_array_index_of((self.language_tag).encode(u"ASCII"), 0) != -1:
                raise kaitaistruct.ConsistencyError(u"language_tag", -1, KaitaiStream.byte_array_index_of((self.language_tag).encode(u"ASCII"), 0))
            if KaitaiStream.byte_array_index_of((self.translated_keyword).encode(u"UTF-8"), 0) != -1:
                raise kaitaistruct.ConsistencyError(u"translated_keyword", -1, KaitaiStream.byte_array_index_of((self.translated_keyword).encode(u"UTF-8"), 0))
            if self.compression_flag == 0:
                pass
                if self.text_plain._root != self._root:
                    raise kaitaistruct.ConsistencyError(u"text_plain", self._root, self.text_plain._root)
                if self.text_plain._parent != self:
                    raise kaitaistruct.ConsistencyError(u"text_plain", self, self.text_plain._parent)

            if self.compression_flag == 1:
                pass
                if self.text_zlib._root != self._root:
                    raise kaitaistruct.ConsistencyError(u"text_zlib", self._root, self.text_zlib._root)
                if self.text_zlib._parent != self:
                    raise kaitaistruct.ConsistencyError(u"text_zlib", self, self.text_zlib._parent)

            self._dirty = False

        @property
        def text(self):
            """Text string (the "value" of this key-value pair), written in language
            specified in `language_tag`.
            
            Although it is not null-terminated (unlike other textual data in the
            `iTXt` chunk), it must not contain a zero byte
            (U+0000 NULL character). A newline should be represented by a single
            U+000A LINE FEED (LF) character (aka `\n`). The remaining control
            characters (U+0001..U+0009, U+000B..0+001F, U+007F..U+009F) are
            discouraged.
            """
            if hasattr(self, '_m_text'):
                return self._m_text

            self._m_text = (self.text_plain if self.compression_flag == 0 else self.text_zlib).value
            return getattr(self, '_m_text', None)

        def _invalidate_text(self):
            del self._m_text

    class MdcvChromaticity(ReadWriteKaitaiStruct):
        def __init__(self, _io=None, _parent=None, _root=None):
            super(Png.MdcvChromaticity, self).__init__(_io)
            self._parent = _parent
            self._root = _root

        def _read(self):
            self.x_int = self._io.read_u2be()
            self.y_int = self._io.read_u2be()
            self._dirty = False


        def _fetch_instances(self):
            pass


        def _write__seq(self, io=None):
            super(Png.MdcvChromaticity, self)._write__seq(io)
            self._io.write_u2be(self.x_int)
            self._io.write_u2be(self.y_int)


        def _check(self):
            self._dirty = False

        @property
        def x(self):
            if hasattr(self, '_m_x'):
                return self._m_x

            self._m_x = self.x_int * 0.00002
            return getattr(self, '_m_x', None)

        def _invalidate_x(self):
            del self._m_x
        @property
        def y(self):
            if hasattr(self, '_m_y'):
                return self._m_y

            self._m_y = self.y_int * 0.00002
            return getattr(self, '_m_y', None)

        def _invalidate_y(self):
            del self._m_y

    class MdcvChunk(ReadWriteKaitaiStruct):
        """
        .. seealso::
           Source - https://www.w3.org/TR/png/#mDCV-chunk
        
        
        .. seealso::
           Source - https://w3c.github.io/png/Implementation_Report_3e/#mastering
        """
        def __init__(self, _io=None, _parent=None, _root=None):
            super(Png.MdcvChunk, self).__init__(_io)
            self._parent = _parent
            self._root = _root

        def _read(self):
            self.red = Png.MdcvChromaticity(self._io, self, self._root)
            self.red._read()
            self.green = Png.MdcvChromaticity(self._io, self, self._root)
            self.green._read()
            self.blue = Png.MdcvChromaticity(self._io, self, self._root)
            self.blue._read()
            self.white_point = Png.MdcvChromaticity(self._io, self, self._root)
            self.white_point._read()
            self.max_luminance_int = self._io.read_u4be()
            self.min_luminance_int = self._io.read_u4be()
            self._dirty = False


        def _fetch_instances(self):
            pass
            self.red._fetch_instances()
            self.green._fetch_instances()
            self.blue._fetch_instances()
            self.white_point._fetch_instances()


        def _write__seq(self, io=None):
            super(Png.MdcvChunk, self)._write__seq(io)
            self.red._write__seq(self._io)
            self.green._write__seq(self._io)
            self.blue._write__seq(self._io)
            self.white_point._write__seq(self._io)
            self._io.write_u4be(self.max_luminance_int)
            self._io.write_u4be(self.min_luminance_int)


        def _check(self):
            if self.red._root != self._root:
                raise kaitaistruct.ConsistencyError(u"red", self._root, self.red._root)
            if self.red._parent != self:
                raise kaitaistruct.ConsistencyError(u"red", self, self.red._parent)
            if self.green._root != self._root:
                raise kaitaistruct.ConsistencyError(u"green", self._root, self.green._root)
            if self.green._parent != self:
                raise kaitaistruct.ConsistencyError(u"green", self, self.green._parent)
            if self.blue._root != self._root:
                raise kaitaistruct.ConsistencyError(u"blue", self._root, self.blue._root)
            if self.blue._parent != self:
                raise kaitaistruct.ConsistencyError(u"blue", self, self.blue._parent)
            if self.white_point._root != self._root:
                raise kaitaistruct.ConsistencyError(u"white_point", self._root, self.white_point._root)
            if self.white_point._parent != self:
                raise kaitaistruct.ConsistencyError(u"white_point", self, self.white_point._parent)
            self._dirty = False

        @property
        def max_luminance(self):
            """Maximum luminance in cd/m^2."""
            if hasattr(self, '_m_max_luminance'):
                return self._m_max_luminance

            self._m_max_luminance = self.max_luminance_int * 0.0001
            return getattr(self, '_m_max_luminance', None)

        def _invalidate_max_luminance(self):
            del self._m_max_luminance
        @property
        def min_luminance(self):
            """Minimum luminance in cd/m^2."""
            if hasattr(self, '_m_min_luminance'):
                return self._m_min_luminance

            self._m_min_luminance = self.min_luminance_int * 0.0001
            return getattr(self, '_m_min_luminance', None)

        def _invalidate_min_luminance(self):
            del self._m_min_luminance

    class PhysChunk(ReadWriteKaitaiStruct):
        """Physical pixel dimensions (`pHYs`) chunk specifies the intended physical
        size of the pixels (in meters) or pixel aspect ratio for display of the
        image.
        
        .. seealso::
           Source - https://www.w3.org/TR/png/#11pHYs
        """
        def __init__(self, _io=None, _parent=None, _root=None):
            super(Png.PhysChunk, self).__init__(_io)
            self._parent = _parent
            self._root = _root

        def _read(self):
            self.pixels_per_unit_x = self._io.read_u4be()
            self.pixels_per_unit_y = self._io.read_u4be()
            self.unit = KaitaiStream.resolve_enum(Png.PhysUnit, self._io.read_u1())
            if not isinstance(self.unit, Png.PhysUnit):
                raise kaitaistruct.ValidationNotInEnumError(self.unit, self._io, u"/types/phys_chunk/seq/2")
            self._dirty = False


        def _fetch_instances(self):
            pass


        def _write__seq(self, io=None):
            super(Png.PhysChunk, self)._write__seq(io)
            self._io.write_u4be(self.pixels_per_unit_x)
            self._io.write_u4be(self.pixels_per_unit_y)
            self._io.write_u1(int(self.unit))


        def _check(self):
            if not isinstance(self.unit, Png.PhysUnit):
                raise kaitaistruct.ValidationNotInEnumError(self.unit, None, u"/types/phys_chunk/seq/2")
            self._dirty = False

        @property
        def dots_per_inch_x(self):
            """Horizontal resolution (DPI)."""
            if hasattr(self, '_m_dots_per_inch_x'):
                return self._m_dots_per_inch_x

            if self.unit == Png.PhysUnit.meter:
                pass
                self._m_dots_per_inch_x = self.pixels_per_unit_x * 0.0254

            return getattr(self, '_m_dots_per_inch_x', None)

        def _invalidate_dots_per_inch_x(self):
            del self._m_dots_per_inch_x
        @property
        def dots_per_inch_y(self):
            """Vertical resolution (DPI)."""
            if hasattr(self, '_m_dots_per_inch_y'):
                return self._m_dots_per_inch_y

            if self.unit == Png.PhysUnit.meter:
                pass
                self._m_dots_per_inch_y = self.pixels_per_unit_y * 0.0254

            return getattr(self, '_m_dots_per_inch_y', None)

        def _invalidate_dots_per_inch_y(self):
            del self._m_dots_per_inch_y

    class PlteChunk(ReadWriteKaitaiStruct):
        """
        .. seealso::
           Source - https://www.w3.org/TR/png/#11PLTE
        """
        def __init__(self, _io=None, _parent=None, _root=None):
            super(Png.PlteChunk, self).__init__(_io)
            self._parent = _parent
            self._root = _root

        def _read(self):
            self.entries = []
            i = 0
            while not self._io.is_eof():
                _t_entries = Png.Rgb(self._io, self, self._root)
                try:
                    _t_entries._read()
                finally:
                    self.entries.append(_t_entries)
                i += 1

            self._dirty = False


        def _fetch_instances(self):
            pass
            for i in range(len(self.entries)):
                pass
                self.entries[i]._fetch_instances()



        def _write__seq(self, io=None):
            super(Png.PlteChunk, self)._write__seq(io)
            for i in range(len(self.entries)):
                pass
                if self._io.is_eof():
                    raise kaitaistruct.ConsistencyError(u"entries", 0, self._io.size() - self._io.pos())
                self.entries[i]._write__seq(self._io)

            if not self._io.is_eof():
                raise kaitaistruct.ConsistencyError(u"entries", 0, self._io.size() - self._io.pos())


        def _check(self):
            for i in range(len(self.entries)):
                pass
                if self.entries[i]._root != self._root:
                    raise kaitaistruct.ConsistencyError(u"entries", self._root, self.entries[i]._root)
                if self.entries[i]._parent != self:
                    raise kaitaistruct.ConsistencyError(u"entries", self, self.entries[i]._parent)

            self._dirty = False


    class Rgb(ReadWriteKaitaiStruct):
        def __init__(self, _io=None, _parent=None, _root=None):
            super(Png.Rgb, self).__init__(_io)
            self._parent = _parent
            self._root = _root

        def _read(self):
            self.r = self._io.read_u1()
            self.g = self._io.read_u1()
            self.b = self._io.read_u1()
            self._dirty = False


        def _fetch_instances(self):
            pass


        def _write__seq(self, io=None):
            super(Png.Rgb, self)._write__seq(io)
            self._io.write_u1(self.r)
            self._io.write_u1(self.g)
            self._io.write_u1(self.b)


        def _check(self):
            self._dirty = False


    class SbitChunk(ReadWriteKaitaiStruct):
        """Significant bits (`sBIT`) chunk stores the original number of significant
        bits of the sample values (which can be less than or equal to the sample
        depth). This allows PNG decoders to recover the original data losslessly
        even if the data had a sample depth not directly supported by PNG.
        
        .. seealso::
           Source - https://www.w3.org/TR/png/#11sBIT
        """
        def __init__(self, _io=None, _parent=None, _root=None):
            super(Png.SbitChunk, self).__init__(_io)
            self._parent = _parent
            self._root = _root

        def _read(self):
            _on = self._root.ihdr.color_type
            if _on == Png.ColorType.greyscale:
                pass
                self.significant_bits = Png.SbitGreyscale(False, self._io, self, self._root)
                self.significant_bits._read()
            elif _on == Png.ColorType.greyscale_alpha:
                pass
                self.significant_bits = Png.SbitGreyscale(True, self._io, self, self._root)
                self.significant_bits._read()
            elif _on == Png.ColorType.indexed:
                pass
                self.significant_bits = Png.SbitTruecolor(False, self._io, self, self._root)
                self.significant_bits._read()
            elif _on == Png.ColorType.truecolor:
                pass
                self.significant_bits = Png.SbitTruecolor(False, self._io, self, self._root)
                self.significant_bits._read()
            elif _on == Png.ColorType.truecolor_alpha:
                pass
                self.significant_bits = Png.SbitTruecolor(True, self._io, self, self._root)
                self.significant_bits._read()
            self._dirty = False


        def _fetch_instances(self):
            pass
            _on = self._root.ihdr.color_type
            if _on == Png.ColorType.greyscale:
                pass
                self.significant_bits._fetch_instances()
            elif _on == Png.ColorType.greyscale_alpha:
                pass
                self.significant_bits._fetch_instances()
            elif _on == Png.ColorType.indexed:
                pass
                self.significant_bits._fetch_instances()
            elif _on == Png.ColorType.truecolor:
                pass
                self.significant_bits._fetch_instances()
            elif _on == Png.ColorType.truecolor_alpha:
                pass
                self.significant_bits._fetch_instances()


        def _write__seq(self, io=None):
            super(Png.SbitChunk, self)._write__seq(io)
            _on = self._root.ihdr.color_type
            if _on == Png.ColorType.greyscale:
                pass
                self.significant_bits._write__seq(self._io)
            elif _on == Png.ColorType.greyscale_alpha:
                pass
                self.significant_bits._write__seq(self._io)
            elif _on == Png.ColorType.indexed:
                pass
                self.significant_bits._write__seq(self._io)
            elif _on == Png.ColorType.truecolor:
                pass
                self.significant_bits._write__seq(self._io)
            elif _on == Png.ColorType.truecolor_alpha:
                pass
                self.significant_bits._write__seq(self._io)


        def _check(self):
            _on = self._root.ihdr.color_type
            if _on == Png.ColorType.greyscale:
                pass
                if self.significant_bits._root != self._root:
                    raise kaitaistruct.ConsistencyError(u"significant_bits", self._root, self.significant_bits._root)
                if self.significant_bits._parent != self:
                    raise kaitaistruct.ConsistencyError(u"significant_bits", self, self.significant_bits._parent)
                if self.significant_bits.has_alpha != False:
                    raise kaitaistruct.ConsistencyError(u"significant_bits", False, self.significant_bits.has_alpha)
            elif _on == Png.ColorType.greyscale_alpha:
                pass
                if self.significant_bits._root != self._root:
                    raise kaitaistruct.ConsistencyError(u"significant_bits", self._root, self.significant_bits._root)
                if self.significant_bits._parent != self:
                    raise kaitaistruct.ConsistencyError(u"significant_bits", self, self.significant_bits._parent)
                if self.significant_bits.has_alpha != True:
                    raise kaitaistruct.ConsistencyError(u"significant_bits", True, self.significant_bits.has_alpha)
            elif _on == Png.ColorType.indexed:
                pass
                if self.significant_bits._root != self._root:
                    raise kaitaistruct.ConsistencyError(u"significant_bits", self._root, self.significant_bits._root)
                if self.significant_bits._parent != self:
                    raise kaitaistruct.ConsistencyError(u"significant_bits", self, self.significant_bits._parent)
                if self.significant_bits.has_alpha != False:
                    raise kaitaistruct.ConsistencyError(u"significant_bits", False, self.significant_bits.has_alpha)
            elif _on == Png.ColorType.truecolor:
                pass
                if self.significant_bits._root != self._root:
                    raise kaitaistruct.ConsistencyError(u"significant_bits", self._root, self.significant_bits._root)
                if self.significant_bits._parent != self:
                    raise kaitaistruct.ConsistencyError(u"significant_bits", self, self.significant_bits._parent)
                if self.significant_bits.has_alpha != False:
                    raise kaitaistruct.ConsistencyError(u"significant_bits", False, self.significant_bits.has_alpha)
            elif _on == Png.ColorType.truecolor_alpha:
                pass
                if self.significant_bits._root != self._root:
                    raise kaitaistruct.ConsistencyError(u"significant_bits", self._root, self.significant_bits._root)
                if self.significant_bits._parent != self:
                    raise kaitaistruct.ConsistencyError(u"significant_bits", self, self.significant_bits._parent)
                if self.significant_bits.has_alpha != True:
                    raise kaitaistruct.ConsistencyError(u"significant_bits", True, self.significant_bits.has_alpha)
            self._dirty = False

        @property
        def sample_depth(self):
            if hasattr(self, '_m_sample_depth'):
                return self._m_sample_depth

            self._m_sample_depth = (8 if self._root.ihdr.color_type == Png.ColorType.indexed else self._root.ihdr.bit_depth)
            return getattr(self, '_m_sample_depth', None)

        def _invalidate_sample_depth(self):
            del self._m_sample_depth

    class SbitGreyscale(ReadWriteKaitaiStruct):
        def __init__(self, has_alpha, _io=None, _parent=None, _root=None):
            super(Png.SbitGreyscale, self).__init__(_io)
            self._parent = _parent
            self._root = _root
            self.has_alpha = has_alpha

        def _read(self):
            self.grey = self._io.read_u1()
            if not self.grey >= 1:
                raise kaitaistruct.ValidationLessThanError(1, self.grey, self._io, u"/types/sbit_greyscale/seq/0")
            if not self.grey <= self._parent.sample_depth:
                raise kaitaistruct.ValidationGreaterThanError(self._parent.sample_depth, self.grey, self._io, u"/types/sbit_greyscale/seq/0")
            if self.has_alpha:
                pass
                self.alpha = self._io.read_u1()
                if not self.alpha >= 1:
                    raise kaitaistruct.ValidationLessThanError(1, self.alpha, self._io, u"/types/sbit_greyscale/seq/1")
                if not self.alpha <= self._parent.sample_depth:
                    raise kaitaistruct.ValidationGreaterThanError(self._parent.sample_depth, self.alpha, self._io, u"/types/sbit_greyscale/seq/1")

            self._dirty = False


        def _fetch_instances(self):
            pass
            if self.has_alpha:
                pass



        def _write__seq(self, io=None):
            super(Png.SbitGreyscale, self)._write__seq(io)
            self._io.write_u1(self.grey)
            if self.has_alpha:
                pass
                self._io.write_u1(self.alpha)



        def _check(self):
            if not self.grey >= 1:
                raise kaitaistruct.ValidationLessThanError(1, self.grey, None, u"/types/sbit_greyscale/seq/0")
            if not self.grey <= self._parent.sample_depth:
                raise kaitaistruct.ValidationGreaterThanError(self._parent.sample_depth, self.grey, None, u"/types/sbit_greyscale/seq/0")
            if self.has_alpha:
                pass
                if not self.alpha >= 1:
                    raise kaitaistruct.ValidationLessThanError(1, self.alpha, None, u"/types/sbit_greyscale/seq/1")
                if not self.alpha <= self._parent.sample_depth:
                    raise kaitaistruct.ValidationGreaterThanError(self._parent.sample_depth, self.alpha, None, u"/types/sbit_greyscale/seq/1")

            self._dirty = False


    class SbitTruecolor(ReadWriteKaitaiStruct):
        def __init__(self, has_alpha, _io=None, _parent=None, _root=None):
            super(Png.SbitTruecolor, self).__init__(_io)
            self._parent = _parent
            self._root = _root
            self.has_alpha = has_alpha

        def _read(self):
            self.red = self._io.read_u1()
            if not self.red >= 1:
                raise kaitaistruct.ValidationLessThanError(1, self.red, self._io, u"/types/sbit_truecolor/seq/0")
            if not self.red <= self._parent.sample_depth:
                raise kaitaistruct.ValidationGreaterThanError(self._parent.sample_depth, self.red, self._io, u"/types/sbit_truecolor/seq/0")
            self.green = self._io.read_u1()
            if not self.green >= 1:
                raise kaitaistruct.ValidationLessThanError(1, self.green, self._io, u"/types/sbit_truecolor/seq/1")
            if not self.green <= self._parent.sample_depth:
                raise kaitaistruct.ValidationGreaterThanError(self._parent.sample_depth, self.green, self._io, u"/types/sbit_truecolor/seq/1")
            self.blue = self._io.read_u1()
            if not self.blue >= 1:
                raise kaitaistruct.ValidationLessThanError(1, self.blue, self._io, u"/types/sbit_truecolor/seq/2")
            if not self.blue <= self._parent.sample_depth:
                raise kaitaistruct.ValidationGreaterThanError(self._parent.sample_depth, self.blue, self._io, u"/types/sbit_truecolor/seq/2")
            if self.has_alpha:
                pass
                self.alpha = self._io.read_u1()
                if not self.alpha >= 1:
                    raise kaitaistruct.ValidationLessThanError(1, self.alpha, self._io, u"/types/sbit_truecolor/seq/3")
                if not self.alpha <= self._parent.sample_depth:
                    raise kaitaistruct.ValidationGreaterThanError(self._parent.sample_depth, self.alpha, self._io, u"/types/sbit_truecolor/seq/3")

            self._dirty = False


        def _fetch_instances(self):
            pass
            if self.has_alpha:
                pass



        def _write__seq(self, io=None):
            super(Png.SbitTruecolor, self)._write__seq(io)
            self._io.write_u1(self.red)
            self._io.write_u1(self.green)
            self._io.write_u1(self.blue)
            if self.has_alpha:
                pass
                self._io.write_u1(self.alpha)



        def _check(self):
            if not self.red >= 1:
                raise kaitaistruct.ValidationLessThanError(1, self.red, None, u"/types/sbit_truecolor/seq/0")
            if not self.red <= self._parent.sample_depth:
                raise kaitaistruct.ValidationGreaterThanError(self._parent.sample_depth, self.red, None, u"/types/sbit_truecolor/seq/0")
            if not self.green >= 1:
                raise kaitaistruct.ValidationLessThanError(1, self.green, None, u"/types/sbit_truecolor/seq/1")
            if not self.green <= self._parent.sample_depth:
                raise kaitaistruct.ValidationGreaterThanError(self._parent.sample_depth, self.green, None, u"/types/sbit_truecolor/seq/1")
            if not self.blue >= 1:
                raise kaitaistruct.ValidationLessThanError(1, self.blue, None, u"/types/sbit_truecolor/seq/2")
            if not self.blue <= self._parent.sample_depth:
                raise kaitaistruct.ValidationGreaterThanError(self._parent.sample_depth, self.blue, None, u"/types/sbit_truecolor/seq/2")
            if self.has_alpha:
                pass
                if not self.alpha >= 1:
                    raise kaitaistruct.ValidationLessThanError(1, self.alpha, None, u"/types/sbit_truecolor/seq/3")
                if not self.alpha <= self._parent.sample_depth:
                    raise kaitaistruct.ValidationGreaterThanError(self._parent.sample_depth, self.alpha, None, u"/types/sbit_truecolor/seq/3")

            self._dirty = False


    class SpltChunk(ReadWriteKaitaiStruct):
        """Suggested palette (`sPLT`) chunk.
        
        Multiple `sPLT` chunks are permitted, but each must have a different
        palette name.
        
        .. seealso::
           Source - https://www.w3.org/TR/png/#11sPLT
        
        
        .. seealso::
           Source - https://www.w3.org/TR/png/#12Suggested-palettes
        """
        def __init__(self, _io=None, _parent=None, _root=None):
            super(Png.SpltChunk, self).__init__(_io)
            self._parent = _parent
            self._root = _root

        def _read(self):
            self.palette_name = (self._io.read_bytes_term(0, False, True, True)).decode(u"ISO-8859-1")
            self.sample_depth = self._io.read_u1()
            if not  ((self.sample_depth == 8) or (self.sample_depth == 16)) :
                raise kaitaistruct.ValidationNotAnyOfError(self.sample_depth, self._io, u"/types/splt_chunk/seq/1")
            self.entries = []
            i = 0
            while not self._io.is_eof():
                _t_entries = Png.SpltEntry(self._io, self, self._root)
                try:
                    _t_entries._read()
                finally:
                    self.entries.append(_t_entries)
                i += 1

            self._dirty = False


        def _fetch_instances(self):
            pass
            for i in range(len(self.entries)):
                pass
                self.entries[i]._fetch_instances()



        def _write__seq(self, io=None):
            super(Png.SpltChunk, self)._write__seq(io)
            self._io.write_bytes((self.palette_name).encode(u"ISO-8859-1"))
            self._io.write_u1(0)
            self._io.write_u1(self.sample_depth)
            for i in range(len(self.entries)):
                pass
                if self._io.is_eof():
                    raise kaitaistruct.ConsistencyError(u"entries", 0, self._io.size() - self._io.pos())
                self.entries[i]._write__seq(self._io)

            if not self._io.is_eof():
                raise kaitaistruct.ConsistencyError(u"entries", 0, self._io.size() - self._io.pos())


        def _check(self):
            if KaitaiStream.byte_array_index_of((self.palette_name).encode(u"ISO-8859-1"), 0) != -1:
                raise kaitaistruct.ConsistencyError(u"palette_name", -1, KaitaiStream.byte_array_index_of((self.palette_name).encode(u"ISO-8859-1"), 0))
            if not  ((self.sample_depth == 8) or (self.sample_depth == 16)) :
                raise kaitaistruct.ValidationNotAnyOfError(self.sample_depth, None, u"/types/splt_chunk/seq/1")
            for i in range(len(self.entries)):
                pass
                if self.entries[i]._root != self._root:
                    raise kaitaistruct.ConsistencyError(u"entries", self._root, self.entries[i]._root)
                if self.entries[i]._parent != self:
                    raise kaitaistruct.ConsistencyError(u"entries", self, self.entries[i]._parent)

            self._dirty = False


    class SpltEntry(ReadWriteKaitaiStruct):
        def __init__(self, _io=None, _parent=None, _root=None):
            super(Png.SpltEntry, self).__init__(_io)
            self._parent = _parent
            self._root = _root

        def _read(self):
            _on = self._parent.sample_depth
            if _on == 8:
                pass
                self.red = self._io.read_u1()
            else:
                pass
                self.red = self._io.read_u2be()
            _on = self._parent.sample_depth
            if _on == 8:
                pass
                self.green = self._io.read_u1()
            else:
                pass
                self.green = self._io.read_u2be()
            _on = self._parent.sample_depth
            if _on == 8:
                pass
                self.blue = self._io.read_u1()
            else:
                pass
                self.blue = self._io.read_u2be()
            _on = self._parent.sample_depth
            if _on == 8:
                pass
                self.alpha = self._io.read_u1()
            else:
                pass
                self.alpha = self._io.read_u2be()
            self.freq = self._io.read_u2be()
            self._dirty = False


        def _fetch_instances(self):
            pass
            _on = self._parent.sample_depth
            if _on == 8:
                pass
            else:
                pass
            _on = self._parent.sample_depth
            if _on == 8:
                pass
            else:
                pass
            _on = self._parent.sample_depth
            if _on == 8:
                pass
            else:
                pass
            _on = self._parent.sample_depth
            if _on == 8:
                pass
            else:
                pass


        def _write__seq(self, io=None):
            super(Png.SpltEntry, self)._write__seq(io)
            _on = self._parent.sample_depth
            if _on == 8:
                pass
                self._io.write_u1(self.red)
            else:
                pass
                self._io.write_u2be(self.red)
            _on = self._parent.sample_depth
            if _on == 8:
                pass
                self._io.write_u1(self.green)
            else:
                pass
                self._io.write_u2be(self.green)
            _on = self._parent.sample_depth
            if _on == 8:
                pass
                self._io.write_u1(self.blue)
            else:
                pass
                self._io.write_u2be(self.blue)
            _on = self._parent.sample_depth
            if _on == 8:
                pass
                self._io.write_u1(self.alpha)
            else:
                pass
                self._io.write_u2be(self.alpha)
            self._io.write_u2be(self.freq)


        def _check(self):
            _on = self._parent.sample_depth
            if _on == 8:
                pass
            else:
                pass
            _on = self._parent.sample_depth
            if _on == 8:
                pass
            else:
                pass
            _on = self._parent.sample_depth
            if _on == 8:
                pass
            else:
                pass
            _on = self._parent.sample_depth
            if _on == 8:
                pass
            else:
                pass
            self._dirty = False


    class SrgbChunk(ReadWriteKaitaiStruct):
        """
        .. seealso::
           Source - https://www.w3.org/TR/png/#11sRGB
        """

        class Intent(IntEnum):
            perceptual = 0
            relative_colorimetric = 1
            saturation = 2
            absolute_colorimetric = 3
        def __init__(self, _io=None, _parent=None, _root=None):
            super(Png.SrgbChunk, self).__init__(_io)
            self._parent = _parent
            self._root = _root

        def _read(self):
            self.render_intent = KaitaiStream.resolve_enum(Png.SrgbChunk.Intent, self._io.read_u1())
            if not isinstance(self.render_intent, Png.SrgbChunk.Intent):
                raise kaitaistruct.ValidationNotInEnumError(self.render_intent, self._io, u"/types/srgb_chunk/seq/0")
            self._dirty = False


        def _fetch_instances(self):
            pass


        def _write__seq(self, io=None):
            super(Png.SrgbChunk, self)._write__seq(io)
            self._io.write_u1(int(self.render_intent))


        def _check(self):
            if not isinstance(self.render_intent, Png.SrgbChunk.Intent):
                raise kaitaistruct.ValidationNotInEnumError(self.render_intent, None, u"/types/srgb_chunk/seq/0")
            self._dirty = False


    class TextChunk(ReadWriteKaitaiStruct):
        """Textual data (`tEXt`) chunk effectively allows you to store key-value
        string pairs in the PNG container.
        
        Both the "key" (`keyword`) and "value" (`text`) parts are restricted to
        printable ISO-8859-1 (Latin-1) characters and ASCII spaces, with the
        exception that `text` can also contain newlines (U+000A LINE FEED (LF)
        characters) and U+00A0 NON-BREAKING SPACE characters.
        
        .. seealso::
           Source - https://www.w3.org/TR/png/#11tEXt
        """
        def __init__(self, _io=None, _parent=None, _root=None):
            super(Png.TextChunk, self).__init__(_io)
            self._parent = _parent
            self._root = _root

        def _read(self):
            self.keyword = (self._io.read_bytes_term(0, False, True, True)).decode(u"ISO-8859-1")
            self.text = (self._io.read_bytes_full()).decode(u"ISO-8859-1")
            self._dirty = False


        def _fetch_instances(self):
            pass


        def _write__seq(self, io=None):
            super(Png.TextChunk, self)._write__seq(io)
            self._io.write_bytes((self.keyword).encode(u"ISO-8859-1"))
            self._io.write_u1(0)
            self._io.write_bytes((self.text).encode(u"ISO-8859-1"))
            if not self._io.is_eof():
                raise kaitaistruct.ConsistencyError(u"text", 0, self._io.size() - self._io.pos())


        def _check(self):
            if KaitaiStream.byte_array_index_of((self.keyword).encode(u"ISO-8859-1"), 0) != -1:
                raise kaitaistruct.ConsistencyError(u"keyword", -1, KaitaiStream.byte_array_index_of((self.keyword).encode(u"ISO-8859-1"), 0))
            self._dirty = False


    class TimeChunk(ReadWriteKaitaiStruct):
        """Time chunk stores time stamp of last modification of this image,
        up to 1 second precision in UTC timezone.
        
        .. seealso::
           Source - https://www.w3.org/TR/png/#11tIME
        """
        def __init__(self, _io=None, _parent=None, _root=None):
            super(Png.TimeChunk, self).__init__(_io)
            self._parent = _parent
            self._root = _root

        def _read(self):
            self.year = self._io.read_u2be()
            self.month = self._io.read_u1()
            self.day = self._io.read_u1()
            self.hour = self._io.read_u1()
            self.minute = self._io.read_u1()
            self.second = self._io.read_u1()
            self._dirty = False


        def _fetch_instances(self):
            pass


        def _write__seq(self, io=None):
            super(Png.TimeChunk, self)._write__seq(io)
            self._io.write_u2be(self.year)
            self._io.write_u1(self.month)
            self._io.write_u1(self.day)
            self._io.write_u1(self.hour)
            self._io.write_u1(self.minute)
            self._io.write_u1(self.second)


        def _check(self):
            self._dirty = False


    class TrnsChunk(ReadWriteKaitaiStruct):
        """Transparency (`tRNS`) chunk specifies either alpha values that are
        associated with palette entries (for indexed-color images) or a single
        transparent color (for greyscale and truecolor images).
        
        A `tRNS` chunk must not appear for color types
        `color_type::greyscale_alpha` = 4 and `color_type::truecolor_alpha` = 6,
        since a full alpha channel is already present in those cases.
        
        .. seealso::
           Source - https://www.w3.org/TR/png/#11tRNS
        """
        def __init__(self, _io=None, _parent=None, _root=None):
            super(Png.TrnsChunk, self).__init__(_io)
            self._parent = _parent
            self._root = _root

        def _read(self):
            if self._root.ihdr.color_type == Png.ColorType.indexed:
                pass
                self.palette_alphas = []
                i = 0
                while not self._io.is_eof():
                    self.palette_alphas.append(self._io.read_u1())
                    i += 1


            _on = self._root.ihdr.color_type
            if _on == Png.ColorType.greyscale:
                pass
                self.transparent_color = Png.TrnsGreyscaleColor(self._io, self, self._root)
                self.transparent_color._read()
            elif _on == Png.ColorType.truecolor:
                pass
                self.transparent_color = Png.TrnsTruecolorColor(self._io, self, self._root)
                self.transparent_color._read()
            self._dirty = False


        def _fetch_instances(self):
            pass
            if self._root.ihdr.color_type == Png.ColorType.indexed:
                pass
                for i in range(len(self.palette_alphas)):
                    pass


            _on = self._root.ihdr.color_type
            if _on == Png.ColorType.greyscale:
                pass
                self.transparent_color._fetch_instances()
            elif _on == Png.ColorType.truecolor:
                pass
                self.transparent_color._fetch_instances()


        def _write__seq(self, io=None):
            super(Png.TrnsChunk, self)._write__seq(io)
            if self._root.ihdr.color_type == Png.ColorType.indexed:
                pass
                for i in range(len(self.palette_alphas)):
                    pass
                    if self._io.is_eof():
                        raise kaitaistruct.ConsistencyError(u"palette_alphas", 0, self._io.size() - self._io.pos())
                    self._io.write_u1(self.palette_alphas[i])

                if not self._io.is_eof():
                    raise kaitaistruct.ConsistencyError(u"palette_alphas", 0, self._io.size() - self._io.pos())

            _on = self._root.ihdr.color_type
            if _on == Png.ColorType.greyscale:
                pass
                self.transparent_color._write__seq(self._io)
            elif _on == Png.ColorType.truecolor:
                pass
                self.transparent_color._write__seq(self._io)


        def _check(self):
            if self._root.ihdr.color_type == Png.ColorType.indexed:
                pass
                for i in range(len(self.palette_alphas)):
                    pass


            _on = self._root.ihdr.color_type
            if _on == Png.ColorType.greyscale:
                pass
                if self.transparent_color._root != self._root:
                    raise kaitaistruct.ConsistencyError(u"transparent_color", self._root, self.transparent_color._root)
                if self.transparent_color._parent != self:
                    raise kaitaistruct.ConsistencyError(u"transparent_color", self, self.transparent_color._parent)
            elif _on == Png.ColorType.truecolor:
                pass
                if self.transparent_color._root != self._root:
                    raise kaitaistruct.ConsistencyError(u"transparent_color", self._root, self.transparent_color._root)
                if self.transparent_color._parent != self:
                    raise kaitaistruct.ConsistencyError(u"transparent_color", self, self.transparent_color._parent)
            self._dirty = False

        @property
        def sample_mask(self):
            if hasattr(self, '_m_sample_mask'):
                return self._m_sample_mask

            self._m_sample_mask = (1 << self._root.ihdr.bit_depth) - 1
            return getattr(self, '_m_sample_mask', None)

        def _invalidate_sample_mask(self):
            del self._m_sample_mask

    class TrnsGreyscaleColor(ReadWriteKaitaiStruct):
        def __init__(self, _io=None, _parent=None, _root=None):
            super(Png.TrnsGreyscaleColor, self).__init__(_io)
            self._parent = _parent
            self._root = _root

        def _read(self):
            self.grey_raw = self._io.read_u2be()
            self._dirty = False


        def _fetch_instances(self):
            pass


        def _write__seq(self, io=None):
            super(Png.TrnsGreyscaleColor, self)._write__seq(io)
            self._io.write_u2be(self.grey_raw)


        def _check(self):
            self._dirty = False

        @property
        def grey(self):
            if hasattr(self, '_m_grey'):
                return self._m_grey

            self._m_grey = self.grey_raw & self._parent.sample_mask
            return getattr(self, '_m_grey', None)

        def _invalidate_grey(self):
            del self._m_grey

    class TrnsTruecolorColor(ReadWriteKaitaiStruct):
        def __init__(self, _io=None, _parent=None, _root=None):
            super(Png.TrnsTruecolorColor, self).__init__(_io)
            self._parent = _parent
            self._root = _root

        def _read(self):
            self.red_raw = self._io.read_u2be()
            self.green_raw = self._io.read_u2be()
            self.blue_raw = self._io.read_u2be()
            self._dirty = False


        def _fetch_instances(self):
            pass


        def _write__seq(self, io=None):
            super(Png.TrnsTruecolorColor, self)._write__seq(io)
            self._io.write_u2be(self.red_raw)
            self._io.write_u2be(self.green_raw)
            self._io.write_u2be(self.blue_raw)


        def _check(self):
            self._dirty = False

        @property
        def blue(self):
            if hasattr(self, '_m_blue'):
                return self._m_blue

            self._m_blue = self.blue_raw & self._parent.sample_mask
            return getattr(self, '_m_blue', None)

        def _invalidate_blue(self):
            del self._m_blue
        @property
        def green(self):
            if hasattr(self, '_m_green'):
                return self._m_green

            self._m_green = self.green_raw & self._parent.sample_mask
            return getattr(self, '_m_green', None)

        def _invalidate_green(self):
            del self._m_green
        @property
        def red(self):
            if hasattr(self, '_m_red'):
                return self._m_red

            self._m_red = self.red_raw & self._parent.sample_mask
            return getattr(self, '_m_red', None)

        def _invalidate_red(self):
            del self._m_red