When CircuitPython starts up, the internal flash filesystem is read only. If you want to save bitmaps or screenshots to it, you must remount it as writable by creating a boot.py file with the following in it:
import storage storage.remount("/", False)
The catch is that it can only be writable by the MCU or USB. The common solution to this is to check an input to see which should be able to write it. Something like:
import board import digitalio import storage switch = digitalio.DigitalInOut(board.D0) switch.direction = digitalio.Direction.INPUT switch.pull = digitalio.Pull.UP # If the D0 is connected to ground with a wire # CircuitPython can write to the drive storage.remount("/", switch.value)
SD Card Support
Setting up the SD card for use is shown below. From then on files can be saved to files in the /sd directory.
import board import busio import storage spi = busio.SPI(board.SCK, MOSI=board.MOSI, MISO=board.MISO) try: import sdcardio sdcard = sdcardio.SDCard(spi, board.SD_CS) except ImportError: import adafruit_sdcard import digitalio cs = digitalio.DigitalInOut(board.SD_CS) sd_card = adafruit_sdcard.SDCard(spi, cs) vfs = storage.VfsFat(sdcard) storage.mount(vfs, "/sd")
Taking a Screenshot
This can be as simple as importing the library and calling the save_pixels()
function with an argument of either a file object or an absolute filename. The example below configures the SD card support and saves a screenshot onto the card.
If a file object is passed, it is written to. If a filename is passed, the named file is opened for writing and written to. In either case, the file is closed once the screenshot has been written.
import board import busio import storage from adafruit_bitmapsaver import save_pixels spi = busio.SPI(board.SCK, MOSI=board.MOSI, MISO=board.MISO) try: import sdcardio sdcard = sdcardio.SDCard(spi, board.SD_CS) except ImportError: import adafruit_sdcard import digitalio cs = digitalio.DigitalInOut(board.SD_CS) sd_card = adafruit_sdcard.SDCard(spi, cs) vfs = storage.VfsFat(sdcard) storage.mount(vfs, "/sd") print('Taking Screenshot...') save_pixels('/sd/screenshot.bmp') print('Screenshot taken')
Handling rotation
A wrinkle with taking screenshots is that some boards use a rotated buffer and some don't. The library takes this into account. On some boards, e.g. the PyPortal, the screenshot will be oriented as expected (shown at the top of this page).
However, on some otherboards, e.g. the PyGamer, it will be rotated 90 degrees. This can be correctly with any image editing software.
Saving a Bitmap
Saving a bitmap is only slightly more involved than saving a screenshot.
A file or filename is passed and used in the same way.
Since this saves the contents of a Bitmap
object and not the contents of the screen, that Bitmap
must be passed as well. Furthermore, Bitmaps
don't contain the actual 24-bit color that ends up on the screen. Instead, they contain indecies into a Palette
. The result of this is a dramatic memory savings, but at the cost of an additional step between the bitmap and the screen. The practical result of this is that the associated displayio.Palette
object must be passed along with the bitmap.
Consider the PyPaint project found in this guide. The ability to save the painting can be added with a few lines, essentially:
from adafruit_bitmapsaver import save_pixels . . . save_pixels('/sd/pypaint.bmp', self._fg_bitmap, self._fg_palette)
Because saving a PyPortal sized bitmap blocks other code from running and takes a noticeable amount of time, it can be useful to display a message to the user while the saving is taking place.
This results in a BMP file as shown below:
Page last edited March 08, 2024
Text editor powered by tinymce.