1 | void bmpDraw(String filename, int x, int y) {
|
2 |
|
3 | File bmpFile;
|
4 | int bmpWidth, bmpHeight; // W+H in Pixel
|
5 | uint8_t bmpDepth; // Bittiefe (muss derzeit 24 sein)
|
6 | uint32_t bmpImageoffset; // Beginn der Bilddaten in der Datei
|
7 | uint32_t rowSize; // Nicht immer = bmpWidth; kann Füllung haben
|
8 | uint8_t sdbuffer[3 * BUFFPIXEL]; // Pixel im Puffer (R+G+B pro Pixel)
|
9 | uint16_t lcdbuffer[BUFFPIXEL]; // Pixel-Ausgangspuffer (16-Bit pro Pixel)
|
10 | uint8_t buffidx = sizeof(sdbuffer); // Aktuelle Position im sdbuffer
|
11 | boolean goodBmp = false; // Bei gültigem Header-Parsing auf true setzen
|
12 | boolean flip = true; // BMP wird von unten nach oben gespeichert
|
13 | int w, h, row, col;
|
14 | uint8_t r, g, b;
|
15 | uint32_t pos = 0;
|
16 | uint8_t lcdidx = 0;
|
17 | boolean first = true;
|
18 |
|
19 | if ((x >= 64) || (y >= 32)) return; // zu groß
|
20 |
|
21 | // Angeforderte Datei auf SD-Karte öffnen
|
22 | if (!(bmpFile = SPIFFS.open(filename, "r"))) return; // keine Datei gefunden
|
23 |
|
24 | // Parse BMP header
|
25 | if (read16(bmpFile) == 0x4D42) // BMP-Signatur
|
26 | {
|
27 | Serial.print(F("Dateigröße: ")); Serial.println(read32(bmpFile));
|
28 |
|
29 | read32(bmpFile); // Erzeuger-Bytes lesen & ignorieren
|
30 | bmpImageoffset = read32(bmpFile); // Beginn der Bilddaten
|
31 |
|
32 | Serial.print(F("Headergröße: ")); Serial.println(read32(bmpFile));
|
33 |
|
34 | bmpWidth = read32(bmpFile);
|
35 | bmpHeight = read32(bmpFile);
|
36 | if (read16(bmpFile) == 1) // # Ebenen -- muss '1' sein
|
37 | {
|
38 | bmpDepth = read16(bmpFile); // Bits pro Pixel
|
39 | Serial.print(F("Bittiefe: ")); Serial.println(bmpDepth);
|
40 |
|
41 | if ((bmpDepth == 24) && (read32(bmpFile) == 0)) // 0 = unkomprimiert
|
42 | {
|
43 | goodBmp = true; // Unterstütztes BMP-Format -- weiter!
|
44 |
|
45 | rowSize = (bmpWidth * 3 + 3) & ~3;
|
46 |
|
47 | if (bmpHeight < 0) {
|
48 | bmpHeight = -bmpHeight;
|
49 | flip = false;
|
50 | }
|
51 |
|
52 | // Crop area to be loaded
|
53 | w = bmpWidth;
|
54 | h = bmpHeight;
|
55 | if ((x + w - 1) >= 64) w = 64 - x; // Breite
|
56 | if ((y + h - 1) >= 32) h = 32 - y; // Höhe
|
57 |
|
58 | for (row = 0; row < h; row++)
|
59 | {
|
60 | if (flip)
|
61 | pos = bmpImageoffset + (bmpHeight - 1 - row) * rowSize;
|
62 |
|
63 | else // Bitmap wird von oben nach unten gespeichert
|
64 | pos = bmpImageoffset + row * rowSize;
|
65 |
|
66 | if (bmpFile.position() != pos) { // suchen?
|
67 | bmpFile.seek(pos);
|
68 | buffidx = sizeof(sdbuffer); // Puffer-Neuladen erzwingen
|
69 | }
|
70 |
|
71 | for (col = 0; col < w; col++) // Für jede Spalte...
|
72 | {
|
73 |
|
74 | // Zeit, mehr Pixeldaten zu lesen?
|
75 | if (buffidx >= sizeof(sdbuffer)) { // tatsächlich
|
76 |
|
77 | bmpFile.read(sdbuffer, sizeof(sdbuffer));
|
78 | buffidx = 0; // Index auf Anfang setzen
|
79 | }
|
80 |
|
81 | // Pixel von BMP in TFT-Format konvertieren
|
82 | b = sdbuffer[buffidx++];
|
83 | g = sdbuffer[buffidx++];
|
84 | r = sdbuffer[buffidx++];
|
85 |
|
86 | display.drawPixelRGB888(col, row, r, g, b);
|
87 | } // Endpixel
|
88 | } // Scanline beenden
|
89 | }
|
90 | }
|
91 | }
|
92 |
|
93 | bmpFile.close();
|
94 | if (!goodBmp) Serial.println("FEHLER"); // BMP Format nicht unterstützt
|
95 | }
|