summaryrefslogtreecommitdiff
path: root/external/construct/formats/graphics/gif.py
diff options
context:
space:
mode:
Diffstat (limited to 'external/construct/formats/graphics/gif.py')
-rw-r--r--external/construct/formats/graphics/gif.py151
1 files changed, 151 insertions, 0 deletions
diff --git a/external/construct/formats/graphics/gif.py b/external/construct/formats/graphics/gif.py
new file mode 100644
index 0000000..fa50150
--- /dev/null
+++ b/external/construct/formats/graphics/gif.py
@@ -0,0 +1,151 @@
+# Contributed by
+# Dany Zatuchna (danzat at gmail)
+""" Implementation of the following grammar for the GIF89a file format
+<GIF Data Stream> ::= Header <Logical Screen> <Data>* Trailer
+
+<Logical Screen> ::= Logical Screen Descriptor [Global Color Table]
+
+<Data> ::= <Graphic Block> |
+ <Special-Purpose Block>
+
+<Graphic Block> ::= [Graphic Control Extension] <Graphic-Rendering Block>
+
+<Graphic-Rendering Block> ::= <Table-Based Image> |
+ Plain Text Extension
+
+<Table-Based Image> ::= Image Descriptor [Local Color Table] Image Data
+
+<Special-Purpose Block> ::= Application Extension |
+ Comment Extension
+"""
+from construct import *
+import six
+
+
+data_sub_block = Struct("data_sub_block",
+ ULInt8("size"),
+ String("data", lambda ctx: ctx["size"])
+)
+
+gif_logical_screen = Struct("logical_screen",
+ ULInt16("width"),
+ ULInt16("height"),
+ BitStruct("flags",
+ Bit("global_color_table"),
+ BitField("color_resolution", 3),
+ Bit("sort_flag"),
+ BitField("global_color_table_bpp", 3)
+ ),
+ ULInt8("bgcolor_index"),
+ ULInt8("pixel_aspect_ratio"),
+ If(lambda ctx: ctx["flags"]["global_color_table"],
+ Array(lambda ctx: 2**(ctx["flags"]["global_color_table_bpp"] + 1),
+ Struct("palette",
+ ULInt8("R"),
+ ULInt8("G"),
+ ULInt8("B")
+ )
+ )
+ )
+)
+
+gif_header = Struct("gif_header",
+ Const(String("signature", 3), six.b("GIF")),
+ Const(String("version", 3), six.b("89a")),
+)
+
+application_extension = Struct("application_extension",
+ Const(ULInt8("block_size"), 11),
+ String("application_identifier", 8),
+ String("application_auth_code", 3),
+ data_sub_block,
+ ULInt8("block_terminator")
+)
+
+comment_extension = Struct("comment_extension",
+ data_sub_block,
+ ULInt8("block_terminator")
+)
+
+graphic_control_extension = Struct("graphic_control_extension",
+ Const(ULInt8("block_size"), 4),
+ BitStruct("flags",
+ BitField("reserved", 3),
+ BitField("disposal_method", 3),
+ Bit("user_input_flag"),
+ Bit("transparent_color_flag"),
+ ),
+ ULInt16("delay"),
+ ULInt8("transparent_color_index"),
+ ULInt8("block_terminator")
+)
+
+plain_text_extension = Struct("plain_text_extension",
+ Const(ULInt8("block_size"), 12),
+ ULInt16("text_left"),
+ ULInt16("text_top"),
+ ULInt16("text_width"),
+ ULInt16("text_height"),
+ ULInt8("cell_width"),
+ ULInt8("cell_height"),
+ ULInt8("foreground_index"),
+ ULInt8("background_index"),
+ data_sub_block,
+ ULInt8("block_terminator")
+)
+
+extension = Struct("extension",
+ ULInt8("label"),
+ Switch("ext", lambda ctx: ctx["label"], {
+ 0xFF: application_extension,
+ 0xFE: comment_extension,
+ 0xF9: graphic_control_extension,
+ 0x01: plain_text_extension
+ })
+)
+
+image_descriptor = Struct("image_descriptor",
+ ULInt16("left"),
+ ULInt16("top"),
+ ULInt16("width"),
+ ULInt16("height"),
+ BitStruct("flags",
+ Bit("local_color_table"),
+ Bit("interlace"),
+ Bit("sort"),
+ BitField("reserved", 2),
+ BitField("local_color_table_bpp", 3)
+ ),
+ If(lambda ctx: ctx["flags"]["local_color_table"],
+ Array(lambda ctx: 2**(ctx["flags"]["local_color_table_bpp"] + 1),
+ Struct("palette",
+ ULInt8("R"),
+ ULInt8("G"),
+ ULInt8("B")
+ )
+ )
+ ),
+ ULInt8("LZW_minimum_code_size"),
+ RepeatUntil(lambda obj, ctx: obj.size == 0, data_sub_block)
+)
+
+gif_data = Struct("gif_data",
+ ULInt8("introducer"),
+ Switch("dat", lambda ctx: ctx["introducer"], {
+ 0x21: extension,
+ 0x2C: image_descriptor
+ })
+)
+
+gif_file = Struct("gif_file",
+ gif_header,
+ gif_logical_screen,
+ OptionalGreedyRange(gif_data),
+ #Const(ULInt8("trailer"), 0x3B)
+)
+
+if __name__ == "__main__":
+ f = open("../../../tests/sample.gif", "rb")
+ s = f.read()
+ f.close()
+ print(gif_file.parse(s))