-
Notifications
You must be signed in to change notification settings - Fork 11
Expand file tree
/
Copy pathgif.py
More file actions
156 lines (139 loc) · 6.67 KB
/
Copy pathgif.py
File metadata and controls
156 lines (139 loc) · 6.67 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
""" GIF file parse script for IceBuddha.com
"""
import icebuddha
__author__ = "0xdabbad00"
__license__ = "Apache"
class Parser:
def run(self, data):
filedata = data
ib = icebuddha.IceBuddha(filedata, "GIF")
RGB = """
BYTE R;
BYTE G;
BYTE B;
"""
gifHeader = ib.parse(0, "GIFHEADER", """
CHAR Signature[3];
CHAR Version[3];
""")
if (gifHeader.findChild("Signature").getValue() != "GIF"):
print "File is not a gif"
return []
ib.append(gifHeader)
lsd = ib.parse(gifHeader.end(), "LOGICAL_SCREEN_DESCRIPTOR", """
WORD Width;
WORD Height;
BYTE GlobalColorTable;
BYTE BackgroundColorIndex;
BYTE PixelAspectRatio;
""")
gct = lsd.findChild("GlobalColorTable")
gct.parseBitField("""
BYTE SizeOfGlobalColorTable : 3;
BYTE SortFlag : 1;
BYTE ColorResolution : 3;
BYTE GlobalColorTableFlag : 1;
""")
GlobalColorTableFlag = gct.getData() & 1
if (GlobalColorTableFlag == 1):
SizeOfGlobalColorTable = (gct.getData() & 7)
SizeOfGlobalColorTable = 1 << (SizeOfGlobalColorTable + 1)
ColorTable = ib.parse(lsd.end(), "ColorTable RGB[%d]" % SizeOfGlobalColorTable, "")
for i in range(SizeOfGlobalColorTable):
color = ib.parse(ColorTable.end(), "RGB /* " + str(i) + " */", RGB)
ColorTable.append(color)
lsd.append(ColorTable)
ib.append(lsd)
offset = lsd.end()
Data = ib.parse(offset, "Data", "")
while (not ib.isEqual(offset, [0x3B]) and offset < len(filedata)):
if (ib.isEqual(offset, [0x2C])):
imgDescriptor = ib.parse(offset, "IMAGE_DESCRIPTOR", """
BYTE ImageSeperator;
WORD Left;
WORD Top;
WORD Width;
WORD Height;
BYTE PackedField;
""")
imgDescriptorPackedField = imgDescriptor.findChild("PackedField")
imgDescriptorPackedField.parseBitField("""
BYTE SizeOfLocalColorTable : 3;
BYTE Reserved : 2;
BYTE SortFlag : 1;
BYTE InterlaceFlag : 1;
BYTE LocalColorTableFlag : 1;
""")
Data.append(imgDescriptor)
LocalColorTableFlag = imgDescriptorPackedField.getData() & 1
if (LocalColorTableFlag == 1):
SizeOfLocalColorTable = (imgDescriptorPackedField.getData() & 7)
SizeOfLocalColorTable = 1 << (SizeOfLocalColorTable + 1)
ColorTable = ib.parse(imgDescriptor.end(), "ColorTable RGB[%d]" % SizeOfLocalColorTable, "")
for i in range(SizeOfLocalColorTable):
color = ib.parse(ColorTable.end(), "RGB /* " + str(i) + " */", RGB)
ColorTable.append(color)
Data.append(ColorTable)
imgData = ib.parse(Data.end(), "IMAGE_DATA", "BYTE LZWMinimumCodeSize;")
self.getDataSubBlocks(filedata, ib, imgData)
Data.append(imgData)
elif (ib.isEqual(offset, [0x21, 0xF9])):
Data.append(ib.parse(offset, "GraphicsControlExtension", """
BYTE Introducer; /* Extension Introducer (always 21h) */
BYTE Label; /* Graphic Control Label (always F9h) */
BYTE BlockSize; /* Size of remaining fields (always 04h) */
BYTE Packed; /* Method of graphics disposal to use */
WORD DelayTime; /* Hundredths of seconds to wait */
BYTE ColorIndex; /* Transparent Color Index */
BYTE Terminator; /* Block Terminator (always 0) */
"""))
# TODO Handle Packed field
elif (ib.isEqual(offset, [0x21, 0xFE])):
commentExtension = ib.parse(filedata, offset, "CommentExtension", """
BYTE ExtensionIntroducer;
BYTE CommentLabel;
""")
self.getDataSubBlocks(filedata, ib, commentExtension)
Data.append(commentExtension)
elif (ib.isEqual(offset, [0x21, 0x01])):
plainTextExtension = ib.parse(filedata, offset, "PlainTextExtension", """
BYTE Introducer; /* Extension Introducer (always 21h) */
BYTE Label; /* Extension Label (always 01h) */
BYTE BlockSize; /* Size of Extension Block (always 0Ch) */
WORD TextGridLeft; /* X position of text grid in pixels */
WORD TextGridTop; /* Y position of text grid in pixels */
WORD TextGridWidth; /* Width of the text grid in pixels */
WORD TextGridHeight; /* Height of the text grid in pixels */
BYTE CellWidth; /* Width of a grid cell in pixels */
BYTE CellHeight; /* Height of a grid cell in pixels */
BYTE TextFgColorIndex; /* Text foreground color index value */
BYTE TextBgColorIndex; /* Text background color index value */
BYTE PlainTextData; /* The Plain Text data */
BYTE Terminator; /* Block Terminator (always 0) */
""")
# TODO Handle PlainTextData
Data.append(plainTextExtension)
elif (ib.isEqual(offset, [0xFF])):
applicationExtension = ib.parse(filedata, offset, "ApplicationExtension", """
BYTE BlockSize;
BYTE ApplicationIdentifier[8];
BYTE ApplicationAuthenticationCode[3];
""")
Data.append(applicationExtension)
else:
print "Undefined data at %d" % offset
break
offset = Data.end()
ib.append(Data)
ib.append(ib.parse(Data.end(), "TRAILER", "BYTE GIFTrailer;"))
return ib.getParseTree()
def getDataSubBlocks(self, filedata, ib, struct):
size = 1
while (size != 0):
size = filedata[struct.end()]
subBlock = ib.parse(struct.end(), "SUBBLOCK", """
BYTE Size;
BYTE Data[%d];
""" % size)
struct.append(subBlock)
parser = Parser()