clang, remove travis, add actions, bump

This commit is contained in:
Lady Ada 2019-12-27 20:07:56 -05:00
parent 60d96d6812
commit 70152a185d
10 changed files with 421 additions and 331 deletions

46
.github/ISSUE_TEMPLATE.md vendored Normal file
View file

@ -0,0 +1,46 @@
Thank you for opening an issue on an Adafruit Arduino library repository. To
improve the speed of resolution please review the following guidelines and
common troubleshooting steps below before creating the issue:
- **Do not use GitHub issues for troubleshooting projects and issues.** Instead use
the forums at http://forums.adafruit.com to ask questions and troubleshoot why
something isn't working as expected. In many cases the problem is a common issue
that you will more quickly receive help from the forum community. GitHub issues
are meant for known defects in the code. If you don't know if there is a defect
in the code then start with troubleshooting on the forum first.
- **If following a tutorial or guide be sure you didn't miss a step.** Carefully
check all of the steps and commands to run have been followed. Consult the
forum if you're unsure or have questions about steps in a guide/tutorial.
- **For Arduino projects check these very common issues to ensure they don't apply**:
- For uploading sketches or communicating with the board make sure you're using
a **USB data cable** and **not** a **USB charge-only cable**. It is sometimes
very hard to tell the difference between a data and charge cable! Try using the
cable with other devices or swapping to another cable to confirm it is not
the problem.
- **Be sure you are supplying adequate power to the board.** Check the specs of
your board and plug in an external power supply. In many cases just
plugging a board into your computer is not enough to power it and other
peripherals.
- **Double check all soldering joints and connections.** Flakey connections
cause many mysterious problems. See the [guide to excellent soldering](https://learn.adafruit.com/adafruit-guide-excellent-soldering/tools) for examples of good solder joints.
- **Ensure you are using an official Arduino or Adafruit board.** We can't
guarantee a clone board will have the same functionality and work as expected
with this code and don't support them.
If you're sure this issue is a defect in the code and checked the steps above
please fill in the following fields to provide enough troubleshooting information.
You may delete the guideline and text above to just leave the following details:
- Arduino board: **INSERT ARDUINO BOARD NAME/TYPE HERE**
- Arduino IDE version (found in Arduino -> About Arduino menu): **INSERT ARDUINO
VERSION HERE**
- List the steps to reproduce the problem below (if possible attach a sketch or
copy the sketch code in too): **LIST REPRO STEPS BELOW**

26
.github/PULL_REQUEST_TEMPLATE.md vendored Normal file
View file

@ -0,0 +1,26 @@
Thank you for creating a pull request to contribute to Adafruit's GitHub code!
Before you open the request please review the following guidelines and tips to
help it be more easily integrated:
- **Describe the scope of your change--i.e. what the change does and what parts
of the code were modified.** This will help us understand any risks of integrating
the code.
- **Describe any known limitations with your change.** For example if the change
doesn't apply to a supported platform of the library please mention it.
- **Please run any tests or examples that can exercise your modified code.** We
strive to not break users of the code and running tests/examples helps with this
process.
Thank you again for contributing! We will try to test and integrate the change
as soon as we can, but be aware we have many GitHub repositories to manage and
can't immediately respond to every request. There is no need to bump or check in
on a pull request (it will clutter the discussion of the request).
Also don't be worried if the request is closed or not integrated--sometimes the
priorities of Adafruit's GitHub code (education, ease of use) might not match the
priorities of the pull request. Don't fret, the open source community thrives on
forks and GitHub makes it easy to keep your changes in a forked repo.
After reviewing the guidelines above you can delete this text from the pull request.

32
.github/workflows/githubci.yml vendored Normal file
View file

@ -0,0 +1,32 @@
name: Arduino Library CI
on: [pull_request, push]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/setup-python@v1
with:
python-version: '3.x'
- uses: actions/checkout@v2
- uses: actions/checkout@v2
with:
repository: adafruit/ci-arduino
path: ci
- name: pre-install
run: bash ci/actions_install.sh
- name: test platforms
run: python3 ci/build_platform.py main_platforms arcada_platforms
- name: clang
run: python3 ci/run-clang-format.py -e "ci/*" -e "bin/*" -r .
- name: doxygen
env:
GH_REPO_TOKEN: ${{ secrets.GH_REPO_TOKEN }}
PRETTYNAME : "Adafruit ImageReader Library"
run: bash ci/doxy_gen_and_deploy.sh

View file

@ -1,33 +0,0 @@
language: c
sudo: false
cache:
directories:
- ~/arduino_ide
- ~/.arduino15/packages/
git:
depth: false
quiet: true
addons:
apt:
packages:
- python3
- python3-pip
- python3-setuptools
env:
global:
- PRETTYNAME="Adafruit ImageLoader Arduino Library"
before_install:
- source <(curl -SLs https://raw.githubusercontent.com/adafruit/travis-ci-arduino/master/install.sh)
script:
- build_cplay_platforms
- build_main_platforms
# Generate and deploy documentation
after_success:
- source <(curl -SLs https://raw.githubusercontent.com/adafruit/travis-ci-arduino/master/library_check.sh)
- source <(curl -SLs https://raw.githubusercontent.com/adafruit/travis-ci-arduino/master/doxy_gen_and_deploy.sh)

View file

@ -49,9 +49,9 @@
// on screen or image size.)
#ifdef __AVR__
#define BUFPIXELS 24 ///< 24 * 5 = 120 bytes
#define BUFPIXELS 24 ///< 24 * 5 = 120 bytes
#else
#define BUFPIXELS 200 ///< 200 * 5 = 1000 bytes
#define BUFPIXELS 200 ///< 200 * 5 = 1000 bytes
#endif
// ADAFRUIT_IMAGE CLASS ****************************************************
@ -64,8 +64,8 @@
@brief Constructor.
@return 'Empty' Adafruit_Image object.
*/
Adafruit_Image::Adafruit_Image(void) : mask(NULL), palette(NULL),
format(IMAGE_NONE) {
Adafruit_Image::Adafruit_Image(void)
: mask(NULL), palette(NULL), format(IMAGE_NONE) {
canvas.canvas1 = NULL;
}
@ -73,9 +73,7 @@ Adafruit_Image::Adafruit_Image(void) : mask(NULL), palette(NULL),
@brief Destructor.
@return None (void).
*/
Adafruit_Image::~Adafruit_Image(void) {
dealloc();
}
Adafruit_Image::~Adafruit_Image(void) { dealloc(); }
/*!
@brief Deallocates memory associated with Adafruit_Image object
@ -83,27 +81,27 @@ Adafruit_Image::~Adafruit_Image(void) {
@return None (void).
*/
void Adafruit_Image::dealloc(void) {
if(format == IMAGE_1 ) {
if(canvas.canvas1) {
if (format == IMAGE_1) {
if (canvas.canvas1) {
delete canvas.canvas1;
canvas.canvas1 = NULL;
}
} else if(format == IMAGE_8 ) {
if(canvas.canvas8) {
} else if (format == IMAGE_8) {
if (canvas.canvas8) {
delete canvas.canvas8;
canvas.canvas8 = NULL;
}
} else if(format == IMAGE_16) {
if(canvas.canvas16) {
} else if (format == IMAGE_16) {
if (canvas.canvas16) {
delete canvas.canvas16;
canvas.canvas16 = NULL;
}
}
if(mask) {
if (mask) {
delete mask;
mask = NULL;
}
if(palette) {
if (palette) {
delete[] palette;
palette = NULL;
}
@ -115,10 +113,13 @@ void Adafruit_Image::dealloc(void) {
@return Width in pixels, or 0 if no image loaded.
*/
int16_t Adafruit_Image::width(void) const {
if(format != IMAGE_NONE) { // Image allocated?
if( format == IMAGE_1 ) return canvas.canvas1->width();
else if(format == IMAGE_8 ) return canvas.canvas8->width();
else if(format == IMAGE_16) return canvas.canvas16->width();
if (format != IMAGE_NONE) { // Image allocated?
if (format == IMAGE_1)
return canvas.canvas1->width();
else if (format == IMAGE_8)
return canvas.canvas8->width();
else if (format == IMAGE_16)
return canvas.canvas16->width();
}
return 0;
}
@ -128,10 +129,13 @@ int16_t Adafruit_Image::width(void) const {
@return Height in pixels, or 0 if no image loaded.
*/
int16_t Adafruit_Image::height(void) const {
if(format != IMAGE_NONE) { // Image allocated?
if( format == IMAGE_1 ) return canvas.canvas1->height();
else if(format == IMAGE_8 ) return canvas.canvas8->height();
else if(format == IMAGE_16) return canvas.canvas16->height();
if (format != IMAGE_NONE) { // Image allocated?
if (format == IMAGE_1)
return canvas.canvas1->height();
else if (format == IMAGE_8)
return canvas.canvas8->height();
else if (format == IMAGE_16)
return canvas.canvas16->height();
}
return 0;
}
@ -153,10 +157,13 @@ int16_t Adafruit_Image::height(void) const {
for a lot of mayhem here if used wrong.
*/
void *Adafruit_Image::getCanvas(void) const {
if(format != IMAGE_NONE) { // Image allocated?
if( format == IMAGE_1 ) return (void *)canvas.canvas1;
else if(format == IMAGE_8 ) return (void *)canvas.canvas8;
else if(format == IMAGE_16) return (void *)canvas.canvas16;
if (format != IMAGE_NONE) { // Image allocated?
if (format == IMAGE_1)
return (void *)canvas.canvas1;
else if (format == IMAGE_8)
return (void *)canvas.canvas8;
else if (format == IMAGE_16)
return (void *)canvas.canvas16;
}
return NULL;
}
@ -174,22 +181,21 @@ void *Adafruit_Image::getCanvas(void) const {
@return None (void).
*/
void Adafruit_Image::draw(Adafruit_SPITFT &tft, int16_t x, int16_t y) {
if(format == IMAGE_1 ) {
if (format == IMAGE_1) {
uint16_t foreground, background;
if(palette) {
if (palette) {
foreground = palette[1];
background = palette[0];
} else {
foreground = 0xFFFF;
background = 0x0000;
}
tft.drawBitmap(x, y, canvas.canvas1->getBuffer(),
canvas.canvas1->width(), canvas.canvas1->height(),
foreground, background);
} else if(format == IMAGE_8 ) {
} else if(format == IMAGE_16) {
tft.drawBitmap(x, y, canvas.canvas1->getBuffer(), canvas.canvas1->width(),
canvas.canvas1->height(), foreground, background);
} else if (format == IMAGE_8) {
} else if (format == IMAGE_16) {
tft.drawRGBBitmap(x, y, canvas.canvas16->getBuffer(),
canvas.canvas16->width(), canvas.canvas16->height());
canvas.canvas16->width(), canvas.canvas16->height());
}
}
@ -208,16 +214,15 @@ void Adafruit_Image::draw(Adafruit_SPITFT &tft, int16_t x, int16_t y) {
often be in pre-setup() declaration, but DOES need initializing
before any of the image loading or size functions are called!
*/
Adafruit_ImageReader::Adafruit_ImageReader(FatFileSystem &fs) {
filesys = &fs;
}
Adafruit_ImageReader::Adafruit_ImageReader(FatFileSystem &fs) { filesys = &fs; }
/*!
@brief Destructor.
@return None (void).
*/
Adafruit_ImageReader::~Adafruit_ImageReader(void) {
if(file) file.close();
if (file)
file.close();
// filesystem is left as-is
}
@ -242,7 +247,8 @@ Adafruit_ImageReader::~Adafruit_ImageReader(void) {
completion, other values on failure).
*/
ImageReturnCode Adafruit_ImageReader::drawBMP(char *filename,
Adafruit_SPITFT &tft, int16_t x, int16_t y, boolean transact) {
Adafruit_SPITFT &tft, int16_t x,
int16_t y, boolean transact) {
uint16_t tftbuf[BUFPIXELS]; // Temp space for buffering TFT data
// Call core BMP-reading function, passing address to TFT object,
// TFT working buffer, and X & Y position of top-left corner (image
@ -264,8 +270,8 @@ ImageReturnCode Adafruit_ImageReader::drawBMP(char *filename,
@return One of the ImageReturnCode values (IMAGE_SUCCESS on successful
completion, other values on failure).
*/
ImageReturnCode Adafruit_ImageReader::loadBMP(
char *filename, Adafruit_Image &img) {
ImageReturnCode Adafruit_ImageReader::loadBMP(char *filename,
Adafruit_Image &img) {
// Call core BMP-reading function. TFT and working buffer are NULL
// (unused and allocated in function, respectively), X & Y position are
// always 0 because full image is loaded (RAM permitting). Adafruit_Image
@ -302,76 +308,77 @@ ImageReturnCode Adafruit_ImageReader::loadBMP(
completion, other values on failure).
*/
ImageReturnCode Adafruit_ImageReader::coreBMP(
char *filename, // SD file to load
Adafruit_SPITFT *tft, // Pointer to TFT object, or NULL if to image
uint16_t *dest, // TFT working buffer, or NULL if to canvas
int16_t x, // Position if loading to TFT (else ignored)
int16_t y,
Adafruit_Image *img, // NULL if load-to-screen
boolean transact) { // SD & TFT sharing bus, use transactions
char *filename, // SD file to load
Adafruit_SPITFT *tft, // Pointer to TFT object, or NULL if to image
uint16_t *dest, // TFT working buffer, or NULL if to canvas
int16_t x, // Position if loading to TFT (else ignored)
int16_t y,
Adafruit_Image *img, // NULL if load-to-screen
boolean transact) { // SD & TFT sharing bus, use transactions
ImageReturnCode status = IMAGE_ERR_FORMAT; // IMAGE_SUCCESS on valid file
uint32_t offset; // Start of image data in file
uint32_t headerSize; // Indicates BMP version
int bmpWidth, bmpHeight; // BMP width & height in pixels
uint8_t planes; // BMP planes
uint8_t depth; // BMP bit depth
uint32_t compression = 0; // BMP compression mode
uint32_t colors = 0; // Number of colors in palette
uint16_t *quantized = NULL; // 16-bit 5/6/5 color palette
uint32_t rowSize; // >bmpWidth if scanline padding
uint8_t sdbuf[3*BUFPIXELS]; // BMP read buf (R+G+B/pixel)
#if ((3*BUFPIXELS) <= 255)
uint8_t srcidx = sizeof sdbuf; // Current position in sdbuf
ImageReturnCode status = IMAGE_ERR_FORMAT; // IMAGE_SUCCESS on valid file
uint32_t offset; // Start of image data in file
uint32_t headerSize; // Indicates BMP version
int bmpWidth, bmpHeight; // BMP width & height in pixels
uint8_t planes; // BMP planes
uint8_t depth; // BMP bit depth
uint32_t compression = 0; // BMP compression mode
uint32_t colors = 0; // Number of colors in palette
uint16_t *quantized = NULL; // 16-bit 5/6/5 color palette
uint32_t rowSize; // >bmpWidth if scanline padding
uint8_t sdbuf[3 * BUFPIXELS]; // BMP read buf (R+G+B/pixel)
#if ((3 * BUFPIXELS) <= 255)
uint8_t srcidx = sizeof sdbuf; // Current position in sdbuf
#else
uint16_t srcidx = sizeof sdbuf;
uint16_t srcidx = sizeof sdbuf;
#endif
uint32_t destidx = 0;
uint8_t *dest1 = NULL; // Dest ptr for 1-bit BMPs to img
boolean flip = true; // BMP is stored bottom-to-top
uint32_t bmpPos = 0; // Next pixel position in file
int loadWidth, loadHeight, // Region being loaded (clipped)
loadX , loadY; // "
int row, col; // Current pixel pos.
uint8_t r, g, b; // Current pixel color
uint8_t bitIn = 0; // Bit number for 1-bit data in
uint8_t bitOut = 0; // Column mask for 1-bit data out
uint32_t destidx = 0;
uint8_t *dest1 = NULL; // Dest ptr for 1-bit BMPs to img
boolean flip = true; // BMP is stored bottom-to-top
uint32_t bmpPos = 0; // Next pixel position in file
int loadWidth, loadHeight, // Region being loaded (clipped)
loadX, loadY; // "
int row, col; // Current pixel pos.
uint8_t r, g, b; // Current pixel color
uint8_t bitIn = 0; // Bit number for 1-bit data in
uint8_t bitOut = 0; // Column mask for 1-bit data out
// If an Adafruit_Image object is passed and currently contains anything,
// free its contents as it's about to be overwritten with new stuff.
if(img) img->dealloc();
if (img)
img->dealloc();
// If BMP is being drawn off the right or bottom edge of the screen,
// nothing to do here. NOT an error, just a trivial clip operation.
if(tft && ((x >= tft->width()) || (y >= tft->height())))
if (tft && ((x >= tft->width()) || (y >= tft->height())))
return IMAGE_SUCCESS;
// Open requested file on SD card
if(!(file = filesys->open(filename, FILE_READ))) {
if (!(file = filesys->open(filename, FILE_READ))) {
return IMAGE_ERR_FILE_NOT_FOUND;
}
// Parse BMP header. 0x4D42 (ASCII 'BM') is the Windows BMP signature.
// There are other values possible in a .BMP file but these are super
// esoteric (e.g. OS/2 struct bitmap array) and NOT supported here!
if(readLE16() == 0x4D42) { // BMP signature
if (readLE16() == 0x4D42) { // BMP signature
(void)readLE32(); // Read & ignore file size
(void)readLE32(); // Read & ignore creator bytes
offset = readLE32(); // Start of image data
offset = readLE32(); // Start of image data
// Read DIB header
headerSize = readLE32();
bmpWidth = readLE32();
bmpHeight = readLE32();
headerSize = readLE32();
bmpWidth = readLE32();
bmpHeight = readLE32();
// If bmpHeight is negative, image is in top-down order.
// This is not canon but has been observed in the wild.
if(bmpHeight < 0) {
if (bmpHeight < 0) {
bmpHeight = -bmpHeight;
flip = false;
flip = false;
}
planes = readLE16();
depth = readLE16(); // Bits per pixel
planes = readLE16();
depth = readLE16(); // Bits per pixel
// Compression mode is present in later BMP versions (default = none)
if(headerSize > 12) {
if (headerSize > 12) {
compression = readLE32();
(void)readLE32(); // Raw bitmap data size; ignore
(void)readLE32(); // Horizontal resolution, ignore
@ -380,81 +387,83 @@ ImageReturnCode Adafruit_ImageReader::coreBMP(
(void)readLE32(); // Number of colors used (ignore)
// File position should now be at start of palette (if present)
}
if(!colors) colors = 1 << depth;
if (!colors)
colors = 1 << depth;
loadWidth = bmpWidth;
loadHeight = bmpHeight;
loadX = 0;
loadY = 0;
if(tft) {
loadWidth = bmpWidth;
loadHeight = bmpHeight;
loadX = 0;
loadY = 0;
if (tft) {
// Crop area to be loaded (if destination is TFT)
if(x < 0) {
loadX = -x;
loadWidth += x;
x = 0;
if (x < 0) {
loadX = -x;
loadWidth += x;
x = 0;
}
if(y < 0) {
loadY = -y;
loadHeight += y;
y = 0;
if (y < 0) {
loadY = -y;
loadHeight += y;
y = 0;
}
if((x + loadWidth ) > tft->width()) loadWidth = tft->width() - x;
if((y + loadHeight) > tft->height()) loadHeight = tft->height() - y;
if ((x + loadWidth) > tft->width())
loadWidth = tft->width() - x;
if ((y + loadHeight) > tft->height())
loadHeight = tft->height() - y;
}
if((planes == 1) && (compression == 0)) { // Only uncompressed is handled
if ((planes == 1) && (compression == 0)) { // Only uncompressed is handled
// BMP rows are padded (if needed) to 4-byte boundary
rowSize = ((depth * bmpWidth + 31) / 32) * 4;
if((depth == 24) || (depth == 1)) { // BGR or 1-bit bitmap format
if ((depth == 24) || (depth == 1)) { // BGR or 1-bit bitmap format
if(img) {
if (img) {
// Loading to RAM -- allocate GFX 16-bit canvas type
status = IMAGE_ERR_MALLOC; // Assume won't fit to start
if(depth == 24) {
if((img->canvas.canvas16 = new GFXcanvas16(bmpWidth, bmpHeight))) {
if (depth == 24) {
if ((img->canvas.canvas16 = new GFXcanvas16(bmpWidth, bmpHeight))) {
dest = img->canvas.canvas16->getBuffer();
}
} else {
if((img->canvas.canvas1 = new GFXcanvas1(bmpWidth, bmpHeight))) {
if ((img->canvas.canvas1 = new GFXcanvas1(bmpWidth, bmpHeight))) {
dest1 = img->canvas.canvas1->getBuffer();
}
}
// Future: handle other depths.
}
if(dest || dest1) { // Supported format, alloc OK, etc.
if (dest || dest1) { // Supported format, alloc OK, etc.
status = IMAGE_SUCCESS;
if((loadWidth > 0) && (loadHeight > 0)) { // Clip top/left
if(tft) {
if ((loadWidth > 0) && (loadHeight > 0)) { // Clip top/left
if (tft) {
tft->startWrite(); // Start SPI (regardless of transact)
tft->setAddrWindow(x, y, loadWidth, loadHeight);
} else {
if(depth == 1) {
img->format = IMAGE_1; // Is a GFX 1-bit canvas type
if (depth == 1) {
img->format = IMAGE_1; // Is a GFX 1-bit canvas type
} else {
img->format = IMAGE_16; // Is a GFX 16-bit canvas type
}
}
if((depth >= 16) ||
(quantized = (uint16_t *)malloc(colors * sizeof(uint16_t)))) {
if(depth < 16) {
if ((depth >= 16) ||
(quantized = (uint16_t *)malloc(colors * sizeof(uint16_t)))) {
if (depth < 16) {
// Load and quantize color table
for(uint16_t c=0; c<colors; c++) {
for (uint16_t c = 0; c < colors; c++) {
b = file.read();
g = file.read();
r = file.read();
(void)file.read(); // Ignore 4th byte
quantized[c] = ((r & 0xF8) << 8) |
((g & 0xFC) << 3) |
( b >> 3);
quantized[c] =
((r & 0xF8) << 8) | ((g & 0xFC) << 3) | (b >> 3);
}
}
for(row=0; row<loadHeight; row++) { // For each scanline...
for (row = 0; row < loadHeight; row++) { // For each scanline...
yield(); // Keep ESP8266 happy
@ -464,41 +473,41 @@ ImageReturnCode Adafruit_ImageReader::coreBMP(
// padding. Also, the seek only takes place if the file
// position actually needs to change (avoids a lot of cluster
// math in SD library).
if(flip) // Bitmap is stored bottom-to-top order (normal BMP)
bmpPos = offset +
(bmpHeight - 1 - (row + loadY)) * rowSize;
else // Bitmap is stored top-to-bottom
bmpPos = offset + (row + loadY) * rowSize;
if(depth == 24) {
if (flip) // Bitmap is stored bottom-to-top order (normal BMP)
bmpPos = offset + (bmpHeight - 1 - (row + loadY)) * rowSize;
else // Bitmap is stored top-to-bottom
bmpPos = offset + (row + loadY) * rowSize;
if (depth == 24) {
bmpPos += loadX * 3;
} else {
bmpPos += loadX / 8;
bitIn = 7 - (loadX & 7);
bitOut = 0x80;
if(img) destidx = ((bmpWidth + 7) / 8) * row;
bitIn = 7 - (loadX & 7);
bitOut = 0x80;
if (img)
destidx = ((bmpWidth + 7) / 8) * row;
}
if(file.position() != bmpPos) { // Need seek?
if(transact) {
if (file.position() != bmpPos) { // Need seek?
if (transact) {
tft->dmaWait();
tft->endWrite(); // End TFT SPI transaction
tft->endWrite(); // End TFT SPI transaction
}
file.seek(bmpPos); // Seek = SD transaction
srcidx = sizeof sdbuf; // Force buffer reload
file.seek(bmpPos); // Seek = SD transaction
srcidx = sizeof sdbuf; // Force buffer reload
}
for(col=0; col<loadWidth; col++) { // For each pixel...
if(srcidx >= sizeof sdbuf) { // Time to load more?
if(tft) { // Drawing to TFT?
if(transact) {
for (col = 0; col < loadWidth; col++) { // For each pixel...
if (srcidx >= sizeof sdbuf) { // Time to load more?
if (tft) { // Drawing to TFT?
if (transact) {
tft->dmaWait();
tft->endWrite(); // End TFT SPI transact
tft->endWrite(); // End TFT SPI transact
}
#if defined(ARDUINO_NRF52_ADAFRUIT)
// NRF52840 seems to have trouble reading more than 512
// bytes across certain boundaries. Workaround for now
// is to break the read into smaller chunks...
int32_t bytesToGo = sizeof sdbuf,
bytesRead = 0, bytesThisPass;
while(bytesToGo > 0) {
int32_t bytesToGo = sizeof sdbuf, bytesRead = 0,
bytesThisPass;
while (bytesToGo > 0) {
bytesThisPass = min(bytesToGo, 512);
file.read(&sdbuf[bytesRead], bytesThisPass);
bytesRead += bytesThisPass;
@ -507,75 +516,79 @@ ImageReturnCode Adafruit_ImageReader::coreBMP(
#else
file.read(sdbuf, sizeof sdbuf); // Load from SD
#endif
if(transact) tft->startWrite(); // Start TFT SPI transact
if(destidx) { // If buffered TFT data
if (transact)
tft->startWrite(); // Start TFT SPI transact
if (destidx) { // If buffered TFT data
// Non-blocking writes (DMA) have been temporarily
// disabled until this can be rewritten with two
// alternating 'dest' buffers (else the nonblocking
// data out is overwritten in the dest[] write below).
//tft->writePixels(dest, destidx, false); // Write it
// tft->writePixels(dest, destidx, false); // Write it
tft->writePixels(dest, destidx, true); // Write it
destidx = 0; // and reset dest index
destidx = 0; // and reset dest index
}
} else { // Canvas is simpler,
file.read(sdbuf, sizeof sdbuf); // just load sdbuf
} // (destidx never resets)
srcidx = 0; // Reset bmp buf index
}
if(depth == 24) {
if (depth == 24) {
// Convert each pixel from BMP to 565 format, save in dest
b = sdbuf[srcidx++];
g = sdbuf[srcidx++];
r = sdbuf[srcidx++];
dest[destidx++] = ((r & 0xF8) << 8) |
((g & 0xFC) << 3) |
( b >> 3);
dest[destidx++] =
((r & 0xF8) << 8) | ((g & 0xFC) << 3) | (b >> 3);
} else {
// Extract 1-bit color index
uint8_t n = (sdbuf[srcidx] >> bitIn) & 1;
if(!bitIn) {
if (!bitIn) {
srcidx++;
bitIn = 7;
} else {
bitIn--;
}
if(tft) {
if (tft) {
// Look up in palette, store in tft dest buf
dest[destidx++] = quantized[n];
} else {
// Store bit in canvas1 buffer (ignore palette)
if(n) dest1[destidx] |= bitOut;
else dest1[destidx] &= ~bitOut;
if (n)
dest1[destidx] |= bitOut;
else
dest1[destidx] &= ~bitOut;
bitOut >>= 1;
if(!bitOut) {
if (!bitOut) {
bitOut = 0x80;
destidx++;
}
}
}
} // end pixel loop
if(tft) { // Drawing to TFT?
if(destidx) { // Any remainders?
} // end pixel loop
if (tft) { // Drawing to TFT?
if (destidx) { // Any remainders?
// See notes above re: DMA
//tft->writePixels(dest, destidx, false); // Write it
// tft->writePixels(dest, destidx, false); // Write it
tft->writePixels(dest, destidx, true); // Write it
destidx = 0; // and reset dest index
destidx = 0; // and reset dest index
}
tft->dmaWait();
tft->endWrite(); // End TFT (regardless of transact)
}
} // end scanline loop
if(quantized) {
if(tft) free(quantized); // Palette no longer needed
else img->palette = quantized; // Keep palette with img
if (quantized) {
if (tft)
free(quantized); // Palette no longer needed
else
img->palette = quantized; // Keep palette with img
}
} // end depth>24 or quantized malloc OK
} // end top/left clip
} // end malloc check
} // end depth check
} // end planes/compression check
} // end signature
} // end top/left clip
} // end malloc check
} // end depth check
} // end planes/compression check
} // end signature
file.close();
return status;
@ -592,25 +605,28 @@ ImageReturnCode Adafruit_ImageReader::coreBMP(
@return One of the ImageReturnCode values (IMAGE_SUCCESS on successful
completion, other values on failure).
*/
ImageReturnCode Adafruit_ImageReader::bmpDimensions(
char *filename, int32_t *width, int32_t *height) {
ImageReturnCode Adafruit_ImageReader::bmpDimensions(char *filename,
int32_t *width,
int32_t *height) {
ImageReturnCode status = IMAGE_ERR_FILE_NOT_FOUND; // Guilty until innocent
if((file = filesys->open(filename, FILE_READ))) { // Open requested file
status = IMAGE_ERR_FORMAT; // File's there, might not be BMP tho
if(readLE16() == 0x4D42) { // BMP signature?
(void)readLE32(); // Read & ignore file size
(void)readLE32(); // Read & ignore creator bytes
(void)readLE32(); // Read & ignore position of image data
(void)readLE32(); // Read & ignore header size
if(width) *width = readLE32();
if(height) {
int32_t h = readLE32(); // Don't abs() this, may be a macro
if(h < 0) h = -h; // Do manually instead
if ((file = filesys->open(filename, FILE_READ))) { // Open requested file
status = IMAGE_ERR_FORMAT; // File's there, might not be BMP tho
if (readLE16() == 0x4D42) { // BMP signature?
(void)readLE32(); // Read & ignore file size
(void)readLE32(); // Read & ignore creator bytes
(void)readLE32(); // Read & ignore position of image data
(void)readLE32(); // Read & ignore header size
if (width)
*width = readLE32();
if (height) {
int32_t h = readLE32(); // Don't abs() this, may be a macro
if (h < 0)
h = -h; // Do manually instead
*height = h;
}
status = IMAGE_SUCCESS; // YAY.
status = IMAGE_SUCCESS; // YAY.
}
}
@ -627,7 +643,8 @@ ImageReturnCode Adafruit_ImageReader::bmpDimensions(
@return Unsigned 16-bit value, native endianism.
*/
uint16_t Adafruit_ImageReader::readLE16(void) {
#if !defined(ESP32) && !defined(ESP8266) && (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__)
#if !defined(ESP32) && !defined(ESP8266) && \
(__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__)
// Read directly into result -- BMP data and variable both little-endian.
uint16_t result;
file.read(&result, sizeof result);
@ -645,17 +662,16 @@ uint16_t Adafruit_ImageReader::readLE16(void) {
@return Unsigned 32-bit value, native endianism.
*/
uint32_t Adafruit_ImageReader::readLE32(void) {
#if !defined(ESP32) && !defined(ESP8266) && (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__)
#if !defined(ESP32) && !defined(ESP8266) && \
(__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__)
// Read directly into result -- BMP data and variable both little-endian.
uint32_t result;
file.read(&result, sizeof result);
return result;
#else
// Big-endian or unknown. Byte-by-byte read will perform reversal if needed.
return file.read() |
((uint32_t)file.read() << 8) |
((uint32_t)file.read() << 16) |
((uint32_t)file.read() << 24);
return file.read() | ((uint32_t)file.read() << 8) |
((uint32_t)file.read() << 16) | ((uint32_t)file.read() << 24);
#endif
}
@ -669,12 +685,12 @@ uint32_t Adafruit_ImageReader::readLE32(void) {
@return None (void).
*/
void Adafruit_ImageReader::printStatus(ImageReturnCode stat, Stream &stream) {
if(stat == IMAGE_SUCCESS)
if (stat == IMAGE_SUCCESS)
stream.println(F("Success!"));
else if(stat == IMAGE_ERR_FILE_NOT_FOUND)
else if (stat == IMAGE_ERR_FILE_NOT_FOUND)
stream.println(F("File not found."));
else if(stat == IMAGE_ERR_FORMAT)
else if (stat == IMAGE_ERR_FORMAT)
stream.println(F("Not a supported BMP variant."));
else if(stat == IMAGE_ERR_MALLOC)
else if (stat == IMAGE_ERR_MALLOC)
stream.println(F("Malloc failed (insufficient RAM)."));
}

View file

@ -15,8 +15,8 @@
#ifndef __ADAFRUIT_IMAGE_READER_H__
#define __ADAFRUIT_IMAGE_READER_H__
#include "Adafruit_SPITFT.h"
#include "Adafruit_SPIFlash.h"
#include "Adafruit_SPITFT.h"
/** Status codes returned by drawBMP() and loadBMP() */
enum ImageReturnCode {
@ -28,10 +28,10 @@ enum ImageReturnCode {
/** Image formats returned by loadBMP() */
enum ImageFormat {
IMAGE_NONE, // No image was loaded; IMAGE_ERR_* condition
IMAGE_1, // GFXcanvas1 image (NOT YET SUPPORTED)
IMAGE_8, // GFXcanvas8 image (NOT YET SUPPORTED)
IMAGE_16 // GFXcanvas16 image (SUPPORTED)
IMAGE_NONE, // No image was loaded; IMAGE_ERR_* condition
IMAGE_1, // GFXcanvas1 image (NOT YET SUPPORTED)
IMAGE_8, // GFXcanvas8 image (NOT YET SUPPORTED)
IMAGE_16 // GFXcanvas16 image (SUPPORTED)
};
/*!
@ -39,44 +39,45 @@ enum ImageFormat {
ImageReader.loadBMP() and Image.draw(), not ImageReader.drawBMP().
*/
class Adafruit_Image {
public:
Adafruit_Image(void);
~Adafruit_Image(void);
int16_t width(void) const; // Return image width in pixels
int16_t height(void) const; // Return image height in pixels
void draw(Adafruit_SPITFT &tft, int16_t x, int16_t y);
/*!
@brief Return canvas image format.
@return An ImageFormat type: IMAGE_1 for a GFXcanvas1, IMAGE_8 for
a GFXcanvas8, IMAGE_16 for a GFXcanvas16, IMAGE_NONE if no
canvas currently allocated.
*/
ImageFormat getFormat(void) const { return (ImageFormat)format; }
void *getCanvas(void) const;
/*!
@brief Return pointer to color palette.
@return Pointer to an array of 16-bit color values, or NULL if no
palette associated with image.
*/
uint16_t *getPalette(void) const { return palette; }
/*!
@brief Return pointer to 1bpp image mask canvas.
@return GFXcanvas1* pointer (1-bit RAM-resident image) if present,
NULL otherwise.
*/
GFXcanvas1 *getMask(void) const { return mask; };
protected:
// MOST OF THESE ARE NOT SUPPORTED YET -- WIP
union { // Single pointer, only one variant is used:
GFXcanvas1 *canvas1; ///< Canvas object if 1bpp format
GFXcanvas8 *canvas8; ///< Canvas object if 8bpp format
GFXcanvas16 *canvas16; ///< Canvas object if 16bpp
} canvas; ///< Union of different GFXcanvas types
GFXcanvas1 *mask; ///< 1bpp image mask (or NULL)
uint16_t *palette; ///< Color palette for 8bpp image (or NULL)
uint8_t format; ///< Canvas bundle type in use
void dealloc(void); ///< Free/deinitialize variables
friend class Adafruit_ImageReader; ///< Loading occurs here
public:
Adafruit_Image(void);
~Adafruit_Image(void);
int16_t width(void) const; // Return image width in pixels
int16_t height(void) const; // Return image height in pixels
void draw(Adafruit_SPITFT &tft, int16_t x, int16_t y);
/*!
@brief Return canvas image format.
@return An ImageFormat type: IMAGE_1 for a GFXcanvas1, IMAGE_8 for
a GFXcanvas8, IMAGE_16 for a GFXcanvas16, IMAGE_NONE if no
canvas currently allocated.
*/
ImageFormat getFormat(void) const { return (ImageFormat)format; }
void *getCanvas(void) const;
/*!
@brief Return pointer to color palette.
@return Pointer to an array of 16-bit color values, or NULL if no
palette associated with image.
*/
uint16_t *getPalette(void) const { return palette; }
/*!
@brief Return pointer to 1bpp image mask canvas.
@return GFXcanvas1* pointer (1-bit RAM-resident image) if present,
NULL otherwise.
*/
GFXcanvas1 *getMask(void) const { return mask; };
protected:
// MOST OF THESE ARE NOT SUPPORTED YET -- WIP
union { // Single pointer, only one variant is used:
GFXcanvas1 *canvas1; ///< Canvas object if 1bpp format
GFXcanvas8 *canvas8; ///< Canvas object if 8bpp format
GFXcanvas16 *canvas16; ///< Canvas object if 16bpp
} canvas; ///< Union of different GFXcanvas types
GFXcanvas1 *mask; ///< 1bpp image mask (or NULL)
uint16_t *palette; ///< Color palette for 8bpp image (or NULL)
uint8_t format; ///< Canvas bundle type in use
void dealloc(void); ///< Free/deinitialize variables
friend class Adafruit_ImageReader; ///< Loading occurs here
};
/*!
@ -92,22 +93,23 @@ class Adafruit_Image {
for use.
*/
class Adafruit_ImageReader {
public:
Adafruit_ImageReader(FatFileSystem &fs);
~Adafruit_ImageReader(void);
ImageReturnCode drawBMP(char *filename, Adafruit_SPITFT &tft,
int16_t x, int16_t y, boolean transact = true);
ImageReturnCode loadBMP(char *filename, Adafruit_Image &img);
ImageReturnCode bmpDimensions(char *filename, int32_t *w, int32_t *h);
void printStatus(ImageReturnCode stat, Stream &stream=Serial);
private:
FatFileSystem *filesys;
File file;
ImageReturnCode coreBMP(char *filename, Adafruit_SPITFT *tft,
uint16_t *dest, int16_t x, int16_t y, Adafruit_Image *img,
boolean transact);
uint16_t readLE16(void);
uint32_t readLE32(void);
public:
Adafruit_ImageReader(FatFileSystem &fs);
~Adafruit_ImageReader(void);
ImageReturnCode drawBMP(char *filename, Adafruit_SPITFT &tft, int16_t x,
int16_t y, boolean transact = true);
ImageReturnCode loadBMP(char *filename, Adafruit_Image &img);
ImageReturnCode bmpDimensions(char *filename, int32_t *w, int32_t *h);
void printStatus(ImageReturnCode stat, Stream &stream = Serial);
private:
FatFileSystem *filesys;
File file;
ImageReturnCode coreBMP(char *filename, Adafruit_SPITFT *tft, uint16_t *dest,
int16_t x, int16_t y, Adafruit_Image *img,
boolean transact);
uint16_t readLE16(void);
uint32_t readLE32(void);
};
#endif // __ADAFRUIT_IMAGE_READER_H__

View file

@ -14,51 +14,51 @@
*/
void Adafruit_Image_EPD::draw(Adafruit_EPD &epd, int16_t x, int16_t y) {
int16_t col = x, row = y;
if(format == IMAGE_1 ) {
if (format == IMAGE_1) {
uint8_t *buffer = canvas.canvas1->getBuffer();
uint8_t i, c;
while(row < y + canvas.canvas1->height()) {
for (i = 0; i < 8; i++) {
if ((*buffer & (0x80 >> i)) > 0) {
c = EPD_BLACK; // try to infer black
} else {
c = EPD_WHITE;
}
epd.writePixel(col, row, c);
col++;
if (col == x + canvas.canvas1->width()) {
col = x;
row++;
}
while (row < y + canvas.canvas1->height()) {
for (i = 0; i < 8; i++) {
if ((*buffer & (0x80 >> i)) > 0) {
c = EPD_BLACK; // try to infer black
} else {
c = EPD_WHITE;
}
buffer++;
};
} else if(format == IMAGE_8 ) {
} else if(format == IMAGE_16) {
uint16_t *buffer = canvas.canvas16->getBuffer();
while(row < y + canvas.canvas16->height()) {
// RGB in 565 format
uint8_t r = (*buffer & 0xf800) >> 8;
uint8_t g = (*buffer & 0x07e0) >> 3;
uint8_t b = (*buffer & 0x001f) << 3;
uint8_t c = 0;
if ((r < 0x80) && (g < 0x80) && (b < 0x80)) {
c = EPD_BLACK; // try to infer black
} else if ((r >= 0x80) && (g >= 0x80) && (b >= 0x80)) {
c = EPD_WHITE;
} else if (r >= 0x80) {
c = EPD_RED; //try to infer red color
}
epd.writePixel(col, row, c);
col++;
if (col == x + canvas.canvas16->width()) {
if (col == x + canvas.canvas1->width()) {
col = x;
row++;
}
buffer++;
}
buffer++;
};
} else if (format == IMAGE_8) {
} else if (format == IMAGE_16) {
uint16_t *buffer = canvas.canvas16->getBuffer();
while (row < y + canvas.canvas16->height()) {
// RGB in 565 format
uint8_t r = (*buffer & 0xf800) >> 8;
uint8_t g = (*buffer & 0x07e0) >> 3;
uint8_t b = (*buffer & 0x001f) << 3;
uint8_t c = 0;
if ((r < 0x80) && (g < 0x80) && (b < 0x80)) {
c = EPD_BLACK; // try to infer black
} else if ((r >= 0x80) && (g >= 0x80) && (b >= 0x80)) {
c = EPD_WHITE;
} else if (r >= 0x80) {
c = EPD_RED; // try to infer red color
}
epd.writePixel(col, row, c);
col++;
if (col == x + canvas.canvas16->width()) {
col = x;
row++;
}
buffer++;
};
}
}

View file

@ -15,18 +15,19 @@
#ifndef __ADAFRUIT_IMAGE_READER_EPD_H__
#define __ADAFRUIT_IMAGE_READER_EPD_H__
#include "Adafruit_ImageReader.h"
#include "Adafruit_EPD.h"
#include "Adafruit_ImageReader.h"
/*!
@brief Data bundle returned with an image loaded to RAM. Used by
ImageReader.loadBMP() and Image.draw(), not ImageReader.drawBMP().
*/
class Adafruit_Image_EPD : public Adafruit_Image {
public:
void draw(Adafruit_EPD &epd, int16_t x, int16_t y);
protected:
friend class Adafruit_ImageReader; ///< Loading occurs here
public:
void draw(Adafruit_EPD &epd, int16_t x, int16_t y);
protected:
friend class Adafruit_ImageReader; ///< Loading occurs here
};
#endif // __ADAFRUIT_IMAGE_READER_EPD_H__

View file

@ -1,4 +1,4 @@
# Adafruit_ImageReader [![Build Status](https://travis-ci.com/adafruit/Adafruit_ImageReader.svg?branch=master)](https://travis-ci.com/adafruit/Adafruit_ImageReader)
# Adafruit_ImageReader ![Build Status](https://github.com/adafruit/Adafruit_ImageReader/workflows/Arduino%20Library%20CI/badge.svg)
Companion library for Adafruit_GFX to load images from SD card.

View file

@ -1,5 +1,5 @@
name=Adafruit ImageReader Library
version=2.3.3
version=2.3.4
author=Adafruit
maintainer=Adafruit <info@adafruit.com>
sentence=Companion library for Adafruit_GFX and Adafruit_EPD to load images from SD card.
@ -7,4 +7,4 @@ paragraph=Install this library in addition to Adafruit_GFX and the display libra
category=Display
url=https://github.com/adafruit/Adafruit_ImageReader
architectures=*
depends=Adafruit GFX Library, Adafruit ST7735 and ST7789 Library, Adafruit HX8357 Library, Adafruit ILI9341, Adafruit SSD1351 library, Adafruit SSD1331 OLED Driver Library for Arduino, Adafruit SPIFlash, SdFat - Adafruit Fork, Adafruit EPD, Adafruit seesaw Library
depends=Adafruit GFX Library, Adafruit ST7735 and ST7789 Library, Adafruit HX8357 Library, Adafruit ILI9341, Adafruit SSD1351 library, Adafruit SSD1331 OLED Driver Library for Arduino, Adafruit SPIFlash, SdFat - Adafruit Fork, Adafruit EPD