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