@@ -49,7 +49,7 @@ def load(
4949 :param object palette: Type to store the palette. Must have API similar to
5050 `displayio.Palette`. Will be skipped if None.
5151 """
52- # pylint: disable=too-many-locals,too-many-branches, consider-using-enumerate, too-many-statements
52+ # pylint: disable=too-many-locals, too-many-branches, consider-using-enumerate, too-many-statements, import-outside-toplevel, invalid-name
5353 header = file .read (8 )
5454 if header != b"\x89 PNG\r \n \x1a \n " :
5555 raise ValueError ("Not a PNG file" )
@@ -103,15 +103,80 @@ def load(
103103 file .seek (size , 1 ) # skip unknown chunks
104104 file .seek (4 , 1 ) # skip CRC
105105 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 )
109126 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
113130 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+ )
115179 else :
116- raise NotImplementedError ("Filters not supported" )
180+ raise ValueError ("Unsupported color mode." )
181+ pal = displayio .ColorConverter (input_colorspace = displayio .Colorspace .RGB565 )
117182 return bmp , pal
0 commit comments