From b50da75070f1723c45c6f84367c0cb13cd54bac2 Mon Sep 17 00:00:00 2001 From: HarukiToreda <116696711+HarukiToreda@users.noreply.github.com> Date: Sun, 5 Jul 2026 06:39:14 -0400 Subject: [PATCH] MapTile Compression Improvement (#10882) * compression improvement * Update MapTile.h * t-echo-inkhud fix --- .../InkHUD/Applets/Bases/Map/MapApplet.cpp | 115 +++++++++++++++--- .../niche/InkHUD/Applets/Bases/Map/MapTile.h | 21 +++- 2 files changed, 111 insertions(+), 25 deletions(-) diff --git a/src/graphics/niche/InkHUD/Applets/Bases/Map/MapApplet.cpp b/src/graphics/niche/InkHUD/Applets/Bases/Map/MapApplet.cpp index 83b90ca87..5c8d78cb8 100644 --- a/src/graphics/niche/InkHUD/Applets/Bases/Map/MapApplet.cpp +++ b/src/graphics/niche/InkHUD/Applets/Bases/Map/MapApplet.cpp @@ -13,6 +13,14 @@ int InkHUD::MapApplet::s_lockedZoom = -1; int InkHUD::MapApplet::s_lastRenderedZoom = -1; int InkHUD::MapApplet::s_autoFitZoom = -1; +static bool usesGridTileLayout(); +static int gridTilesPerBlock(); +static int tileZoomAt(int tileIndex); +static int tileTxAt(int tileIndex); +static int tileTyAt(int tileIndex); +static int tileMetadataZoomCount(); +static int tileMetadataZoomAt(int index); + // Observe GPS position updates so the map redraws whenever a new location arrives. InkHUD::MapApplet::MapApplet() { @@ -48,8 +56,8 @@ void InkHUD::MapApplet::zoomIn() // Jump to the next tile zoom strictly above current, not just +1 int next = -1; - for (int i = 0; i < map_tile_count; i++) { - int z = map_tile_zooms[i]; + for (int i = 0; i < tileMetadataZoomCount(); i++) { + int z = tileMetadataZoomAt(i); if (z > baseZoom && (next < 0 || z < next)) next = z; } @@ -73,8 +81,8 @@ bool InkHUD::MapApplet::canZoomIn() const int ref = s_zoomLocked ? s_lockedZoom : s_lastRenderedZoom; if (map_tile_count == 0) return ref < ZOOM_MAX_NO_TILES; - for (int i = 0; i < map_tile_count; i++) { - if (map_tile_zooms[i] > ref) + for (int i = 0; i < tileMetadataZoomCount(); i++) { + if (tileMetadataZoomAt(i) > ref) return true; } return false; @@ -103,8 +111,8 @@ void InkHUD::MapApplet::zoomOut() // Jump to the next tile zoom strictly below current, not just -1 int next = -1; - for (int i = 0; i < map_tile_count; i++) { - int z = map_tile_zooms[i]; + for (int i = 0; i < tileMetadataZoomCount(); i++) { + int z = tileMetadataZoomAt(i); if (z < baseZoom && (next < 0 || z > next)) next = z; } @@ -125,8 +133,8 @@ bool InkHUD::MapApplet::canZoomOut() const int ref = s_zoomLocked ? s_lockedZoom : s_lastRenderedZoom; if (map_tile_count == 0) return s_autoFitZoom >= 0 ? ref > s_autoFitZoom : false; - for (int i = 0; i < map_tile_count; i++) { - if (map_tile_zooms[i] < ref) + for (int i = 0; i < tileMetadataZoomCount(); i++) { + if (tileMetadataZoomAt(i) < ref) return true; } return false; @@ -181,10 +189,79 @@ static int lz4_decompress(const uint8_t *src, int src_len, uint8_t *dst, int dst // Tiles are 1 bit/pixel, column-major: [bx=0..31][y=0..255], 8 pixels per byte. static uint8_t s_tileCacheBuffer[8192]; +static constexpr uint8_t MAP_TILE_LAYOUT_SPARSE = 0; +static constexpr uint8_t MAP_TILE_LAYOUT_GRID = 1; +static constexpr uint8_t MAP_TILE_KIND_LZ4 = 0; +static constexpr uint8_t MAP_TILE_KIND_WHITE = 1; +static constexpr uint8_t MAP_TILE_KIND_BLACK = 2; + +static bool usesGridTileLayout() +{ + return map_tile_layout == MAP_TILE_LAYOUT_GRID && map_tile_grid_cols > 0 && map_tile_grid_rows > 0 && + map_tile_block_count > 0; +} + +static int gridTilesPerBlock() +{ + return (int)map_tile_grid_cols * (int)map_tile_grid_rows; +} + +static int tileZoomAt(int tileIndex) +{ + if (!usesGridTileLayout()) + return map_tile_zooms[tileIndex]; + int tilesPerBlock = gridTilesPerBlock(); + int blockIndex = tilesPerBlock > 0 ? (tileIndex / tilesPerBlock) : 0; + return map_tile_block_zooms[blockIndex]; +} + +static int tileTxAt(int tileIndex) +{ + if (!usesGridTileLayout()) + return map_tile_tx[tileIndex]; + int rows = map_tile_grid_rows; + int tilesPerBlock = gridTilesPerBlock(); + int blockIndex = tilesPerBlock > 0 ? (tileIndex / tilesPerBlock) : 0; + int localIndex = tilesPerBlock > 0 ? (tileIndex % tilesPerBlock) : 0; + return map_tile_block_tx[blockIndex] + (rows > 0 ? (localIndex / rows) : 0); +} + +static int tileTyAt(int tileIndex) +{ + if (!usesGridTileLayout()) + return map_tile_ty[tileIndex]; + int rows = map_tile_grid_rows; + int tilesPerBlock = gridTilesPerBlock(); + int blockIndex = tilesPerBlock > 0 ? (tileIndex / tilesPerBlock) : 0; + int localIndex = tilesPerBlock > 0 ? (tileIndex % tilesPerBlock) : 0; + return map_tile_block_ty[blockIndex] + (rows > 0 ? (localIndex % rows) : 0); +} + +static int tileMetadataZoomCount() +{ + if (usesGridTileLayout()) + return map_tile_block_count; + return map_tile_count; +} + +static int tileMetadataZoomAt(int index) +{ + return usesGridTileLayout() ? map_tile_block_zooms[index] : map_tile_zooms[index]; +} static const uint8_t *decodeSparseTile(int tileIndex) { - int n = lz4_decompress(map_tile_data[tileIndex], map_tile_sizes[tileIndex], s_tileCacheBuffer, sizeof(s_tileCacheBuffer)); + const uint8_t kind = map_tile_kinds[tileIndex]; + if (kind == MAP_TILE_KIND_WHITE) { + memset(s_tileCacheBuffer, 0x00, sizeof(s_tileCacheBuffer)); + return s_tileCacheBuffer; + } + if (kind == MAP_TILE_KIND_BLACK) { + memset(s_tileCacheBuffer, 0xFF, sizeof(s_tileCacheBuffer)); + return s_tileCacheBuffer; + } + const uint8_t *compressed = map_tile_data + map_tile_offsets[tileIndex]; + int n = lz4_decompress(compressed, map_tile_sizes[tileIndex], s_tileCacheBuffer, sizeof(s_tileCacheBuffer)); return n == sizeof(s_tileCacheBuffer) ? s_tileCacheBuffer : nullptr; } @@ -202,14 +279,14 @@ void InkHUD::MapApplet::drawMapTileBackground(int zoom) // Find best tile zoom: highest available <= zoom, or lowest available if none below. int tileZoom = -1; - for (int i = 0; i < map_tile_count; i++) { - int z = map_tile_zooms[i]; + for (int i = 0; i < tileMetadataZoomCount(); i++) { + int z = tileMetadataZoomAt(i); if (z <= zoom && (tileZoom < 0 || z > tileZoom)) tileZoom = z; } if (tileZoom < 0) { - for (int i = 0; i < map_tile_count; i++) { - int z = map_tile_zooms[i]; + for (int i = 0; i < tileMetadataZoomCount(); i++) { + int z = tileMetadataZoomAt(i); if (tileZoom < 0 || z < tileZoom) tileZoom = z; } @@ -231,11 +308,11 @@ void InkHUD::MapApplet::drawMapTileBackground(int zoom) const float maxWy = gpxY + height() * 0.5f * tileWorldPx; for (int i = 0; i < map_tile_count; i++) { - if (map_tile_zooms[i] != tileZoom) + if (tileZoomAt(i) != tileZoom) continue; - const int tx = map_tile_tx[i]; - const int ty = map_tile_ty[i]; + const int tx = tileTxAt(i); + const int ty = tileTyAt(i); const float tileMinWx = tx * 256.0f; const float tileMaxWx = tileMinWx + 256.0f; const float tileMinWy = ty * 256.0f; @@ -299,16 +376,16 @@ void InkHUD::MapApplet::onRender(bool full) // Collect unique zooms, sort descending (highest detail first) int zooms[16] = {}; int nzooms = 0; - for (int i = 0; i < map_tile_count && nzooms < 16; i++) { + for (int i = 0; i < tileMetadataZoomCount() && nzooms < 16; i++) { bool found = false; for (int j = 0; j < nzooms; j++) { - if (zooms[j] == map_tile_zooms[i]) { + if (zooms[j] == tileMetadataZoomAt(i)) { found = true; break; } } if (!found) - zooms[nzooms++] = map_tile_zooms[i]; + zooms[nzooms++] = tileMetadataZoomAt(i); } for (int i = 0; i < nzooms - 1; i++) { for (int j = i + 1; j < nzooms; j++) { diff --git a/src/graphics/niche/InkHUD/Applets/Bases/Map/MapTile.h b/src/graphics/niche/InkHUD/Applets/Bases/Map/MapTile.h index fee0f60f9..c2eed78c7 100644 --- a/src/graphics/niche/InkHUD/Applets/Bases/Map/MapTile.h +++ b/src/graphics/niche/InkHUD/Applets/Bases/Map/MapTile.h @@ -1,9 +1,18 @@ #pragma once #include -static const int map_tile_count = 0; -static const int map_tile_zooms[] = {}; -static const int map_tile_tx[] = {}; -static const int map_tile_ty[] = {}; -static const int map_tile_sizes[] = {}; -static const uint8_t *map_tile_data[] = {}; +static const uint8_t map_tile_layout = 0; +static const uint8_t map_tile_grid_cols = 0; +static const uint8_t map_tile_grid_rows = 0; +static const uint8_t map_tile_block_count = 0; +static const uint16_t map_tile_count = 0; +static const uint8_t map_tile_zooms[] = {}; +static const uint16_t map_tile_tx[] = {}; +static const uint16_t map_tile_ty[] = {}; +static const uint8_t map_tile_block_zooms[] = {}; +static const uint16_t map_tile_block_tx[] = {}; +static const uint16_t map_tile_block_ty[] = {}; +static const uint8_t map_tile_kinds[] = {}; +static const uint16_t map_tile_sizes[] = {}; +static const uint32_t map_tile_offsets[] = {}; +static const uint8_t map_tile_data[] = {};