23
23
`adafruit_bitmapsaver`
24
24
================================================================================
25
25
26
- Save a displayio.Bitmap (and associated displayio.Palette) into a BMP file.
26
+ Save a displayio.Bitmap (and associated displayio.Palette) in a BMP file.
27
+ Make a screenshot (the contents of a displayio.Display) and save in a BMP file.
27
28
28
29
29
30
* Author(s): Dave Astels
43
44
44
45
# imports
45
46
47
+ import gc
46
48
import struct
47
- from displayio import Bitmap , Palette
49
+ import board
50
+ from displayio import Bitmap , Palette , Display
48
51
49
52
__version__ = "0.0.0-auto.0"
50
53
__repo__ = "https://github.com/adafruit/Adafruit_CircuitPython_BitmapSaver.git"
@@ -58,53 +61,72 @@ def _write_bmp_header(output_file, filesize):
58
61
output_file .write (b'\00 \x00 ' )
59
62
output_file .write (struct .pack ('<I' , 54 ))
60
63
61
- def _write_dib_header (output_file , bitmap ):
64
+ def _write_dib_header (output_file , pixel_source ):
62
65
output_file .write (struct .pack ('<I' , 40 ))
63
- output_file .write (struct .pack ('<I' , bitmap .width ))
64
- output_file .write (struct .pack ('<I' , bitmap .height ))
66
+ output_file .write (struct .pack ('<I' , pixel_source .width ))
67
+ output_file .write (struct .pack ('<I' , pixel_source .height ))
65
68
output_file .write (struct .pack ('<H' , 1 ))
66
69
output_file .write (struct .pack ('<H' , 24 ))
67
70
output_file .write (b'\x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 ' )
68
71
69
- def _bytes_per_row (bitmap ):
70
- pixel_bytes = 3 * bitmap .width
72
+ def _bytes_per_row (pixel_source ):
73
+ pixel_bytes = 3 * pixel_source .width
71
74
padding_bytes = (4 - (pixel_bytes % 4 )) % 4
72
75
return pixel_bytes + padding_bytes
73
76
74
- def _write_pixels (output_file , bitmap , palette ):
75
- row_buffer = bytearray (_bytes_per_row (bitmap ))
77
+ def rgb565_to_bgr_tuple (color ):
78
+ blue = (color << 3 ) & 0x00F8 # extract each of the RGB tripple into it's own byte
79
+ green = (color >> 3 ) & 0x00FC
80
+ red = (color >> 8 ) & 0x00F8
81
+ return (blue , green , red )
76
82
77
- for y in range (bitmap .height , 0 , - 1 ):
83
+ def _write_pixels (output_file , pixel_source , palette ):
84
+ row_buffer = bytearray (_bytes_per_row (pixel_source ))
85
+ saving_bitmap = isinstance (pixel_source , Bitmap )
86
+ for y in range (pixel_source .height , 0 , - 1 ):
78
87
buffer_index = 0
79
- for x in range (bitmap .width ):
80
- pixel = bitmap [x , y - 1 ]
81
- color = palette [pixel ]
82
- for _ in range (3 ):
83
- row_buffer [buffer_index ] = color & 0xFF
84
- color >>= 8
85
- buffer_index += 1
88
+ if saving_bitmap :
89
+ for x in range (pixel_source .width ):
90
+ pixel = pixel_source [x , y - 1 ]
91
+ color = palette [pixel ]
92
+ for _ in range (3 ):
93
+ row_buffer [buffer_index ] = color & 0xFF
94
+ color >>= 8
95
+ buffer_index += 1
96
+ else :
97
+ data = pixel_source .fill_area (x = 0 , y = y - 1 , width = pixel_source .width , height = 1 )
98
+ for i in range (pixel_source .width ):
99
+ pixel565 = (data [i * 2 ] << 8 ) + data [i * 2 + 1 ]
100
+ for b in rgb565_to_bgr_tuple (pixel565 ):
101
+ row_buffer [buffer_index ] = b & 0xFF
102
+ buffer_index += 1
86
103
output_file .write (row_buffer )
104
+ gc .collect ()
87
105
88
- def save_bitmap (bitmap , palette , file_or_filename ):
89
- """Save a bitmap (using an associated palette) to a 24 bit per pixel BMP file.
106
+ def save_pixels (file_or_filename , pixel_source = board .DISPLAY , palette = None ):
107
+ """Save pixels to a 24 bit per pixel BMP file.
108
+ If pixel_source if a displayio.Bitmap, save it's pixels through palette.
109
+ If it's a displayio.Display, a palette isn't required.
90
110
91
- :param bitmap: the displayio.Bitmap to save
92
- :param palette: the displayio.Palette to use for looking up colors in the bitmap
111
+ :param file_or_filename: either the file to save to, or it's absolute name
112
+ :param pixel_source: the Bitmap or Display to save
113
+ :param palette: the Palette to use for looking up colors in the bitmap
93
114
"""
94
- if not isinstance (bitmap , Bitmap ):
95
- raise ValueError ('First argument must be a Bitmap' )
96
- if not isinstance (palette , Palette ):
97
- raise ValueError ('Second argument must be a Palette' )
115
+ if isinstance (pixel_source , Bitmap ):
116
+ if not isinstance (palette , Palette ):
117
+ raise ValueError ('Third argument must be a Palette for a Bitmap save' )
118
+ elif not isinstance (pixel_source , Display ):
119
+ raise ValueError ('Second argument must be a Bitmap or Display' )
98
120
try :
99
121
if isinstance (file_or_filename , str ):
100
122
output_file = open (file_or_filename , 'wb' )
101
123
else :
102
124
output_file = file_or_filename
103
125
104
- filesize = 54 + bitmap .height * _bytes_per_row (bitmap )
126
+ filesize = 54 + pixel_source .height * _bytes_per_row (pixel_source )
105
127
_write_bmp_header (output_file , filesize )
106
- _write_dib_header (output_file , bitmap )
107
- _write_pixels (output_file , bitmap , palette )
128
+ _write_dib_header (output_file , pixel_source )
129
+ _write_pixels (output_file , pixel_source , palette )
108
130
except Exception :
109
131
raise
110
132
else :
0 commit comments