bool inline DrawBMP24(ILI9341_t3 *d, int cs, const char *FileName, uint8_t x = 0, uint16_t y = 0) {
File bmpFile;
int bmpWidth, bmpHeight; // W+H in pixels
int w, h, row, col;
uint8_t bmpDepth; // Bit depth (currently must be 24)
uint32_t bmpImageoffset; // Start of image data in file
uint32_t rowSize; // Not always = bmpWidth; may have padding
uint8_t sdbuffer[3 * 8]; // pixel buffer (R+G+B per pixel)
uint8_t buffidx = sizeof(sdbuffer); // Current position in sdbuffer
boolean flip = true; // BMP is stored bottom-to-top
uint8_t r, g, b; // holders for red green blue
uint32_t pos = 0; // file position
uint16_t awColors[320]; // hold colors for one row at a time...
uint16_t Read16; // file read placeholder
uint32_t Read32; // file read placeholder
// let's not test begin, reason is if you create a file SD exists and will fail here
// just use any existing object
// we will trap file open next
SD.begin(cs);
bmpFile = SD.open(FileName, FILE_READ);
if (!bmpFile){
//Serial.print("SD.open: ");
//Serial.println(bmpFile);
return false;
}
if ((x >= d->width()) || (y >= d->height())) {
return false;
}
// Parse BMP header
((uint8_t *)&Read16)[0] = bmpFile.read();
((uint8_t *)&Read16)[1] = bmpFile.read();
if (Read16 == 0x4D42) {
// ignore read
((uint8_t *)&Read32)[0] = bmpFile.read();
((uint8_t *)&Read32)[1] = bmpFile.read();
((uint8_t *)&Read32)[2] = bmpFile.read();
((uint8_t *)&Read32)[3] = bmpFile.read();
// ignore read
((uint8_t *)&Read32)[0] = bmpFile.read();
((uint8_t *)&Read32)[1] = bmpFile.read();
((uint8_t *)&Read32)[2] = bmpFile.read();
((uint8_t *)&Read32)[3] = bmpFile.read();
// read offset
((uint8_t *)&Read32)[0] = bmpFile.read();
((uint8_t *)&Read32)[1] = bmpFile.read();
((uint8_t *)&Read32)[2] = bmpFile.read();
((uint8_t *)&Read32)[3] = bmpFile.read();
bmpImageoffset = Read32;
// ignore read
((uint8_t *)&Read32)[0] = bmpFile.read();
((uint8_t *)&Read32)[1] = bmpFile.read();
((uint8_t *)&Read32)[2] = bmpFile.read();
((uint8_t *)&Read32)[3] = bmpFile.read();
// read width
((uint8_t *)&Read32)[0] = bmpFile.read();
((uint8_t *)&Read32)[1] = bmpFile.read();
((uint8_t *)&Read32)[2] = bmpFile.read();
((uint8_t *)&Read32)[3] = bmpFile.read();
bmpWidth = Read32;
// read height
((uint8_t *)&Read32)[0] = bmpFile.read();
((uint8_t *)&Read32)[1] = bmpFile.read();
((uint8_t *)&Read32)[2] = bmpFile.read();
((uint8_t *)&Read32)[3] = bmpFile.read();
bmpHeight = Read32;
// get planes
((uint8_t *)&Read16)[0] = bmpFile.read();
((uint8_t *)&Read16)[1] = bmpFile.read();
if (Read16 == 1) { // # planes -- must be '1'
// read depth
((uint8_t *)&Read16)[0] = bmpFile.read();
((uint8_t *)&Read16)[1] = bmpFile.read();
bmpDepth = Read16; // bits per pixel
// read compression
((uint8_t *)&Read32)[0] = bmpFile.read();
((uint8_t *)&Read32)[1] = bmpFile.read();
((uint8_t *)&Read32)[2] = bmpFile.read();
((uint8_t *)&Read32)[3] = bmpFile.read();
if ((bmpDepth == 24) && (Read32 == 0)) { // 0 = uncompressed
// if you got this far, legit image file
rowSize = (bmpWidth * 3 + 3) & ~3;
if (bmpHeight < 0) {
bmpHeight = -bmpHeight;
flip = false;
}
w = bmpWidth;
h = bmpHeight;
if ((x + w - 1) >= d->width()) w = d->width() - x;
if ((y + h - 1) >= d->height()) h = d->height() - y;
for (row = 0; row < h; row++) { // For each scanline...
if (flip) // Bitmap is stored bottom-to-top order (normal BMP)
pos = bmpImageoffset + (bmpHeight - 1 - row) * rowSize;
else // Bitmap is stored top-to-bottom
pos = bmpImageoffset + row * rowSize;
if (bmpFile.position() != pos) { // Need seek?
bmpFile.seek(pos);
buffidx = sizeof(sdbuffer); // Force buffer reload
}
for (col = 0; col < w; col++) { // For each pixel...
// Time to read more pixel data?
if (buffidx >= sizeof(sdbuffer)) { // Indeed
bmpFile.read(sdbuffer, sizeof(sdbuffer));
buffidx = 0; // Set index to beginning
}
b = sdbuffer[buffidx++];
g = sdbuffer[buffidx++];
r = sdbuffer[buffidx++];
awColors[col] = d->color565(r, g, b);
}
d->writeRect(0, row, w, 1, awColors);
}
}
else {
return false;
}
}
else {
return false;
}
}
bmpFile.close();
return true;
}