1 | mein Header
|
2 | #ifndef __MYPNGDEC__
|
3 | #define __MYPNGDEC__
|
4 |
|
5 |
|
6 | #include <Arduino.h>
|
7 | #include "FS.h"
|
8 | #include "SD.h"
|
9 | #include "SPI.h"
|
10 | #include <TFT_eSPI.h>
|
11 | #include <pngdec.h>
|
12 |
|
13 | #define MAX_IMAGE_WIDTH 320 // Adjust for your images
|
14 |
|
15 |
|
16 |
|
17 |
|
18 | class PngClass {
|
19 | public:
|
20 | void InitPngLib(TFT_eSPI tft );
|
21 | void listDir(fs::FS &fs, const char * dirname, uint8_t levels);
|
22 | void DrawPng(int x, int y,const String PngName);
|
23 |
|
24 | private:
|
25 | TFT_eSPI * _tft;
|
26 | File pngfile;
|
27 | PNG _png;
|
28 | int xpos;
|
29 | int ypos;
|
30 | void * pngOpen(const char *filename, int32_t *size);
|
31 | void pngClose(void *handle);
|
32 | int32_t pngRead(PNGFILE *page, uint8_t *buffer, int32_t length);
|
33 | int32_t pngSeek(PNGFILE *page, int32_t position);
|
34 | String readFile(fs::FS &fs, const char * path);
|
35 | void pngDraw(PNGDRAW *pDraw);
|
36 | };
|
37 |
|
38 | #endif
|
39 |
|
40 | mein C++ File
|
41 | #include "MyPngLib.h"
|
42 |
|
43 | void PngClass::InitPngLib(TFT_eSPI tft )
|
44 | {
|
45 | _tft = tft;
|
46 | //SPIClass spi = SPIClass(VSPI);
|
47 |
|
48 | Serial.println("**********************************************************");
|
49 | Serial.print("MOSI: ");
|
50 | Serial.println(MOSI);
|
51 | Serial.print("MISO: ");
|
52 | Serial.println(MISO);
|
53 | Serial.print("SCK: ");
|
54 | Serial.println(SCK);
|
55 | Serial.print("SS: ");
|
56 | Serial.println(SS);
|
57 | Serial.println("**********************************************************");
|
58 |
|
59 | //if (!SD.begin(SS, spi, 80000000))
|
60 | if (!SD.begin(SS))
|
61 | {
|
62 | Serial.println("initialization failed!");
|
63 | }
|
64 |
|
65 | Serial.println("initialization done.");
|
66 | listDir(SD, "/", 0);
|
67 |
|
68 | }
|
69 |
|
70 |
|
71 |
|
72 | void PngClass::listDir(fs::FS &fs, const char * dirname, uint8_t levels)
|
73 | {
|
74 | Serial.printf("Listing directory: %s\n", dirname);
|
75 |
|
76 | File root = fs.open(dirname);
|
77 | if (!root) {
|
78 | Serial.println("Failed to open directory");
|
79 | return;
|
80 | }
|
81 | if (!root.isDirectory()) {
|
82 | Serial.println("Not a directory");
|
83 | return;
|
84 | }
|
85 |
|
86 | File file = root.openNextFile();
|
87 | while (file) {
|
88 | if (file.isDirectory()) {
|
89 | Serial.print(" DIR : ");
|
90 | Serial.println(file.name());
|
91 | if (levels) {
|
92 | listDir(fs, file.path(), levels - 1);
|
93 | }
|
94 | } else {
|
95 | Serial.print(" FILE: ");
|
96 | Serial.print(file.name());
|
97 | Serial.print(" SIZE: ");
|
98 | Serial.println(file.size());
|
99 | }
|
100 | file = root.openNextFile();
|
101 | }
|
102 | }
|
103 |
|
104 |
|
105 | void * PngClass::pngOpen(const char *filename, int32_t *size)
|
106 | {
|
107 | Serial.printf("Attempting to open %s\n", filename);
|
108 | File _pngfile = SD.open(filename, "r");
|
109 | *size = _pngfile.size();
|
110 | return &pngfile;
|
111 | }
|
112 |
|
113 | void PngClass::pngClose(void *handle)
|
114 | {
|
115 | File _pngfile = *((File*)handle);
|
116 | if (_pngfile) _pngfile.close();
|
117 | }
|
118 |
|
119 | int32_t PngClass::pngRead(PNGFILE *page, uint8_t *buffer, int32_t length)
|
120 | {
|
121 | if (!pngfile) return 0;
|
122 | page = page; // Avoid warning
|
123 | return pngfile.read(buffer, length);
|
124 | }
|
125 |
|
126 | int32_t PngClass::pngSeek(PNGFILE *page, int32_t position)
|
127 | {
|
128 | if (!pngfile) return 0;
|
129 | page = page; // Avoid warning
|
130 | return pngfile.seek(position);
|
131 | }
|
132 |
|
133 | //=========================================v==========================================
|
134 | // _pngDraw
|
135 | //====================================================================================
|
136 | // This next function will be called during decoding of the _png file to
|
137 | // render each image line to the _tft. If you use a different _tft library
|
138 | // you will need to adapt this function to suit.
|
139 | // Callback function to draw pixels to the display
|
140 | void PngClass::pngDraw(PNGDRAW *pDraw)
|
141 | {
|
142 | uint16_t lineBuffer[MAX_IMAGE_WIDTH];
|
143 | static uint16_t dmaBuffer[MAX_IMAGE_WIDTH]; // static so buffer persists after fn exit
|
144 | _png.getLineAsRGB565(pDraw, lineBuffer, PNG_RGB565_BIG_ENDIAN, 0xffffffff);
|
145 | _tft->pushImageDMA(xpos, ypos + pDraw->y, pDraw->iWidth, 1, lineBuffer, dmaBuffer);
|
146 | }
|
147 |
|
148 |
|
149 | void PngClass::DrawPng(int x, int y,const String PngName)
|
150 | {
|
151 | xpos = x;
|
152 | ypos = y;
|
153 |
|
154 | int16_t rc = _png.open(PngName.c_str(), pngOpen, pngClose, pngRead, pngSeek, pngDraw);
|
155 | if (rc == PNG_SUCCESS) {
|
156 | _tft->startWrite();
|
157 | Serial.printf("image specs: (%d x %d), %d bpp, pixel type: %d\n", _png.getWidth(), _png.getHeight(), _png.getBpp(), _png.getPixelType());
|
158 | uint32_t dt = millis();
|
159 | if (_png.getWidth() > MAX_IMAGE_WIDTH) {
|
160 | Serial.println("Image too wide for allocated lin buffer!");
|
161 | }
|
162 | else {
|
163 | rc = _png.decode(NULL, 0);
|
164 | _png.close();
|
165 | }
|
166 | _tft->endWrite();
|
167 | // How long did rendering take...
|
168 | Serial.print(millis()-dt); Serial.println("ms");
|
169 | }
|
170 | }
|
171 |
|
172 |
|
173 |
|
174 |
|
175 | String PngClass::readFile(fs::FS &fs, const char * path)
|
176 | {
|
177 | Serial.printf("Reading file: %s\r\n", path);
|
178 | File file = fs.open(path, "r");
|
179 | if(!file || file.isDirectory()){
|
180 | Serial.println("- empty file or failed to open file");
|
181 | return String();
|
182 | }
|
183 | Serial.println("- read from file:");
|
184 | String fileContent;
|
185 | while(file.available()){
|
186 | fileContent+=String((char)file.read());
|
187 | }
|
188 | Serial.println(fileContent);
|
189 | return fileContent;
|
190 | }
|