3131import numpy as np
3232from PIL import Image
3333
34- _BACKGROUND_RGBA = [255 , 255 , 255 , 255 ]
34+ _BACKGROUND_RGBA = np .array ([255 , 255 , 255 , 255 ])
35+ _BACKGROUND_RGBA .flags .writeable = False
3536_HEADER_LENGTH = 6 * 4
3637
3738
@@ -46,6 +47,7 @@ def encode(image):
4647 """
4748 im = image .convert ('RGBA' )
4849 pixel_words = np .array (im ).reshape (- 1 , 4 )
50+ pixel_words .flags .writeable = False
4951
5052 colormap = list (filter (lambda x : not np .all (x == _BACKGROUND_RGBA ),
5153 np .unique (pixel_words , axis = 0 )))
@@ -55,14 +57,34 @@ def encode(image):
5557 buff = BytesIO (bytes ([0 ] * (len (colormap ) * 4 + input_byte_len )))
5658
5759 offset = _HEADER_LENGTH # make room for header
58- for color in colormap :
60+
61+ def _color_to_key (color ):
62+ return hash (color .tostring ())
63+
64+ color_dict = dict ()
65+ for i , color in enumerate (colormap ):
66+ color .flags .writeable = False
5967 struct .pack_into ('<BBBB' , buff .getbuffer (), offset , * color )
68+ color_dict [_color_to_key (color )] = i
6069 offset += 4
70+ color_dict [_color_to_key (_BACKGROUND_RGBA )] = i + 1
71+
72+ count = 0
73+ pixel_ints = np .apply_along_axis (_color_to_key , 1 , pixel_words )
74+ for i in range (len (pixel_ints )):
75+ count += 1
76+ if i + 1 == len (pixel_ints ) \
77+ or not pixel_ints [i ] == pixel_ints [i + 1 ] \
78+ or count > 65534 :
79+ struct .pack_into ('<HH' , buff .getbuffer (), offset ,
80+ color_dict [pixel_ints [i ]], count )
81+ offset += 4
82+ count = 0
6183
6284 # write header
6385 struct .pack_into ('<iiiiii' , buff .getbuffer (), 0 ,
6486 1 , im .width , im .height , input_byte_len , len (colormap ),
65- offset - len (colormap ) - _HEADER_LENGTH )
87+ offset - len (colormap )* 4 - _HEADER_LENGTH )
6688
6789 return buff
6890
0 commit comments