3636__version__ = "0.0.0-auto.0"
3737__repo__ = "https://github.com/adafruit/Adafruit_CircuitPython_ImageLoad.git"
3838
39+
3940def load (file , * , bitmap = None , palette = None ):
4041 """Loads a GIF image from the open ``file``.
4142
@@ -48,7 +49,7 @@ def load(file, *, bitmap=None, palette=None):
4849 header = file .read (6 )
4950 if header not in {b'GIF87a' , b'GIF89a' }:
5051 raise ValueError ("Not a GIF file" )
51- w , h , flags , background , aspect = struct .unpack ('<HHBBB' , file .read (7 ))
52+ width , height , flags , _ , _ = struct .unpack ('<HHBBB' , file .read (7 ))
5253 if (flags & 0x80 ) != 0 :
5354 palette_size = 1 << ((flags & 0x07 ) + 1 )
5455 palette_obj = palette (palette_size )
@@ -57,70 +58,75 @@ def load(file, *, bitmap=None, palette=None):
5758 else :
5859 palette_obj = None
5960 color_bits = ((flags & 0x70 ) >> 4 ) + 1
60- bitmap_obj = bitmap (w , h , (1 << color_bits ) - 1 )
61+ bitmap_obj = bitmap (width , height , (1 << color_bits ) - 1 )
6162 while True :
6263 block_type = file .read (1 )[0 ]
6364 if block_type == 0x2c : # frame
64- dx , dy , frame_w , frame_h , flags = struct .unpack ('<HHHHB' ,
65- file .read (9 ))
66- if (flags & 0x40 ) != 0 :
67- raise NotImplementedError ("Interlacing not supported" )
68- if (flags & 0x80 ) != 0 :
69- palette_size = 1 << ((flags & 0x07 ) + 1 )
70- frame_palette = palette (palette_size )
71- for i in range (palette_size ):
72- frame_palette [i ] = file .read (3 )
73- if palette_obj is None :
74- # if there is no global palette, use local one
75- palette_obj = frame_palette
76- min_code_size = file .read (1 )[0 ]
77- x = 0
78- y = 0
79- for decoded in lzw_decode (_read_blockstream (file ), min_code_size ):
80- for byte in decoded :
81- bitmap_obj [dx + x , dy + y ] = byte
82- x += 1
83- if x >= frame_w :
84- x = 0
85- y += 1
65+ _read_frame (file , bitmap_obj )
8666 elif block_type == 0x21 : # extension
87- extension_type = file .read (1 )[0 ]
67+ _ = file .read (1 )[0 ]
8868 # 0x01 = label, 0xfe = comment
89- data = bytes (_read_blockstream (file ))
69+ _ = bytes (_read_blockstream (file ))
9070 elif block_type == 0x3b : # terminator
9171 break
9272 else :
9373 raise ValueError ("Bad block type" )
9474 return bitmap_obj , palette_obj
9575
9676
97- def _read_blockstream (f ):
77+ def _read_frame (file , bitmap ):
78+ """Read a signle frame and apply it to the bitmap."""
79+ ddx , ddy , width , _ , flags = struct .unpack ('<HHHHB' , file .read (9 ))
80+ if (flags & 0x40 ) != 0 :
81+ raise NotImplementedError ("Interlacing not supported" )
82+ if (flags & 0x80 ) != 0 :
83+ palette_size = 1 << ((flags & 0x07 ) + 1 )
84+ for _ in range (palette_size ):
85+ _ = file .read (3 )
86+ min_code_size = file .read (1 )[0 ]
87+ x = 0
88+ y = 0
89+ for decoded in lzw_decode (_read_blockstream (file ), min_code_size ):
90+ for byte in decoded :
91+ bitmap [ddx + x , ddy + y ] = byte
92+ x += 1
93+ if x >= width :
94+ x = 0
95+ y += 1
96+
97+
98+ def _read_blockstream (file ):
99+ """Read a block from a file."""
98100 while True :
99- size = f .read (1 )[0 ]
101+ size = file .read (1 )[0 ]
100102 if size == 0 :
101103 break
102- for i in range (size ):
103- yield f .read (1 )[0 ]
104+ for _ in range (size ):
105+ yield file .read (1 )[0 ]
104106
105107
106108class EndOfData (Exception ):
107- pass
109+ """Signified end of compressed data."""
108110
109111
110112class LZWDict :
113+ """A dictionary of LZW codes."""
111114 def __init__ (self , code_size ):
112115 self .code_size = code_size
113116 self .clear_code = 1 << code_size
114117 self .end_code = self .clear_code + 1
115118 self .codes = []
119+ self .last = None
116120 self .clear ()
117121
118122 def clear (self ):
123+ """Reset the dictionary to default codes."""
119124 self .last = b''
120125 self .code_len = self .code_size + 1
121126 self .codes [:] = []
122127
123128 def decode (self , code ):
129+ """Decode a code."""
124130 if code == self .clear_code :
125131 self .clear ()
126132 return b''
@@ -135,16 +141,17 @@ def decode(self, code):
135141 if self .last :
136142 self .codes .append (self .last + value [0 :1 ])
137143 if (len (self .codes ) + self .end_code + 1 >= 1 << self .code_len and
138- self .code_len < 12 ):
139- self .code_len += 1
144+ self .code_len < 12 ):
145+ self .code_len += 1
140146 self .last = value
141147 return value
142148
143149
144150def lzw_decode (data , code_size ):
151+ """Decode LZW-compressed data."""
145152 dictionary = LZWDict (code_size )
146153 bit = 0
147- byte = next (data )
154+ byte = next (data ) # pylint: disable=stop-iteration-return
148155 try :
149156 while True :
150157 code = 0
@@ -153,8 +160,8 @@ def lzw_decode(data, code_size):
153160 bit += 1
154161 if bit >= 8 :
155162 bit = 0
156- byte = next (data )
163+ byte = next (data ) # pylint: disable=stop-iteration-return
157164 yield dictionary .decode (code )
158165 except EndOfData :
159166 while True :
160- next (data )
167+ next (data ) # pylint: disable=stop-iteration-return
0 commit comments