32
32
import struct
33
33
import board
34
34
from displayio import Bitmap , Palette , ColorConverter
35
- from busdisplay import BusDisplay
35
+
36
36
37
37
try :
38
38
from typing import Tuple , Optional , Union
39
39
from io import BufferedWriter
40
+ from busdisplay import BusDisplay
41
+ from framebufferio import FramebufferDisplay
40
42
except ImportError :
41
43
pass
42
44
@@ -69,10 +71,10 @@ def _bytes_per_row(source_width: int) -> int:
69
71
70
72
71
73
def _rotated_height_and_width (
72
- pixel_source : Union [Bitmap , BusDisplay ]
74
+ pixel_source : Union [Bitmap , BusDisplay , FramebufferDisplay ]
73
75
) -> Tuple [int , int ]:
74
76
# flip axis if the display is rotated
75
- if isinstance (pixel_source , BusDisplay ) and (pixel_source .rotation % 180 != 0 ):
77
+ if hasattr (pixel_source , "rotation" ) and (pixel_source .rotation % 180 != 0 ):
76
78
return pixel_source .height , pixel_source .width
77
79
return pixel_source .width , pixel_source .height
78
80
@@ -114,7 +116,7 @@ def rgb565_to_rgb888(rgb565):
114
116
# pylint:disable=too-many-locals
115
117
def _write_pixels (
116
118
output_file : BufferedWriter ,
117
- pixel_source : Union [Bitmap , BusDisplay ],
119
+ pixel_source : Union [Bitmap , BusDisplay , FramebufferDisplay ],
118
120
palette : Optional [Union [Palette , ColorConverter ]],
119
121
) -> None :
120
122
saving_bitmap = isinstance (pixel_source , Bitmap )
@@ -139,7 +141,7 @@ def _write_pixels(
139
141
color >>= 8
140
142
buffer_index += 1
141
143
else :
142
- # pixel_source: Display
144
+ # pixel_source: display
143
145
result_buffer = bytearray (2048 )
144
146
data = pixel_source .fill_row (y - 1 , result_buffer )
145
147
for i in range (width ):
@@ -159,15 +161,17 @@ def _write_pixels(
159
161
160
162
def save_pixels (
161
163
file_or_filename : Union [str , BufferedWriter ],
162
- pixel_source : Union [BusDisplay , Bitmap ] = None ,
164
+ pixel_source : Union [BusDisplay , FramebufferDisplay , Bitmap ] = None ,
163
165
palette : Optional [Union [Palette , ColorConverter ]] = None ,
164
166
) -> None :
165
167
"""Save pixels to a 24 bit per pixel BMP file.
166
168
If pixel_source if a displayio.Bitmap, save it's pixels through palette.
167
- If it's a displayio.Display, a palette isn't required.
169
+ If it's a displayio display, a palette isn't required. To be supported,
170
+ a display must implement `busdisplay.BusDisplay.fill_row`. Known supported
171
+ display types are `busdisplay.BusDisplay` and `framebufferio.FramebufferDisplay`.
168
172
169
173
:param file_or_filename: either the file to save to, or it's absolute name
170
- :param pixel_source: the Bitmap or Display to save
174
+ :param pixel_source: the Bitmap or display to save
171
175
:param palette: the Palette to use for looking up colors in the bitmap
172
176
"""
173
177
if not pixel_source :
@@ -180,8 +184,8 @@ def save_pixels(
180
184
raise ValueError (
181
185
"Third argument must be a Palette or ColorConverter for a Bitmap save"
182
186
)
183
- elif not isinstance (pixel_source , BusDisplay ):
184
- raise ValueError ("Second argument must be a Bitmap or Display " )
187
+ elif not hasattr (pixel_source , "fill_row" ):
188
+ raise ValueError ("Second argument must be a Bitmap or supported display type " )
185
189
try :
186
190
if isinstance (file_or_filename , str ):
187
191
output_file = open ( # pylint: disable=consider-using-with
0 commit comments