89 lines
		
	
	
		
			2.2 KiB
		
	
	
	
		
			C++
		
	
	
	
			
		
		
	
	
			89 lines
		
	
	
		
			2.2 KiB
		
	
	
	
		
			C++
		
	
	
	
| // Bodmers BMP image rendering function
 | |
| 
 | |
| void drawBmp(const char *filename, int16_t x, int16_t y) {
 | |
| 
 | |
|   if ((x >= tft.width()) || (y >= tft.height())) return;
 | |
| 
 | |
|   fs::File bmpFS;
 | |
| 
 | |
|   // Open requested file on SD card
 | |
|   bmpFS = SPIFFS.open(filename, "r");
 | |
| 
 | |
|   if (!bmpFS)
 | |
|   {
 | |
|     Serial.print("File not found");
 | |
|     return;
 | |
|   }
 | |
| 
 | |
|   uint32_t seekOffset;
 | |
|   uint16_t w, h, row, col;
 | |
|   uint8_t  r, g, b;
 | |
| 
 | |
|   uint32_t startTime = millis();
 | |
| 
 | |
|   if (read16(bmpFS) == 0x4D42)
 | |
|   {
 | |
|     read32(bmpFS);
 | |
|     read32(bmpFS);
 | |
|     seekOffset = read32(bmpFS);
 | |
|     read32(bmpFS);
 | |
|     w = read32(bmpFS);
 | |
|     h = read32(bmpFS);
 | |
| 
 | |
|     if ((read16(bmpFS) == 1) && (read16(bmpFS) == 24) && (read32(bmpFS) == 0))
 | |
|     {
 | |
|       y += h - 1;
 | |
| 
 | |
|       tft.setSwapBytes(true);
 | |
|       bmpFS.seek(seekOffset);
 | |
| 
 | |
|       uint16_t padding = (4 - ((w * 3) & 3)) & 3;
 | |
|       uint8_t lineBuffer[w * 3 + padding];
 | |
| 
 | |
|       for (row = 0; row < h; row++) {
 | |
|         
 | |
|         bmpFS.read(lineBuffer, sizeof(lineBuffer));
 | |
|         uint8_t*  bptr = lineBuffer;
 | |
|         uint16_t* tptr = (uint16_t*)lineBuffer;
 | |
|         // Convert 24 to 16 bit colours
 | |
|         for (uint16_t col = 0; col < w; col++)
 | |
|         {
 | |
|           b = *bptr++;
 | |
|           g = *bptr++;
 | |
|           r = *bptr++;
 | |
|           *tptr++ = ((r & 0xF8) << 8) | ((g & 0xFC) << 3) | (b >> 3);
 | |
|         }
 | |
| 
 | |
|         // Push the pixel row to screen, pushImage will crop the line if needed
 | |
|         // y is decremented as the BMP image is drawn bottom up
 | |
|         tft.pushImage(x, y--, w, 1, (uint16_t*)lineBuffer);
 | |
|       }
 | |
|       Serial.print("Loaded in "); Serial.print(millis() - startTime);
 | |
|       Serial.println(" ms");
 | |
|     }
 | |
|     else Serial.println("BMP format not recognized.");
 | |
|   }
 | |
|   bmpFS.close();
 | |
| }
 | |
| 
 | |
| // These read 16- and 32-bit types from the SD card file.
 | |
| // BMP data is stored little-endian, Arduino is little-endian too.
 | |
| // May need to reverse subscript order if porting elsewhere.
 | |
| 
 | |
| uint16_t read16(fs::File &f) {
 | |
|   uint16_t result;
 | |
|   ((uint8_t *)&result)[0] = f.read(); // LSB
 | |
|   ((uint8_t *)&result)[1] = f.read(); // MSB
 | |
|   return result;
 | |
| }
 | |
| 
 | |
| uint32_t read32(fs::File &f) {
 | |
|   uint32_t result;
 | |
|   ((uint8_t *)&result)[0] = f.read(); // LSB
 | |
|   ((uint8_t *)&result)[1] = f.read();
 | |
|   ((uint8_t *)&result)[2] = f.read();
 | |
|   ((uint8_t *)&result)[3] = f.read(); // MSB
 | |
|   return result;
 | |
| }
 | |
| 
 |