diff --git a/firmware/application/ui/ui_geomap.cpp b/firmware/application/ui/ui_geomap.cpp index a7cfd70a0..59c8a9f2a 100644 --- a/firmware/application/ui/ui_geomap.cpp +++ b/firmware/application/ui/ui_geomap.cpp @@ -454,14 +454,22 @@ bool GeoMap::draw_osm_file(int zoom, int tile_x, int tile_y, int relative_x, int return false; } std::vector line(clip_w); - for (int y = 0; y < clip_h; ++y) { - int source_row = src_y + y; - int dest_row = dest_y + y; - bmp.seek(src_x, source_row); - for (int x = 0; x < clip_w; ++x) { - bmp.read_next_px(line[x], true); + if (bmp.is_bottomup()) { + for (int y = clip_h - 1; y >= 0; --y) { + int source_row = src_y + y; + int dest_row = dest_y + y; + bmp.seek(src_x, source_row); + bmp.read_next_px_cnt(line.data(), clip_w, false); + display.draw_pixels({dest_x + r.left(), dest_row + r.top(), clip_w, 1}, line); + } + } else { + for (int y = 0; y < clip_h; ++y) { + int source_row = src_y + y; + int dest_row = dest_y + y; + bmp.seek(src_x, source_row); + bmp.read_next_px_cnt(line.data(), clip_w, false); + display.draw_pixels({dest_x + r.left(), dest_row + r.top(), clip_w, 1}, line); } - display.draw_pixels({dest_x + r.left(), dest_row + r.top(), clip_w, 1}, line); } return true; } diff --git a/firmware/common/bmpfile.cpp b/firmware/common/bmpfile.cpp index bc8e51340..4ef17aed0 100644 --- a/firmware/common/bmpfile.cpp +++ b/firmware/common/bmpfile.cpp @@ -200,6 +200,53 @@ bool BMPFile::read_next_px(ui::Color& px, bool seek = true) { return true; } +bool BMPFile::read_next_px_cnt(ui::Color* px, uint32_t count, bool seek) { + if (!is_opened) return false; + size_t bytesneeded = byte_per_px * count; + while (bytesneeded > 0) { // read in batches + size_t currusedbytes = bytesneeded > 512 ? 170 * byte_per_px : bytesneeded; // don't mind this magic number. + uint8_t buffer[currusedbytes]; + auto res = bmpimage.read(buffer, currusedbytes); + if (res.is_error()) return false; + for (uint32_t i = 0; i < currusedbytes; i += byte_per_px, px++) { + switch (type) { + case 5: { + // ARGB1555 + uint16_t val = buffer[i] | (buffer[i + 1] << 8); + // Extract components + //*a = (val >> 15) & 0x01; // 1-bit alpha + uint8_t r = (val >> 10) & 0x1F; // 5-bit red + uint8_t g = (val >> 5) & 0x1F; // 5-bit green + uint8_t b = (val)&0x1F; // 5-bit blue + // expand + r = (r << 3) | (r >> 2); + g = (g << 3) | (g >> 2); + b = (b << 3) | (b >> 2); + *px = ui::Color(r, g, b); + break; + } + case 2: // 32 + *px = ui::Color(buffer[i + 2], buffer[i + 1], buffer[i]); + break; + + case 4: { // 8-bit + // uint8_t index = buffer[0]; + // px = ui::Color(color_palette[index][2], color_palette[index][1], color_palette[index][0]); // Palette is BGR + // px = ui::Color(buffer[0]); // niy, since needs a lot of ram for the palette + break; + } + case 1: // 24 + default: + *px = ui::Color(buffer[i + 2], buffer[i + 1], buffer[i]); + break; + } + } + bytesneeded -= currusedbytes; + } + if (seek) advance_curr_px(count); + return true; +} + // if you set this, then the expanded part (or the newly created) will be filled with this color. but the expansion or the creation will be slower. void BMPFile::set_bg_color(ui::Color background) { bg = background; diff --git a/firmware/common/bmpfile.hpp b/firmware/common/bmpfile.hpp index f3709bd23..f0d6c1b0f 100644 --- a/firmware/common/bmpfile.hpp +++ b/firmware/common/bmpfile.hpp @@ -42,6 +42,7 @@ class BMPFile { uint32_t getbpr() { return byte_per_row; }; bool read_next_px(ui::Color& px, bool seek); + bool read_next_px_cnt(ui::Color* px, uint32_t count, bool seek); bool write_next_px(ui::Color& px); uint32_t get_real_height(); uint32_t get_width(); diff --git a/firmware/standalone/common/ui/bmpfile.cpp b/firmware/standalone/common/ui/bmpfile.cpp index bc8e51340..c0f129fce 100644 --- a/firmware/standalone/common/ui/bmpfile.cpp +++ b/firmware/standalone/common/ui/bmpfile.cpp @@ -173,7 +173,7 @@ bool BMPFile::read_next_px(ui::Color& px, bool seek = true) { //*a = (val >> 15) & 0x01; // 1-bit alpha uint8_t r = (val >> 10) & 0x1F; // 5-bit red uint8_t g = (val >> 5) & 0x1F; // 5-bit green - uint8_t b = (val)&0x1F; // 5-bit blue + uint8_t b = (val) & 0x1F; // 5-bit blue // expand r = (r << 3) | (r >> 2); g = (g << 3) | (g >> 2); @@ -200,6 +200,53 @@ bool BMPFile::read_next_px(ui::Color& px, bool seek = true) { return true; } +bool BMPFile::read_next_px_cnt(ui::Color* px, uint32_t count, bool seek) { + if (!is_opened) return false; + size_t bytesneeded = byte_per_px * count; + while (bytesneeded > 0) { // read in batches + size_t currusedbytes = bytesneeded > 256 ? 85 * byte_per_px : bytesneeded; // don't mind this magic number. + uint8_t buffer[currusedbytes]; + auto res = bmpimage.read(buffer, currusedbytes); + if (res.is_error()) return false; + for (uint32_t i = 0; i < currusedbytes; i += byte_per_px, px++) { + switch (type) { + case 5: { + // ARGB1555 + uint16_t val = buffer[i] | (buffer[i + 1] << 8); + // Extract components + //*a = (val >> 15) & 0x01; // 1-bit alpha + uint8_t r = (val >> 10) & 0x1F; // 5-bit red + uint8_t g = (val >> 5) & 0x1F; // 5-bit green + uint8_t b = (val) & 0x1F; // 5-bit blue + // expand + r = (r << 3) | (r >> 2); + g = (g << 3) | (g >> 2); + b = (b << 3) | (b >> 2); + *px = ui::Color(r, g, b); + break; + } + case 2: // 32 + *px = ui::Color(buffer[i + 2], buffer[i + 1], buffer[i]); + break; + + case 4: { // 8-bit + // uint8_t index = buffer[0]; + // px = ui::Color(color_palette[index][2], color_palette[index][1], color_palette[index][0]); // Palette is BGR + // px = ui::Color(buffer[0]); // niy, since needs a lot of ram for the palette + break; + } + case 1: // 24 + default: + *px = ui::Color(buffer[i + 2], buffer[i + 1], buffer[i]); + break; + } + } + bytesneeded -= currusedbytes; + } + if (seek) advance_curr_px(count); + return true; +} + // if you set this, then the expanded part (or the newly created) will be filled with this color. but the expansion or the creation will be slower. void BMPFile::set_bg_color(ui::Color background) { bg = background; diff --git a/firmware/standalone/common/ui/bmpfile.hpp b/firmware/standalone/common/ui/bmpfile.hpp index f3709bd23..f0d6c1b0f 100644 --- a/firmware/standalone/common/ui/bmpfile.hpp +++ b/firmware/standalone/common/ui/bmpfile.hpp @@ -42,6 +42,7 @@ class BMPFile { uint32_t getbpr() { return byte_per_row; }; bool read_next_px(ui::Color& px, bool seek); + bool read_next_px_cnt(ui::Color* px, uint32_t count, bool seek); bool write_next_px(ui::Color& px); uint32_t get_real_height(); uint32_t get_width(); diff --git a/firmware/standalone/common/ui/ui_geomap.cpp b/firmware/standalone/common/ui/ui_geomap.cpp index c44857b1c..3f1fd9abd 100644 --- a/firmware/standalone/common/ui/ui_geomap.cpp +++ b/firmware/standalone/common/ui/ui_geomap.cpp @@ -451,14 +451,22 @@ bool GeoMap::draw_osm_file(int zoom, int tile_x, int tile_y, int relative_x, int return false; } std::vector line(clip_w); - for (int y = 0; y < clip_h; ++y) { - int source_row = src_y + y; - int dest_row = dest_y + y; - bmp.seek(src_x, source_row); - for (int x = 0; x < clip_w; ++x) { - bmp.read_next_px(line[x], true); + if (bmp.is_bottomup()) { + for (int y = clip_h - 1; y >= 0; --y) { + int source_row = src_y + y; + int dest_row = dest_y + y; + bmp.seek(src_x, source_row); + bmp.read_next_px_cnt(line.data(), clip_w, false); + painter.draw_pixels({dest_x + r.left(), dest_row + r.top(), clip_w, 1}, line); + } + } else { + for (int y = 0; y < clip_h; ++y) { + int source_row = src_y + y; + int dest_row = dest_y + y; + bmp.seek(src_x, source_row); + bmp.read_next_px_cnt(line.data(), clip_w, false); + painter.draw_pixels({dest_x + r.left(), dest_row + r.top(), clip_w, 1}, line); } - painter.draw_pixels({dest_x + r.left(), dest_row + r.top(), clip_w, 1}, line); } return true; } diff --git a/firmware/standalone/pacman/main.cpp b/firmware/standalone/pacman/main.cpp index d8dd88479..65832b4aa 100644 --- a/firmware/standalone/pacman/main.cpp +++ b/firmware/standalone/pacman/main.cpp @@ -25,6 +25,7 @@ bool notouch(int, int, uint32_t) { // do nothing + return false; } void nothing() { // do nothing