Fit top left clipping, update examples, update images
This commit is contained in:
parent
0a49733447
commit
ca37168105
8 changed files with 209 additions and 37 deletions
|
|
@ -279,7 +279,8 @@ ImageReturnCode Adafruit_ImageReader::coreBMP(
|
||||||
uint32_t destidx = 0;
|
uint32_t destidx = 0;
|
||||||
boolean flip = true; // BMP is stored bottom-to-top
|
boolean flip = true; // BMP is stored bottom-to-top
|
||||||
uint32_t bmpPos = 0; // Next pixel position in file
|
uint32_t bmpPos = 0; // Next pixel position in file
|
||||||
int loadWidth, loadHeight; // Region being loaded (clipped)
|
int loadWidth, loadHeight, // Region being loaded (clipped)
|
||||||
|
loadX , loadY; // "
|
||||||
int row, col; // Current pixel pos.
|
int row, col; // Current pixel pos.
|
||||||
uint8_t r, g, b; // Current pixel color
|
uint8_t r, g, b; // Current pixel color
|
||||||
|
|
||||||
|
|
@ -319,15 +320,19 @@ ImageReturnCode Adafruit_ImageReader::coreBMP(
|
||||||
|
|
||||||
loadWidth = bmpWidth;
|
loadWidth = bmpWidth;
|
||||||
loadHeight = bmpHeight;
|
loadHeight = bmpHeight;
|
||||||
|
loadX = 0;
|
||||||
|
loadY = 0;
|
||||||
if(tft) {
|
if(tft) {
|
||||||
// Crop area to be loaded (if destination is TFT)
|
// Crop area to be loaded (if destination is TFT)
|
||||||
if(x < 0) {
|
if(x < 0) {
|
||||||
loadWidth += x;
|
loadX = -x;
|
||||||
x = 0;
|
loadWidth += x;
|
||||||
|
x = 0;
|
||||||
}
|
}
|
||||||
if(y < 0) {
|
if(y < 0) {
|
||||||
loadHeight += y;
|
loadY = -y;
|
||||||
y = 0;
|
loadHeight += y;
|
||||||
|
y = 0;
|
||||||
}
|
}
|
||||||
if((x + loadWidth ) > tft->width()) loadWidth = tft->width() - x;
|
if((x + loadWidth ) > tft->width()) loadWidth = tft->width() - x;
|
||||||
if((y + loadHeight) > tft->height()) loadHeight = tft->height() - y;
|
if((y + loadHeight) > tft->height()) loadHeight = tft->height() - y;
|
||||||
|
|
@ -370,9 +375,10 @@ ImageReturnCode Adafruit_ImageReader::coreBMP(
|
||||||
// the seek only takes place if the file position actually needs
|
// the seek only takes place if the file position actually needs
|
||||||
// to change (avoids a lot of cluster math in SD library).
|
// to change (avoids a lot of cluster math in SD library).
|
||||||
if(flip) // Bitmap is stored bottom-to-top order (normal BMP)
|
if(flip) // Bitmap is stored bottom-to-top order (normal BMP)
|
||||||
bmpPos = offset + (bmpHeight - 1 - row) * rowSize;
|
bmpPos = offset + (bmpHeight - 1 - (row + loadY)) * rowSize +
|
||||||
|
loadX * 3;
|
||||||
else // Bitmap is stored top-to-bottom
|
else // Bitmap is stored top-to-bottom
|
||||||
bmpPos = offset + row * rowSize;
|
bmpPos = offset + (row + loadY) * rowSize + loadX * 3;
|
||||||
if(file.position() != bmpPos) { // Need seek?
|
if(file.position() != bmpPos) { // Need seek?
|
||||||
if(transact) tft->endWrite(); // End TFT SPI transaction
|
if(transact) tft->endWrite(); // End TFT SPI transaction
|
||||||
file.seek(bmpPos); // Seek = SD transaction
|
file.seek(bmpPos); // Seek = SD transaction
|
||||||
|
|
|
||||||
135
examples/FeatherWingHX8357/FeatherWingHX8357.ino
Normal file
135
examples/FeatherWingHX8357/FeatherWingHX8357.ino
Normal file
|
|
@ -0,0 +1,135 @@
|
||||||
|
// Adafruit_ImageReader test for 3.5" TFT FeatherWing. Demonstrates loading
|
||||||
|
// images to the screen, to RAM, and how to query image file dimensions.
|
||||||
|
// OPEN THE ARDUINO SERIAL MONITOR WINDOW TO START PROGRAM.
|
||||||
|
// Requires three BMP files in root directory of SD card:
|
||||||
|
// gators.bmp, parrot.bmp and wales.bmp.
|
||||||
|
|
||||||
|
#include <SPI.h>
|
||||||
|
#include <SD.h>
|
||||||
|
#include <Adafruit_GFX.h> // Core graphics library
|
||||||
|
#include <Adafruit_HX8357.h> // Hardware-specific library
|
||||||
|
#include <Adafruit_ImageReader.h> // Image-reading functions
|
||||||
|
|
||||||
|
// Pin definitions for 2.4" TFT FeatherWing vary among boards...
|
||||||
|
|
||||||
|
#if defined(ESP8266)
|
||||||
|
#define TFT_CS 0
|
||||||
|
#define TFT_DC 15
|
||||||
|
#define SD_CS 2
|
||||||
|
#elif defined(ESP32)
|
||||||
|
#define TFT_CS 15
|
||||||
|
#define TFT_DC 33
|
||||||
|
#define SD_CS 14
|
||||||
|
#elif defined(TEENSYDUINO)
|
||||||
|
#define TFT_DC 10
|
||||||
|
#define TFT_CS 4
|
||||||
|
#define SD_CS 8
|
||||||
|
#elif defined(ARDUINO_STM32_FEATHER)
|
||||||
|
#define TFT_DC PB4
|
||||||
|
#define TFT_CS PA15
|
||||||
|
#define SD_CS PC5
|
||||||
|
#elif defined(ARDUINO_NRF52_FEATHER) // BSP 0.6.5 and higher!
|
||||||
|
#define TFT_DC 11
|
||||||
|
#define TFT_CS 31
|
||||||
|
#define SD_CS 27
|
||||||
|
#elif defined(ARDUINO_MAX32620FTHR) || defined(ARDUINO_MAX32630FTHR)
|
||||||
|
#define TFT_DC P5_4
|
||||||
|
#define TFT_CS P5_3
|
||||||
|
#define STMPE_CS P3_3
|
||||||
|
#define SD_CS P3_2
|
||||||
|
#else // Anything else!
|
||||||
|
#define TFT_CS 9
|
||||||
|
#define TFT_DC 10
|
||||||
|
#define SD_CS 5
|
||||||
|
#endif
|
||||||
|
|
||||||
|
Adafruit_HX8357 tft = Adafruit_HX8357(TFT_CS, TFT_DC);
|
||||||
|
Adafruit_ImageReader reader; // Class w/image-reading functions
|
||||||
|
Adafruit_Image img; // An image loaded into RAM
|
||||||
|
int32_t width = 0, // BMP image dimensions
|
||||||
|
height = 0;
|
||||||
|
|
||||||
|
void setup(void) {
|
||||||
|
|
||||||
|
ImageReturnCode stat; // Status from image-reading functions
|
||||||
|
|
||||||
|
Serial.begin(9600);
|
||||||
|
#if !defined(ESP32)
|
||||||
|
while(!Serial); // Wait for Serial Monitor before continuing
|
||||||
|
#endif
|
||||||
|
|
||||||
|
tft.begin(); // Initialize screen
|
||||||
|
|
||||||
|
Serial.print(F("Initializing SD card..."));
|
||||||
|
if(!SD.begin(SD_CS)) {
|
||||||
|
Serial.println(F("failed!"));
|
||||||
|
for(;;); // Loop here forever
|
||||||
|
}
|
||||||
|
Serial.println(F("OK!"));
|
||||||
|
|
||||||
|
// Fill screen blue. Not a required step, this just shows that we're
|
||||||
|
// successfully communicating with the screen.
|
||||||
|
tft.fillScreen(HX8357_BLUE);
|
||||||
|
|
||||||
|
// Load full-screen BMP file 'gators.bmp' at position (0,0) (top left).
|
||||||
|
// Notice the 'reader' object performs this, with 'tft' as an argument.
|
||||||
|
Serial.print(F("Loading gators.bmp to screen..."));
|
||||||
|
stat = reader.drawBMP("/gators.bmp", tft, 0, 0);
|
||||||
|
// (Absolute path isn't necessary on most devices, but something
|
||||||
|
// with the ESP32 SD library seems to require it.)
|
||||||
|
reader.printStatus(stat); // How'd we do?
|
||||||
|
|
||||||
|
// Query the dimensions of image 'parrot.bmp' WITHOUT loading to screen:
|
||||||
|
Serial.print(F("Querying parrot.bmp image size..."));
|
||||||
|
stat = reader.bmpDimensions("/parrot.bmp", &width, &height);
|
||||||
|
reader.printStatus(stat); // How'd we do?
|
||||||
|
if(stat == IMAGE_SUCCESS) { // If it worked, print image size...
|
||||||
|
Serial.print(F("Image dimensions: "));
|
||||||
|
Serial.print(width);
|
||||||
|
Serial.write('x');
|
||||||
|
Serial.println(height);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Load small BMP 'wales.bmp' into a GFX canvas in RAM. This should
|
||||||
|
// fail gracefully on AVR and other small devices, meaning the image
|
||||||
|
// will not load, but this won't make the program stop or crash, it
|
||||||
|
// just continues on without it.
|
||||||
|
Serial.print(F("Loading wales.bmp to canvas..."));
|
||||||
|
stat = reader.loadBMP("/wales.bmp", img);
|
||||||
|
reader.printStatus(stat); // How'd we do?
|
||||||
|
|
||||||
|
delay(2000); // Pause 2 seconds before moving on to loop()
|
||||||
|
}
|
||||||
|
|
||||||
|
void loop() {
|
||||||
|
for(int r=0; r<4; r++) { // For each of 4 rotations...
|
||||||
|
tft.setRotation(r); // Set rotation
|
||||||
|
tft.fillScreen(0); // and clear screen
|
||||||
|
|
||||||
|
// Load 4 copies of the 'parrot.bmp' image to the screen, some
|
||||||
|
// partially off screen edges to demonstrate clipping. Globals
|
||||||
|
// 'width' and 'height' were set by bmpDimensions() call in setup().
|
||||||
|
for(int i=0; i<4; i++) {
|
||||||
|
reader.drawBMP("/parrot.bmp", tft,
|
||||||
|
(tft.width() * i / 3) - (width / 2),
|
||||||
|
(tft.height() * i / 3) - (height / 2));
|
||||||
|
}
|
||||||
|
|
||||||
|
delay(1000); // Pause 1 sec.
|
||||||
|
|
||||||
|
// Draw 50 Welsh dragon flags in random positions. This has no effect
|
||||||
|
// on memory-constrained boards like the Arduino Uno, where the image
|
||||||
|
// failed to load due to insufficient RAM, but it's NOT fatal.
|
||||||
|
for(int i=0; i<50; i++) {
|
||||||
|
// Rather than reader.drawBMP() (which works from SD card),
|
||||||
|
// a different function is used for RAM-resident images:
|
||||||
|
img.draw(tft, // Pass in tft object
|
||||||
|
(int16_t)random(-img.width() , tft.width()) , // Horiz pos.
|
||||||
|
(int16_t)random(-img.height(), tft.height())); // Vert pos
|
||||||
|
// Reiterating a prior point: img.draw() does nothing and returns
|
||||||
|
// if the image failed to load. It's unfortunate but not disastrous.
|
||||||
|
}
|
||||||
|
|
||||||
|
delay(1000); // Pause 2 sec.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,6 +1,8 @@
|
||||||
// Adafruit_ImageReader test for 2.4" TFT FeatherWing.
|
// Adafruit_ImageReader test for 2.4" TFT FeatherWing. Demonstrates loading
|
||||||
|
// images to the screen, to RAM, and how to query image file dimensions.
|
||||||
|
// OPEN THE ARDUINO SERIAL MONITOR WINDOW TO START PROGRAM.
|
||||||
// Requires three BMP files in root directory of SD card:
|
// Requires three BMP files in root directory of SD card:
|
||||||
// purple.bmp, parrot.bmp and test.bmp.
|
// purple.bmp, parrot.bmp and wales.bmp.
|
||||||
|
|
||||||
#include <SPI.h>
|
#include <SPI.h>
|
||||||
#include <SD.h>
|
#include <SD.h>
|
||||||
|
|
@ -26,7 +28,7 @@
|
||||||
#define TFT_DC PB4
|
#define TFT_DC PB4
|
||||||
#define TFT_CS PA15
|
#define TFT_CS PA15
|
||||||
#define SD_CS PC5
|
#define SD_CS PC5
|
||||||
#elif defined(ARDUINO_NRF52_FEATHER) /* BSP 0.6.5 and higher! */
|
#elif defined(ARDUINO_NRF52_FEATHER) // BSP 0.6.5 and higher!
|
||||||
#define TFT_DC 11
|
#define TFT_DC 11
|
||||||
#define TFT_CS 31
|
#define TFT_CS 31
|
||||||
#define SD_CS 27
|
#define SD_CS 27
|
||||||
|
|
@ -41,64 +43,93 @@
|
||||||
#define SD_CS 5
|
#define SD_CS 5
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
Adafruit_ILI9341 tft = Adafruit_ILI9341(TFT_CS, TFT_DC);
|
Adafruit_ILI9341 tft = Adafruit_ILI9341(TFT_CS, TFT_DC);
|
||||||
Adafruit_ImageReader reader; // Class w/image-reading functions
|
Adafruit_ImageReader reader; // Class w/image-reading functions
|
||||||
Adafruit_Image img; // Image loaded in RAM
|
Adafruit_Image img; // An image loaded into RAM
|
||||||
|
int32_t width = 0, // BMP image dimensions
|
||||||
|
height = 0;
|
||||||
|
|
||||||
void setup(void) {
|
void setup(void) {
|
||||||
|
|
||||||
ImageReturnCode stat; // Status from image-reading functions
|
ImageReturnCode stat; // Status from image-reading functions
|
||||||
int32_t width=0, height=0; // BMP image dimensions
|
|
||||||
|
|
||||||
Serial.begin(9600);
|
Serial.begin(9600);
|
||||||
#if !defined(ESP32)
|
#if !defined(ESP32)
|
||||||
while(!Serial); // Wait for Serial Monitor before continuing
|
while(!Serial); // Wait for Serial Monitor before continuing
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
tft.begin();
|
tft.begin(); // Initialize screen
|
||||||
|
|
||||||
Serial.print(F("Initializing SD card..."));
|
Serial.print(F("Initializing SD card..."));
|
||||||
if(!SD.begin(SD_CS)) {
|
if(!SD.begin(SD_CS)) {
|
||||||
Serial.println("failed!");
|
Serial.println(F("failed!"));
|
||||||
for(;;); // Loop here forever
|
for(;;); // Loop here forever
|
||||||
}
|
}
|
||||||
Serial.println(F("OK!"));
|
Serial.println(F("OK!"));
|
||||||
|
|
||||||
// Fill screen blue just to show that we're talking to screen OK
|
// Fill screen blue. Not a required step, this just shows that we're
|
||||||
|
// successfully communicating with the screen.
|
||||||
tft.fillScreen(ILI9341_BLUE);
|
tft.fillScreen(ILI9341_BLUE);
|
||||||
|
|
||||||
// Load BMP file 'purple.bmp' at position (0, 0) (top left corner)
|
// Load full-screen BMP file 'purple.bmp' at position (0,0) (top left).
|
||||||
|
// Notice the 'reader' object performs this, with 'tft' as an argument.
|
||||||
Serial.print(F("Loading purple.bmp to screen..."));
|
Serial.print(F("Loading purple.bmp to screen..."));
|
||||||
stat = reader.drawBMP("/purple.bmp", tft, 0, 0);
|
stat = reader.drawBMP("/purple.bmp", tft, 0, 0);
|
||||||
// (Absolute path isn't necessary on most devices, but something
|
// (Absolute path isn't necessary on most devices, but something
|
||||||
// with the ESP32 SD library seems to require it.)
|
// with the ESP32 SD library seems to require it.)
|
||||||
reader.printStatus(stat); // How'd we do?
|
reader.printStatus(stat); // How'd we do?
|
||||||
|
|
||||||
Serial.print("Querying parrot.bmp image size...");
|
// Query the dimensions of image 'parrot.bmp' WITHOUT loading to screen:
|
||||||
|
Serial.print(F("Querying parrot.bmp image size..."));
|
||||||
stat = reader.bmpDimensions("/parrot.bmp", &width, &height);
|
stat = reader.bmpDimensions("/parrot.bmp", &width, &height);
|
||||||
reader.printStatus(stat); // How'd we do?
|
reader.printStatus(stat); // How'd we do?
|
||||||
if(stat == IMAGE_SUCCESS) { // If it worked...
|
if(stat == IMAGE_SUCCESS) { // If it worked, print image size...
|
||||||
Serial.print(F("Image dimensions: "));
|
Serial.print(F("Image dimensions: "));
|
||||||
Serial.print(width);
|
Serial.print(width);
|
||||||
Serial.write('x');
|
Serial.write('x');
|
||||||
Serial.println(height);
|
Serial.println(height);
|
||||||
// Draw 4 parrots, edges are clipped as necessary...
|
}
|
||||||
|
|
||||||
|
// Load small BMP 'wales.bmp' into a GFX canvas in RAM. This should
|
||||||
|
// fail gracefully on AVR and other small devices, meaning the image
|
||||||
|
// will not load, but this won't make the program stop or crash, it
|
||||||
|
// just continues on without it.
|
||||||
|
Serial.print(F("Loading wales.bmp to canvas..."));
|
||||||
|
stat = reader.loadBMP("/wales.bmp", img);
|
||||||
|
reader.printStatus(stat); // How'd we do?
|
||||||
|
|
||||||
|
delay(2000); // Pause 2 seconds before moving on to loop()
|
||||||
|
}
|
||||||
|
|
||||||
|
void loop() {
|
||||||
|
for(int r=0; r<4; r++) { // For each of 4 rotations...
|
||||||
|
tft.setRotation(r); // Set rotation
|
||||||
|
tft.fillScreen(0); // and clear screen
|
||||||
|
|
||||||
|
// Load 4 copies of the 'parrot.bmp' image to the screen, some
|
||||||
|
// partially off screen edges to demonstrate clipping. Globals
|
||||||
|
// 'width' and 'height' were set by bmpDimensions() call in setup().
|
||||||
for(int i=0; i<4; i++) {
|
for(int i=0; i<4; i++) {
|
||||||
reader.drawBMP("/parrot.bmp", tft,
|
reader.drawBMP("/parrot.bmp", tft,
|
||||||
(tft.width() * i / 3) - (width / 2),
|
(tft.width() * i / 3) - (width / 2),
|
||||||
(tft.height() * i / 3) - (height / 2));
|
(tft.height() * i / 3) - (height / 2));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
delay(1000); // Pause 1 sec.
|
||||||
|
|
||||||
|
// Draw 50 Welsh dragon flags in random positions. This has no effect
|
||||||
|
// on memory-constrained boards like the Arduino Uno, where the image
|
||||||
|
// failed to load due to insufficient RAM, but it's NOT fatal.
|
||||||
|
for(int i=0; i<50; i++) {
|
||||||
|
// Rather than reader.drawBMP() (which works from SD card),
|
||||||
|
// a different function is used for RAM-resident images:
|
||||||
|
img.draw(tft, // Pass in tft object
|
||||||
|
(int16_t)random(-img.width() , tft.width()) , // Horiz pos.
|
||||||
|
(int16_t)random(-img.height(), tft.height())); // Vert pos
|
||||||
|
// Reiterating a prior point: img.draw() does nothing and returns
|
||||||
|
// if the image failed to load. It's unfortunate but not disastrous.
|
||||||
|
}
|
||||||
|
|
||||||
|
delay(2000); // Pause 2 sec.
|
||||||
}
|
}
|
||||||
|
|
||||||
// Load BMP 'test.bmp' into a GFX canvas in RAM.
|
|
||||||
// This won't work on AVR and other small devices.
|
|
||||||
Serial.print("Loading test.bmp to canvas...");
|
|
||||||
stat = reader.loadBMP("/test.bmp", img);
|
|
||||||
reader.printStatus(stat); // How'd we do?
|
|
||||||
}
|
|
||||||
|
|
||||||
void loop() {
|
|
||||||
img.draw(tft,
|
|
||||||
(int16_t)random(-img.width() , tft.width()) , // Horiz pos.
|
|
||||||
(int16_t)random(-img.height(), tft.height())); // Vert pos
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
BIN
images/gators.bmp
Normal file
BIN
images/gators.bmp
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 450 KiB |
BIN
images/miniwoof.bmp
Normal file
BIN
images/miniwoof.bmp
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 56 KiB |
BIN
images/test.bmp
BIN
images/test.bmp
Binary file not shown.
|
Before Width: | Height: | Size: 12 KiB |
BIN
images/wales.bmp
Normal file
BIN
images/wales.bmp
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 8.2 KiB |
BIN
images/woof.bmp
Normal file
BIN
images/woof.bmp
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 225 KiB |
Loading…
Reference in a new issue