|
| 1 | +// Adafruit_ImageReader test for PyPortal. Demonstrates loading images |
| 2 | +// from SD card to screen, to RAM, and how to query image file dimensions. |
| 3 | +// OPEN THE ARDUINO SERIAL MONITOR WINDOW TO START PROGRAM. |
| 4 | +// Requires three BMP files in root directory of SD card: |
| 5 | +// purple.bmp, parrot.bmp and wales.bmp. |
| 6 | + |
| 7 | +#include <SD.h> |
| 8 | +#include <Adafruit_GFX.h> // Core graphics library |
| 9 | +#include <Adafruit_ILI9341.h> // Hardware-specific library |
| 10 | +#include <Adafruit_ImageReader.h> // Image-reading functions |
| 11 | + |
| 12 | +#define TFT_D0 34 // Data bit 0 pin (MUST be on PORT byte boundary) |
| 13 | +#define TFT_WR 26 // Write-strobe pin (CCL-inverted timer output) |
| 14 | +#define TFT_DC 10 // Data/command pin |
| 15 | +#define TFT_CS 11 // Chip-select pin |
| 16 | +#define TFT_RST 24 // Reset pin |
| 17 | +#define TFT_RD 9 // Read-strobe pin |
| 18 | +#define TFT_BACKLIGHT 25 |
| 19 | +#define SD_CS 32 |
| 20 | + |
| 21 | +Adafruit_ILI9341 tft(tft8, TFT_D0, TFT_WR, TFT_DC, TFT_CS, TFT_RST, TFT_RD); |
| 22 | +Adafruit_ImageReader reader; // Class w/image-reading functions |
| 23 | +Adafruit_Image img; // An image loaded into RAM |
| 24 | +int32_t width = 0, // BMP image dimensions |
| 25 | + height = 0; |
| 26 | + |
| 27 | +void setup(void) { |
| 28 | + |
| 29 | + ImageReturnCode stat; // Status from image-reading functions |
| 30 | + |
| 31 | + Serial.begin(9600); |
| 32 | + while(!Serial); // Wait for Serial Monitor before continuing |
| 33 | + |
| 34 | + // Turn on backlight (required on PyPortal) |
| 35 | + pinMode(TFT_BACKLIGHT, OUTPUT); |
| 36 | + digitalWrite(TFT_BACKLIGHT, HIGH); |
| 37 | + |
| 38 | + tft.begin(); // Initialize screen |
| 39 | + |
| 40 | + Serial.print(F("Initializing SD card...")); |
| 41 | + if(!SD.begin(SD_CS)) { |
| 42 | + Serial.println(F("failed!")); |
| 43 | + for(;;); // Loop here forever |
| 44 | + } |
| 45 | + Serial.println(F("OK!")); |
| 46 | + |
| 47 | + // Fill screen blue. Not a required step, this just shows that we're |
| 48 | + // successfully communicating with the screen. |
| 49 | + tft.fillScreen(ILI9341_BLUE); |
| 50 | + |
| 51 | + // Load full-screen BMP file 'purple.bmp' at position (0,0) (top left). |
| 52 | + // Notice the 'reader' object performs this, with 'tft' as an argument. |
| 53 | + Serial.print(F("Loading purple.bmp to screen...")); |
| 54 | + stat = reader.drawBMP("/purple.bmp", tft, 0, 0); |
| 55 | + // (Absolute path isn't necessary on most devices, but something |
| 56 | + // with the ESP32 SD library seems to require it.) |
| 57 | + reader.printStatus(stat); // How'd we do? |
| 58 | + |
| 59 | + // Query the dimensions of image 'parrot.bmp' WITHOUT loading to screen: |
| 60 | + Serial.print(F("Querying parrot.bmp image size...")); |
| 61 | + stat = reader.bmpDimensions("/parrot.bmp", &width, &height); |
| 62 | + reader.printStatus(stat); // How'd we do? |
| 63 | + if(stat == IMAGE_SUCCESS) { // If it worked, print image size... |
| 64 | + Serial.print(F("Image dimensions: ")); |
| 65 | + Serial.print(width); |
| 66 | + Serial.write('x'); |
| 67 | + Serial.println(height); |
| 68 | + } |
| 69 | + |
| 70 | + // Load small BMP 'wales.bmp' into a GFX canvas in RAM. This should |
| 71 | + // fail gracefully on AVR and other small devices, meaning the image |
| 72 | + // will not load, but this won't make the program stop or crash, it |
| 73 | + // just continues on without it. |
| 74 | + Serial.print(F("Loading wales.bmp to canvas...")); |
| 75 | + stat = reader.loadBMP("/wales.bmp", img); |
| 76 | + reader.printStatus(stat); // How'd we do? |
| 77 | + |
| 78 | + delay(2000); // Pause 2 seconds before moving on to loop() |
| 79 | +} |
| 80 | + |
| 81 | +void loop() { |
| 82 | + for(int r=0; r<4; r++) { // For each of 4 rotations... |
| 83 | + tft.setRotation(r); // Set rotation |
| 84 | + tft.fillScreen(0); // and clear screen |
| 85 | + |
| 86 | + // Load 4 copies of the 'parrot.bmp' image to the screen, some |
| 87 | + // partially off screen edges to demonstrate clipping. Globals |
| 88 | + // 'width' and 'height' were set by bmpDimensions() call in setup(). |
| 89 | + for(int i=0; i<4; i++) { |
| 90 | + reader.drawBMP("/parrot.bmp", tft, |
| 91 | + (tft.width() * i / 3) - (width / 2), |
| 92 | + (tft.height() * i / 3) - (height / 2)); |
| 93 | + } |
| 94 | + |
| 95 | + delay(1000); // Pause 1 sec. |
| 96 | + |
| 97 | + // Draw 50 Welsh dragon flags in random positions. This has no effect |
| 98 | + // on memory-constrained boards like the Arduino Uno, where the image |
| 99 | + // failed to load due to insufficient RAM, but it's NOT fatal. |
| 100 | + for(int i=0; i<50; i++) { |
| 101 | + // Rather than reader.drawBMP() (which works from SD card), |
| 102 | + // a different function is used for RAM-resident images: |
| 103 | + img.draw(tft, // Pass in tft object |
| 104 | + (int16_t)random(-img.width() , tft.width()) , // Horiz pos. |
| 105 | + (int16_t)random(-img.height(), tft.height())); // Vert pos |
| 106 | + // Reiterating a prior point: img.draw() does nothing and returns |
| 107 | + // if the image failed to load. It's unfortunate but not disastrous. |
| 108 | + } |
| 109 | + |
| 110 | + delay(2000); // Pause 2 sec. |
| 111 | + } |
| 112 | +} |
0 commit comments