3232import struct
3333import board
3434from displayio import Bitmap , Palette , ColorConverter
35- from busdisplay import BusDisplay
35+
3636
3737try :
3838 from typing import Tuple , Optional , Union
3939 from io import BufferedWriter
40+ from busdisplay import BusDisplay
41+ from framebufferio import FramebufferDisplay
4042except ImportError :
4143 pass
4244
@@ -69,10 +71,10 @@ def _bytes_per_row(source_width: int) -> int:
6971
7072
7173def _rotated_height_and_width (
72- pixel_source : Union [Bitmap , BusDisplay ]
74+ pixel_source : Union [Bitmap , BusDisplay , FramebufferDisplay ]
7375) -> Tuple [int , int ]:
7476 # 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 ):
7678 return pixel_source .height , pixel_source .width
7779 return pixel_source .width , pixel_source .height
7880
@@ -114,7 +116,7 @@ def rgb565_to_rgb888(rgb565):
114116# pylint:disable=too-many-locals
115117def _write_pixels (
116118 output_file : BufferedWriter ,
117- pixel_source : Union [Bitmap , BusDisplay ],
119+ pixel_source : Union [Bitmap , BusDisplay , FramebufferDisplay ],
118120 palette : Optional [Union [Palette , ColorConverter ]],
119121) -> None :
120122 saving_bitmap = isinstance (pixel_source , Bitmap )
@@ -139,7 +141,7 @@ def _write_pixels(
139141 color >>= 8
140142 buffer_index += 1
141143 else :
142- # pixel_source: Display
144+ # pixel_source: display
143145 result_buffer = bytearray (2048 )
144146 data = pixel_source .fill_row (y - 1 , result_buffer )
145147 for i in range (width ):
@@ -159,15 +161,17 @@ def _write_pixels(
159161
160162def save_pixels (
161163 file_or_filename : Union [str , BufferedWriter ],
162- pixel_source : Union [BusDisplay , Bitmap ] = None ,
164+ pixel_source : Union [BusDisplay , FramebufferDisplay , Bitmap ] = None ,
163165 palette : Optional [Union [Palette , ColorConverter ]] = None ,
164166) -> None :
165167 """Save pixels to a 24 bit per pixel BMP file.
166168 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`.
168172
169173 :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
171175 :param palette: the Palette to use for looking up colors in the bitmap
172176 """
173177 if not pixel_source :
@@ -180,8 +184,8 @@ def save_pixels(
180184 raise ValueError (
181185 "Third argument must be a Palette or ColorConverter for a Bitmap save"
182186 )
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 " )
185189 try :
186190 if isinstance (file_or_filename , str ):
187191 output_file = open ( # pylint: disable=consider-using-with
0 commit comments