@@ -103,15 +103,80 @@ def load(
103
103
file .seek (size , 1 ) # skip unknown chunks
104
104
file .seek (4 , 1 ) # skip CRC
105
105
data_bytes = zlib .decompress (data )
106
- bmp = bitmap (width , height , 1 << depth )
107
- scanline = (width * depth + 7 ) // 8
108
- mem = memoryview (bmp )
106
+ unit = (1 , 0 , 3 , 1 , 2 , 0 , 4 )[mode ]
107
+ scanline = (width * depth * unit + 7 ) // 8
108
+ colors = 1 << (depth * unit )
109
+ if mode == 3 : # indexed
110
+ bmp = bitmap (width , height , colors )
111
+ mem = memoryview (bmp )
112
+ for y in range (height ):
113
+ dst = y * scanline
114
+ src = y * (scanline + 1 ) + 1
115
+ mem [dst : dst + scanline ] = data_bytes [src : src + scanline ]
116
+ return bmp , pal
117
+ # RGB, RGBA or Grayscale
118
+ import displayio
119
+
120
+ if depth != 8 :
121
+ raise ValueError ("Must be 8bit depth." )
122
+ pal = displayio .ColorConverter (input_colorspace = displayio .Colorspace .RGB888 )
123
+ bmp = bitmap (width , height , 65536 )
124
+ prev = bytearray (scanline )
125
+ line = bytearray (scanline )
109
126
for y in range (height ):
110
- dst = y * scanline
111
- src = y * ( scanline + 1 ) + 1
112
- filter_ = data_bytes [ src - 1 ]
127
+ src = y * ( scanline + 1 )
128
+ filter_ = data_bytes [ src ]
129
+ src += 1
113
130
if filter_ == 0 :
114
- mem [dst : dst + scanline ] = data_bytes [src : src + scanline ]
131
+ line [0 :scanline ] = data_bytes [src : src + scanline ]
132
+ elif filter_ == 1 : # sub
133
+ for i in range (scanline ):
134
+ a = line [i - unit ] if i >= unit else 0
135
+ line [i ] = (data_bytes [src ] + a ) & 0xFF
136
+ src += 1
137
+ elif filter_ == 2 : # up
138
+ for i in range (scanline ):
139
+ b = prev [i ]
140
+ line [i ] = (data_bytes [src ] + b ) & 0xFF
141
+ src += 1
142
+ elif filter_ == 3 : # average
143
+ for i in range (scanline ):
144
+ a = line [i - unit ] if i >= unit else 0
145
+ b = prev [i ]
146
+ line [i ] = (data_bytes [src ] + ((a + b ) >> 1 )) & 0xFF
147
+ src += 1
148
+ elif filter_ == 4 : # paeth
149
+ for i in range (scanline ):
150
+ a = line [i - unit ] if i >= unit else 0
151
+ b = prev [i ]
152
+ c = prev [i - unit ] if i >= unit else 0
153
+ p = a + b - c
154
+ pa = abs (p - a )
155
+ pb = abs (p - b )
156
+ pc = abs (p - c )
157
+ if pa <= pb and pa <= pc :
158
+ p = a
159
+ elif pb <= pc :
160
+ p = b
161
+ else :
162
+ p = c
163
+ line [i ] = (data_bytes [src ] + p ) & 0xFF
164
+ src += 1
165
+ else :
166
+ raise ValueError ("Wrong filter." )
167
+ prev , line = line , prev
168
+ if mode in (0 , 4 ): # grayscale
169
+ for x in range (width ):
170
+ c = line [x * unit ]
171
+ bmp [x , y ] = pal .convert ((c << 16 ) | (c << 8 ) | c )
172
+ elif mode in {2 , 6 }: # rgb
173
+ for x in range (width ):
174
+ bmp [x , y ] = pal .convert (
175
+ (line [x * unit + 0 ] << 16 )
176
+ | (line [x * unit + 1 ] << 8 )
177
+ | line [x * unit + 2 ]
178
+ )
115
179
else :
116
- raise NotImplementedError ("Filters not supported" )
180
+ raise ValueError ("Unsupported color mode." )
181
+ pal = displayio .ColorConverter (input_colorspace = displayio .Colorspace .RGB565 )
117
182
return bmp , pal
0 commit comments