358 lines
13 KiB
Python
358 lines
13 KiB
Python
# This is a generated file! Please edit source .ksy file and use kaitai-struct-compiler to rebuild
|
|
|
|
import kaitaistruct
|
|
from kaitaistruct import KaitaiStruct, KaitaiStream, BytesIO
|
|
from enum import Enum
|
|
|
|
|
|
if getattr(kaitaistruct, 'API_VERSION', (0, 9)) < (0, 9):
|
|
raise Exception("Incompatible Kaitai Struct Python API: 0.9 or later is required, but you have %s" % (kaitaistruct.__version__))
|
|
|
|
class Gif(KaitaiStruct):
|
|
"""GIF (Graphics Interchange Format) is an image file format, developed
|
|
in 1987. It became popular in 1990s as one of the main image formats
|
|
used in World Wide Web.
|
|
|
|
GIF format allows encoding of palette-based images up to 256 colors
|
|
(each of the colors can be chosen from a 24-bit RGB
|
|
colorspace). Image data stream uses LZW (Lempel-Ziv-Welch) lossless
|
|
compression.
|
|
|
|
Over the years, several version of the format were published and
|
|
several extensions to it were made, namely, a popular Netscape
|
|
extension that allows to store several images in one file, switching
|
|
between them, which produces crude form of animation.
|
|
|
|
Structurally, format consists of several mandatory headers and then
|
|
a stream of blocks follows. Blocks can carry additional
|
|
metainformation or image data.
|
|
"""
|
|
|
|
class BlockType(Enum):
|
|
extension = 33
|
|
local_image_descriptor = 44
|
|
end_of_file = 59
|
|
|
|
class ExtensionLabel(Enum):
|
|
graphic_control = 249
|
|
comment = 254
|
|
application = 255
|
|
def __init__(self, _io, _parent=None, _root=None):
|
|
self._io = _io
|
|
self._parent = _parent
|
|
self._root = _root if _root else self
|
|
self._read()
|
|
|
|
def _read(self):
|
|
self.hdr = Gif.Header(self._io, self, self._root)
|
|
self.logical_screen_descriptor = Gif.LogicalScreenDescriptorStruct(self._io, self, self._root)
|
|
if self.logical_screen_descriptor.has_color_table:
|
|
self._raw_global_color_table = self._io.read_bytes((self.logical_screen_descriptor.color_table_size * 3))
|
|
_io__raw_global_color_table = KaitaiStream(BytesIO(self._raw_global_color_table))
|
|
self.global_color_table = Gif.ColorTable(_io__raw_global_color_table, self, self._root)
|
|
|
|
self.blocks = []
|
|
i = 0
|
|
while True:
|
|
_ = Gif.Block(self._io, self, self._root)
|
|
self.blocks.append(_)
|
|
if ((self._io.is_eof()) or (_.block_type == Gif.BlockType.end_of_file)) :
|
|
break
|
|
i += 1
|
|
|
|
class ImageData(KaitaiStruct):
|
|
"""
|
|
.. seealso::
|
|
- section 22 - https://www.w3.org/Graphics/GIF/spec-gif89a.txt
|
|
"""
|
|
def __init__(self, _io, _parent=None, _root=None):
|
|
self._io = _io
|
|
self._parent = _parent
|
|
self._root = _root if _root else self
|
|
self._read()
|
|
|
|
def _read(self):
|
|
self.lzw_min_code_size = self._io.read_u1()
|
|
self.subblocks = Gif.Subblocks(self._io, self, self._root)
|
|
|
|
|
|
class ColorTableEntry(KaitaiStruct):
|
|
def __init__(self, _io, _parent=None, _root=None):
|
|
self._io = _io
|
|
self._parent = _parent
|
|
self._root = _root if _root else self
|
|
self._read()
|
|
|
|
def _read(self):
|
|
self.red = self._io.read_u1()
|
|
self.green = self._io.read_u1()
|
|
self.blue = self._io.read_u1()
|
|
|
|
|
|
class LogicalScreenDescriptorStruct(KaitaiStruct):
|
|
"""
|
|
.. seealso::
|
|
- section 18 - https://www.w3.org/Graphics/GIF/spec-gif89a.txt
|
|
"""
|
|
def __init__(self, _io, _parent=None, _root=None):
|
|
self._io = _io
|
|
self._parent = _parent
|
|
self._root = _root if _root else self
|
|
self._read()
|
|
|
|
def _read(self):
|
|
self.screen_width = self._io.read_u2le()
|
|
self.screen_height = self._io.read_u2le()
|
|
self.flags = self._io.read_u1()
|
|
self.bg_color_index = self._io.read_u1()
|
|
self.pixel_aspect_ratio = self._io.read_u1()
|
|
|
|
@property
|
|
def has_color_table(self):
|
|
if hasattr(self, '_m_has_color_table'):
|
|
return self._m_has_color_table
|
|
|
|
self._m_has_color_table = (self.flags & 128) != 0
|
|
return getattr(self, '_m_has_color_table', None)
|
|
|
|
@property
|
|
def color_table_size(self):
|
|
if hasattr(self, '_m_color_table_size'):
|
|
return self._m_color_table_size
|
|
|
|
self._m_color_table_size = (2 << (self.flags & 7))
|
|
return getattr(self, '_m_color_table_size', None)
|
|
|
|
|
|
class LocalImageDescriptor(KaitaiStruct):
|
|
def __init__(self, _io, _parent=None, _root=None):
|
|
self._io = _io
|
|
self._parent = _parent
|
|
self._root = _root if _root else self
|
|
self._read()
|
|
|
|
def _read(self):
|
|
self.left = self._io.read_u2le()
|
|
self.top = self._io.read_u2le()
|
|
self.width = self._io.read_u2le()
|
|
self.height = self._io.read_u2le()
|
|
self.flags = self._io.read_u1()
|
|
if self.has_color_table:
|
|
self._raw_local_color_table = self._io.read_bytes((self.color_table_size * 3))
|
|
_io__raw_local_color_table = KaitaiStream(BytesIO(self._raw_local_color_table))
|
|
self.local_color_table = Gif.ColorTable(_io__raw_local_color_table, self, self._root)
|
|
|
|
self.image_data = Gif.ImageData(self._io, self, self._root)
|
|
|
|
@property
|
|
def has_color_table(self):
|
|
if hasattr(self, '_m_has_color_table'):
|
|
return self._m_has_color_table
|
|
|
|
self._m_has_color_table = (self.flags & 128) != 0
|
|
return getattr(self, '_m_has_color_table', None)
|
|
|
|
@property
|
|
def has_interlace(self):
|
|
if hasattr(self, '_m_has_interlace'):
|
|
return self._m_has_interlace
|
|
|
|
self._m_has_interlace = (self.flags & 64) != 0
|
|
return getattr(self, '_m_has_interlace', None)
|
|
|
|
@property
|
|
def has_sorted_color_table(self):
|
|
if hasattr(self, '_m_has_sorted_color_table'):
|
|
return self._m_has_sorted_color_table
|
|
|
|
self._m_has_sorted_color_table = (self.flags & 32) != 0
|
|
return getattr(self, '_m_has_sorted_color_table', None)
|
|
|
|
@property
|
|
def color_table_size(self):
|
|
if hasattr(self, '_m_color_table_size'):
|
|
return self._m_color_table_size
|
|
|
|
self._m_color_table_size = (2 << (self.flags & 7))
|
|
return getattr(self, '_m_color_table_size', None)
|
|
|
|
|
|
class Block(KaitaiStruct):
|
|
def __init__(self, _io, _parent=None, _root=None):
|
|
self._io = _io
|
|
self._parent = _parent
|
|
self._root = _root if _root else self
|
|
self._read()
|
|
|
|
def _read(self):
|
|
self.block_type = KaitaiStream.resolve_enum(Gif.BlockType, self._io.read_u1())
|
|
_on = self.block_type
|
|
if _on == Gif.BlockType.extension:
|
|
self.body = Gif.Extension(self._io, self, self._root)
|
|
elif _on == Gif.BlockType.local_image_descriptor:
|
|
self.body = Gif.LocalImageDescriptor(self._io, self, self._root)
|
|
|
|
|
|
class ColorTable(KaitaiStruct):
|
|
"""
|
|
.. seealso::
|
|
- section 19 - https://www.w3.org/Graphics/GIF/spec-gif89a.txt
|
|
"""
|
|
def __init__(self, _io, _parent=None, _root=None):
|
|
self._io = _io
|
|
self._parent = _parent
|
|
self._root = _root if _root else self
|
|
self._read()
|
|
|
|
def _read(self):
|
|
self.entries = []
|
|
i = 0
|
|
while not self._io.is_eof():
|
|
self.entries.append(Gif.ColorTableEntry(self._io, self, self._root))
|
|
i += 1
|
|
|
|
|
|
|
|
class Header(KaitaiStruct):
|
|
"""
|
|
.. seealso::
|
|
- section 17 - https://www.w3.org/Graphics/GIF/spec-gif89a.txt
|
|
"""
|
|
def __init__(self, _io, _parent=None, _root=None):
|
|
self._io = _io
|
|
self._parent = _parent
|
|
self._root = _root if _root else self
|
|
self._read()
|
|
|
|
def _read(self):
|
|
self.magic = self._io.read_bytes(3)
|
|
if not self.magic == b"\x47\x49\x46":
|
|
raise kaitaistruct.ValidationNotEqualError(b"\x47\x49\x46", self.magic, self._io, u"/types/header/seq/0")
|
|
self.version = (self._io.read_bytes(3)).decode(u"ASCII")
|
|
|
|
|
|
class ExtGraphicControl(KaitaiStruct):
|
|
"""
|
|
.. seealso::
|
|
- section 23 - https://www.w3.org/Graphics/GIF/spec-gif89a.txt
|
|
"""
|
|
def __init__(self, _io, _parent=None, _root=None):
|
|
self._io = _io
|
|
self._parent = _parent
|
|
self._root = _root if _root else self
|
|
self._read()
|
|
|
|
def _read(self):
|
|
self.block_size = self._io.read_bytes(1)
|
|
if not self.block_size == b"\x04":
|
|
raise kaitaistruct.ValidationNotEqualError(b"\x04", self.block_size, self._io, u"/types/ext_graphic_control/seq/0")
|
|
self.flags = self._io.read_u1()
|
|
self.delay_time = self._io.read_u2le()
|
|
self.transparent_idx = self._io.read_u1()
|
|
self.terminator = self._io.read_bytes(1)
|
|
if not self.terminator == b"\x00":
|
|
raise kaitaistruct.ValidationNotEqualError(b"\x00", self.terminator, self._io, u"/types/ext_graphic_control/seq/4")
|
|
|
|
@property
|
|
def transparent_color_flag(self):
|
|
if hasattr(self, '_m_transparent_color_flag'):
|
|
return self._m_transparent_color_flag
|
|
|
|
self._m_transparent_color_flag = (self.flags & 1) != 0
|
|
return getattr(self, '_m_transparent_color_flag', None)
|
|
|
|
@property
|
|
def user_input_flag(self):
|
|
if hasattr(self, '_m_user_input_flag'):
|
|
return self._m_user_input_flag
|
|
|
|
self._m_user_input_flag = (self.flags & 2) != 0
|
|
return getattr(self, '_m_user_input_flag', None)
|
|
|
|
|
|
class Subblock(KaitaiStruct):
|
|
def __init__(self, _io, _parent=None, _root=None):
|
|
self._io = _io
|
|
self._parent = _parent
|
|
self._root = _root if _root else self
|
|
self._read()
|
|
|
|
def _read(self):
|
|
self.len_bytes = self._io.read_u1()
|
|
self.bytes = self._io.read_bytes(self.len_bytes)
|
|
|
|
|
|
class ApplicationId(KaitaiStruct):
|
|
def __init__(self, _io, _parent=None, _root=None):
|
|
self._io = _io
|
|
self._parent = _parent
|
|
self._root = _root if _root else self
|
|
self._read()
|
|
|
|
def _read(self):
|
|
self.len_bytes = self._io.read_u1()
|
|
if not self.len_bytes == 11:
|
|
raise kaitaistruct.ValidationNotEqualError(11, self.len_bytes, self._io, u"/types/application_id/seq/0")
|
|
self.application_identifier = (self._io.read_bytes(8)).decode(u"ASCII")
|
|
self.application_auth_code = self._io.read_bytes(3)
|
|
|
|
|
|
class ExtApplication(KaitaiStruct):
|
|
def __init__(self, _io, _parent=None, _root=None):
|
|
self._io = _io
|
|
self._parent = _parent
|
|
self._root = _root if _root else self
|
|
self._read()
|
|
|
|
def _read(self):
|
|
self.application_id = Gif.ApplicationId(self._io, self, self._root)
|
|
self.subblocks = []
|
|
i = 0
|
|
while True:
|
|
_ = Gif.Subblock(self._io, self, self._root)
|
|
self.subblocks.append(_)
|
|
if _.len_bytes == 0:
|
|
break
|
|
i += 1
|
|
|
|
|
|
class Subblocks(KaitaiStruct):
|
|
def __init__(self, _io, _parent=None, _root=None):
|
|
self._io = _io
|
|
self._parent = _parent
|
|
self._root = _root if _root else self
|
|
self._read()
|
|
|
|
def _read(self):
|
|
self.entries = []
|
|
i = 0
|
|
while True:
|
|
_ = Gif.Subblock(self._io, self, self._root)
|
|
self.entries.append(_)
|
|
if _.len_bytes == 0:
|
|
break
|
|
i += 1
|
|
|
|
|
|
class Extension(KaitaiStruct):
|
|
def __init__(self, _io, _parent=None, _root=None):
|
|
self._io = _io
|
|
self._parent = _parent
|
|
self._root = _root if _root else self
|
|
self._read()
|
|
|
|
def _read(self):
|
|
self.label = KaitaiStream.resolve_enum(Gif.ExtensionLabel, self._io.read_u1())
|
|
_on = self.label
|
|
if _on == Gif.ExtensionLabel.application:
|
|
self.body = Gif.ExtApplication(self._io, self, self._root)
|
|
elif _on == Gif.ExtensionLabel.comment:
|
|
self.body = Gif.Subblocks(self._io, self, self._root)
|
|
elif _on == Gif.ExtensionLabel.graphic_control:
|
|
self.body = Gif.ExtGraphicControl(self._io, self, self._root)
|
|
else:
|
|
self.body = Gif.Subblocks(self._io, self, self._root)
|
|
|
|
|
|
|