-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathPhotoShow.ino
172 lines (147 loc) · 5.95 KB
/
PhotoShow.ino
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
#include "FlixCapacitor.h"
#if defined(ENABLE_TFT) && defined(ENABLE_AUDIO_SD)
#define BUFFPIXEL 32
#include <ILI9341_t3.h>
File bmpFile;
void resetScreen() {
tft.fillScreen(tft.color565(0x20, 0x20, 0x20));
tft.setTextColor(ILI9341_YELLOW);
tft.setTextSize(3);
tft.setTextWrap(false);
tft.setCursor(20, 100);
tft.print("FilxCapacitor v1");
tft.setTextSize(1);
tft.setCursor(30, 140);
tft.setTextColor(ILI9341_WHITE);
tft.print("Made for Fil to aid in quick recovery :=) ");
}
void bmpDraw(char *filename, uint8_t x, uint16_t y) {
int bmpWidth, bmpHeight; // W+H in pixels
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 * BUFFPIXEL]; // pixel buffer (R+G+B per pixel)
uint8_t buffidx = sizeof(sdbuffer); // Current position in sdbuffer
boolean goodBmp = false; // Set to true on valid header parse
boolean flip = true; // BMP is stored bottom-to-top
int w, h, row, col;
uint8_t r, g, b;
uint32_t pos = 0, startTime = millis();
uint16_t awColors[320]; // hold colors for one row at a time...
if ((x >= tft.width()) || (y >= tft.height()))
return;
Serial.println();
Serial.print(F("Loading image ["));
Serial.print(filename);
Serial.print("]... ");
bmpFile = SD.open(filename);
// Open requested file on SD card
if (!bmpFile) {
Serial.println(F("File not found"));
return;
}
// Parse BMP header
if (read16(bmpFile) == 0x4D42) { // BMP signature
#ifdef DEBUG_IMAGES
Serial.print(F("File size: "));
Serial.println(read32(bmpFile));
#else
read32(bmpFile);
#endif
(void) read32(bmpFile); // Read & ignore creator bytes
bmpImageoffset = read32(bmpFile); // Start of image data
#ifdef DEBUG_IMAGES
Serial.print(F("Image Offset: "));
Serial.println(bmpImageoffset, DEC);
// Read DIB header
Serial.print(F("Header size: "));
Serial.println(read32(bmpFile));
#else
read32(bmpFile);
#endif
bmpWidth = read32(bmpFile);
bmpHeight = read32(bmpFile);
if (read16(bmpFile) == 1) { // # planes -- must be '1'
bmpDepth = read16(bmpFile); // bits per pixel
#ifdef DEBUG_IMAGES
Serial.print(F("Bit Depth: "));
Serial.println(bmpDepth);
#endif
if ((bmpDepth == 24) && (read32(bmpFile) == 0)) { // 0 = uncompressed
goodBmp = true; // Supported BMP format -- proceed!
#ifdef DEBUG_IMAGES
Serial.print(F("Image size: "));
Serial.print(bmpWidth);
Serial.print('x');
Serial.println(bmpHeight);
#endif
// BMP rows are padded (if needed) to 4-byte boundary
rowSize = (bmpWidth * 3 + 3) & ~3;
// If bmpHeight is negative, image is in top-down order.
// This is not canon but has been observed in the wild.
if (bmpHeight < 0) {
bmpHeight = -bmpHeight;
flip = false;
}
// Crop area to be loaded
w = bmpWidth;
h = bmpHeight;
if ((x + w - 1) >= tft.width())
w = tft.width() - x;
if ((y + h - 1) >= tft.height())
h = tft.height() - y;
for (row = 0; row < h; row++) { // For each scanline...
// Seek to start of scan line. It might seem labor-
// intensive to be doing this on every line, but this
// method covers a lot of gritty details like cropping
// and scanline 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)
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
}
// Convert pixel from BMP to TFT format, push to display
b = sdbuffer[buffidx++];
g = sdbuffer[buffidx++];
r = sdbuffer[buffidx++];
awColors[col] = tft.color565(r, g, b);
} // end pixel
tft.writeRect(0, row, w, 1, awColors);
} // end scanline
Serial.print(F(", loaded in ["));
Serial.print(millis() - startTime);
Serial.println("] ms");
} // end goodBmp
}
}
bmpFile.close();
if (!goodBmp)
Serial.println(F("BMP format not recognized."));
}
uint16_t read16(File &f) {
uint16_t result;
((uint8_t *) &result)[0] = f.read(); // LSB
((uint8_t *) &result)[1] = f.read(); // MSB
return result;
}
uint32_t read32(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;
}
#endif // ENABLE_TFT