71{
72 File file;
73 bool valid = false;
74 bool flip = true;
75 uint32_t startTime = millis();
76
77 if ((x >= display.width()) || (y >= display.height())) return;
78
80 DEBUG.print(
"Loading image '");
81 DEBUG.print(filename);
83
84 file = fs.open(String("/") + filename, FILE_READ);
85 if (!file) {
86 DEBUG.print(
"File not found");
87 return;
88 }
89
90
91 if (
read16(file) == 0x4D42) {
92 uint32_t fileSize =
read32(file);
93 uint32_t creatorBytes =
read32(file);
94 uint32_t imageOffset =
read32(file);
95 uint32_t headerSize =
read32(file);
96 uint32_t width =
read32(file);
97 uint32_t height =
read32(file);
98 uint16_t planes =
read16(file);
99 uint16_t depth =
read16(file);
100 uint32_t format =
read32(file);
101 if ((planes == 1) && ((format == 0) || (format == 3))) {
102 DEBUG.print(
"File size: ");
DEBUG.println(fileSize);
103 DEBUG.print(
"Image Offset: ");
DEBUG.println(imageOffset);
104 DEBUG.print(
"Header size: ");
DEBUG.println(headerSize);
105 DEBUG.print(
"Bit Depth: ");
DEBUG.println(depth);
106 DEBUG.print(
"Image size: ");
109 DEBUG.println(height);
110
111 uint32_t rowSize = (width * depth / 8 + 3) & ~3;
112 if (depth < 8) rowSize = ((width * depth + 8 - depth) / 8 + 3) & ~3;
113 if (height < 0) {
114 height = -height;
115 flip = false;
116 }
117 uint16_t w = width;
118 uint16_t h = height;
119 if ((x + w - 1) >= display.width()) w = display.width() - x;
120 if ((y + h - 1) >= display.height()) h = display.height() - y;
121 valid = true;
122 uint8_t bitmask = 0xFF;
123 uint8_t bitshift = 8 - depth;
124 uint16_t red, green, blue;
125 bool whitish, colored;
126 if (depth == 1) with_color = false;
127 if (depth <= 8) {
128 if (depth < 8) bitmask >>= depth;
129 file.seekSet(54);
130 for (uint16_t pn = 0; pn < (1 << depth); pn++) {
131 blue = file.read();
132 green = file.read();
133 red = file.read();
134 file.read();
135 whitish = with_color ? ((red > 0x80) && (green > 0x80) && (blue > 0x80)) : ((red + green + blue) > 3 * 0x80);
136 colored = (red > 0xF0) || ((green > 0xF0) && (blue > 0xF0));
137 if (0 == pn % 8) mono_palette_buffer[pn / 8] = 0;
138 mono_palette_buffer[pn / 8] |= whitish << pn % 8;
139 if (0 == pn % 8) color_palette_buffer[pn / 8] = 0;
140 color_palette_buffer[pn / 8] |= colored << pn % 8;
141 }
142 }
143
144 uint32_t rowPosition = flip ? imageOffset + (height - h) * rowSize : imageOffset;
145 for (uint16_t row = 0; row < h; row++, rowPosition += rowSize) {
146 uint32_t in_remain = rowSize;
147 uint32_t in_idx = 0;
148 uint32_t in_bytes = 0;
149 uint8_t in_byte = 0;
150 uint8_t in_bits = 0;
152 file.seekSet(rowPosition);
153 for (uint16_t col = 0; col < w; col++) {
154
155 if (in_idx >= in_bytes) {
156 in_bytes = file.read(input_buffer, in_remain > sizeof(input_buffer) ? sizeof(input_buffer) : in_remain);
157 in_remain -= in_bytes;
158 in_idx = 0;
159 }
160 switch (depth) {
161 case 24:
162 blue = input_buffer[in_idx++];
163 green = input_buffer[in_idx++];
164 red = input_buffer[in_idx++];
165 whitish = with_color ? ((red > 0x80) && (green > 0x80) && (blue > 0x80)) : ((red + green + blue) > 3 * 0x80);
166 colored = (red > 0xF0) || ((green > 0xF0) && (blue > 0xF0));
167 break;
168 case 16:
169 {
170 uint8_t lsb = input_buffer[in_idx++];
171 uint8_t msb = input_buffer[in_idx++];
172 if (format == 0) {
173 blue = (lsb & 0x1F) << 3;
174 green = ((msb & 0x03) << 6) | ((lsb & 0xE0) >> 2);
175 red = (msb & 0x7C) << 1;
176 } else {
177 blue = (lsb & 0x1F) << 3;
178 green = ((msb & 0x07) << 5) | ((lsb & 0xE0) >> 3);
179 red = (msb & 0xF8);
180 }
181 whitish = with_color ? ((red > 0x80) && (green > 0x80) && (blue > 0x80)) : ((red + green + blue) > 3 * 0x80);
182 colored = (red > 0xF0) || ((green > 0xF0) && (blue > 0xF0));
183 }
184 break;
185 case 1:
186 case 4:
187 case 8:
188 {
189 if (0 == in_bits) {
190 in_byte = input_buffer[in_idx++];
191 in_bits = 8;
192 }
193 uint16_t pn = (in_byte >> bitshift) & bitmask;
194 whitish = mono_palette_buffer[pn / 8] & (0x1 << pn % 8);
195 colored = color_palette_buffer[pn / 8] & (0x1 << pn % 8);
196 in_byte <<= depth;
197 in_bits -= depth;
198 }
199 break;
200 }
201 if (whitish)
203 else if (colored && with_color)
205 else
207 uint16_t yrow = y + (flip ? h - row - 1 : row);
208 display.drawPixel(x + col, yrow, color);
209 }
210 }
211 DEBUG.print(
"loaded in ");
DEBUG.print(millis() - startTime);
DEBUG.println(
" ms");
212 }
213 }
214 file.close();
215 if (!valid)
216 DEBUG.println(
"bitmap format not handled.");
217}