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