Topics

► Games

► Sound & Music

► Watches & Clocks

► GPS

► Power Supplies

► Computers

► Graphics

► Thermometers

► Wearables

► Test Equipment

► Tutorials

► Libraries

► PCB-Based Projects

By processor

AVR ATtiny

► ATtiny10

► ATtiny2313

► ATtiny84

► ATtiny841

► ATtiny85

► ATtiny861

► ATtiny88

AVR ATmega

► ATmega328

► ATmega1284

AVR 0-series and 1-series

► ATmega4809

► ATtiny1604

► ATtiny1614

► ATtiny3216

► ATtiny3227

► ATtiny402

► ATtiny404

► ATtiny414

► ATtiny814

AVR DA/DB-series

► AVR128DA28

► AVR128DA32

► AVR128DA48

► AVR128DB28

ARM

► ATSAMD21

► RP2040

► RA4M1

About me

  • About me
  • Twitter
  • Mastodon

Feeds

RSS feed

Saving Screenshots from a TFT Display

8th August 2020

This article describes a utility that will save a screenshot from the Adafruit PyGamer display. Suppose you've displayed an image on the TFT display:

Screenshot.jpg

Plot demo running on an Adafruit PyGamer.

This program will save a screenshot as a BMP-format file to the SD card, which you can then use to display the image in a document or on a web page:

Screenshot1.gif

Screenshot captured from the plot demo using the routine described in this article.

It will also work with the Adafruit PyBadge with an external SD card interface, and many other TFT displays with minor changes.

Introduction

Suppose you want to show images from an Adafruit PyGamer TFT display in a blog, or on a website. One way is to take a photograph of the screen, but getting a good quality image is quite difficult. This routine lets you create a perfect screenshot of the TFT display, and save it to an SD card so you can read it onto a computer and incorporate it into a document or web page.

This routine uses the Windows BMP file format as it is relatively simple, and is compatible with most image editors [1]. It doesn't support image compression which makes the routine simpler, but even so the images are only 41 Kbytes. Alternatively you could use an image editor to convert the images to GIF, PNG, or JPEG.

Note that for the example above I scaled the image up by a factor of 4 to display it larger without it getting smoothed by the web browser. The original is 160x128, the same as the screen resolution.

The routine could be modified to work with most displays, provided they support reading a pixel from the display.

The program

The program uses the getPixel() routine I described in my earlier projects Reading the PyBadge Display and Simple Sprite Routines for the PyGamer/PyBadge. I've included it again in this program for convenience.

Saving a BMP file

The main bmpSave() routine opens a file on the SD card, and then reads the display a pixel at a time, and writes the BMP-format data to the file:

void bmpSave () {
  uint32_t filesize, offset;
  uint16_t width = tft.width(), height = tft.height();
  char filename[11] = "image1.bmp";
  SD.begin();
  while (SD.exists(filename)) { filename[5]++; } 
  bmpFile = SD.open(filename, FILE_WRITE);
  // On error hang up
  if (!bmpFile) for (;;);
  digitalWrite(LED_BUILTIN, HIGH);
  //
  // File header: 14 bytes
  bmpFile.write('B'); bmpFile.write('M');
  writeFour(14+40+12+width*height*2); // File size in bytes
  writeFour(0);
  writeFour(14+40+12);                // Offset to image data from start
  //
  // Image header: 40 bytes
  writeFour(40);                      // Header size
  writeFour(width);                   // Image width
  writeFour(height);                  // Image height
  writeTwo(1);                        // Planes
  writeTwo(16);                       // Bits per pixel
  writeFour(0);                       // Compression (none)
  writeFour(0);                       // Image size (0 for uncompressed)
  writeFour(0);                       // Preferred X resolution (ignore)
  writeFour(0);                       // Preferred Y resolution (ignore)
  writeFour(0);                       // Colour map entries (ignore)
  writeFour(0);                       // Important colours (ignore)
  //
  // Colour masks: 12 bytes
  writeFour(0b0000011111100000);      // Green
  writeFour(0b1111100000000000);      // Red
  writeFour(0b0000000000011111);      // Blue
  //
  // Image data: width * height * 2 bytes
  for (int y=height-1; y>=0; y--) {
    for (int x=0; x<width; x++) {
      writeTwo(tft.getPixel(x,y));    // Each row must be a multiple of four bytes
    }
  }
  // Close the file
  bmpFile.close();
  digitalWrite(LED_BUILTIN, LOW);
}

It saves the image to a file called image1.bmp. If this already exists on the SD card it uses the name image2.bmp, and so on, making it convenient to save a series of images.

The built-in LED is used to show the progress of the save. It's initially off, and is lit while the image data is being written to the card. If there's a problem with the card, or no card is present, the LED won't light up at all.

The rest of the routine handles the writing of the headers and image data in BMP format.

Plot demo

I've included a simple plot demo to demonstrate the screenshot program; it's the same demo I used in my Tiny TFT Graphics Library, rewritten to use the Adafruit GFX library.

Here's the screenshot routine together with the plot demo: TFT Screenshot Program


  1. ^ Simplified Windows BMP Bitmap File Format Specification on Hackaday.

blog comments powered by Disqus