MapTile Compression Improvement (#10882)
* compression improvement * Update MapTile.h * t-echo-inkhud fix
This commit is contained in:
@@ -13,6 +13,14 @@ int InkHUD::MapApplet::s_lockedZoom = -1;
|
|||||||
int InkHUD::MapApplet::s_lastRenderedZoom = -1;
|
int InkHUD::MapApplet::s_lastRenderedZoom = -1;
|
||||||
int InkHUD::MapApplet::s_autoFitZoom = -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.
|
// Observe GPS position updates so the map redraws whenever a new location arrives.
|
||||||
InkHUD::MapApplet::MapApplet()
|
InkHUD::MapApplet::MapApplet()
|
||||||
{
|
{
|
||||||
@@ -48,8 +56,8 @@ void InkHUD::MapApplet::zoomIn()
|
|||||||
|
|
||||||
// Jump to the next tile zoom strictly above current, not just +1
|
// Jump to the next tile zoom strictly above current, not just +1
|
||||||
int next = -1;
|
int next = -1;
|
||||||
for (int i = 0; i < map_tile_count; i++) {
|
for (int i = 0; i < tileMetadataZoomCount(); i++) {
|
||||||
int z = map_tile_zooms[i];
|
int z = tileMetadataZoomAt(i);
|
||||||
if (z > baseZoom && (next < 0 || z < next))
|
if (z > baseZoom && (next < 0 || z < next))
|
||||||
next = z;
|
next = z;
|
||||||
}
|
}
|
||||||
@@ -73,8 +81,8 @@ bool InkHUD::MapApplet::canZoomIn() const
|
|||||||
int ref = s_zoomLocked ? s_lockedZoom : s_lastRenderedZoom;
|
int ref = s_zoomLocked ? s_lockedZoom : s_lastRenderedZoom;
|
||||||
if (map_tile_count == 0)
|
if (map_tile_count == 0)
|
||||||
return ref < ZOOM_MAX_NO_TILES;
|
return ref < ZOOM_MAX_NO_TILES;
|
||||||
for (int i = 0; i < map_tile_count; i++) {
|
for (int i = 0; i < tileMetadataZoomCount(); i++) {
|
||||||
if (map_tile_zooms[i] > ref)
|
if (tileMetadataZoomAt(i) > ref)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
@@ -103,8 +111,8 @@ void InkHUD::MapApplet::zoomOut()
|
|||||||
|
|
||||||
// Jump to the next tile zoom strictly below current, not just -1
|
// Jump to the next tile zoom strictly below current, not just -1
|
||||||
int next = -1;
|
int next = -1;
|
||||||
for (int i = 0; i < map_tile_count; i++) {
|
for (int i = 0; i < tileMetadataZoomCount(); i++) {
|
||||||
int z = map_tile_zooms[i];
|
int z = tileMetadataZoomAt(i);
|
||||||
if (z < baseZoom && (next < 0 || z > next))
|
if (z < baseZoom && (next < 0 || z > next))
|
||||||
next = z;
|
next = z;
|
||||||
}
|
}
|
||||||
@@ -125,8 +133,8 @@ bool InkHUD::MapApplet::canZoomOut() const
|
|||||||
int ref = s_zoomLocked ? s_lockedZoom : s_lastRenderedZoom;
|
int ref = s_zoomLocked ? s_lockedZoom : s_lastRenderedZoom;
|
||||||
if (map_tile_count == 0)
|
if (map_tile_count == 0)
|
||||||
return s_autoFitZoom >= 0 ? ref > s_autoFitZoom : false;
|
return s_autoFitZoom >= 0 ? ref > s_autoFitZoom : false;
|
||||||
for (int i = 0; i < map_tile_count; i++) {
|
for (int i = 0; i < tileMetadataZoomCount(); i++) {
|
||||||
if (map_tile_zooms[i] < ref)
|
if (tileMetadataZoomAt(i) < ref)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
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.
|
// Tiles are 1 bit/pixel, column-major: [bx=0..31][y=0..255], 8 pixels per byte.
|
||||||
static uint8_t s_tileCacheBuffer[8192];
|
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)
|
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;
|
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.
|
// Find best tile zoom: highest available <= zoom, or lowest available if none below.
|
||||||
int tileZoom = -1;
|
int tileZoom = -1;
|
||||||
for (int i = 0; i < map_tile_count; i++) {
|
for (int i = 0; i < tileMetadataZoomCount(); i++) {
|
||||||
int z = map_tile_zooms[i];
|
int z = tileMetadataZoomAt(i);
|
||||||
if (z <= zoom && (tileZoom < 0 || z > tileZoom))
|
if (z <= zoom && (tileZoom < 0 || z > tileZoom))
|
||||||
tileZoom = z;
|
tileZoom = z;
|
||||||
}
|
}
|
||||||
if (tileZoom < 0) {
|
if (tileZoom < 0) {
|
||||||
for (int i = 0; i < map_tile_count; i++) {
|
for (int i = 0; i < tileMetadataZoomCount(); i++) {
|
||||||
int z = map_tile_zooms[i];
|
int z = tileMetadataZoomAt(i);
|
||||||
if (tileZoom < 0 || z < tileZoom)
|
if (tileZoom < 0 || z < tileZoom)
|
||||||
tileZoom = z;
|
tileZoom = z;
|
||||||
}
|
}
|
||||||
@@ -231,11 +308,11 @@ void InkHUD::MapApplet::drawMapTileBackground(int zoom)
|
|||||||
const float maxWy = gpxY + height() * 0.5f * tileWorldPx;
|
const float maxWy = gpxY + height() * 0.5f * tileWorldPx;
|
||||||
|
|
||||||
for (int i = 0; i < map_tile_count; i++) {
|
for (int i = 0; i < map_tile_count; i++) {
|
||||||
if (map_tile_zooms[i] != tileZoom)
|
if (tileZoomAt(i) != tileZoom)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
const int tx = map_tile_tx[i];
|
const int tx = tileTxAt(i);
|
||||||
const int ty = map_tile_ty[i];
|
const int ty = tileTyAt(i);
|
||||||
const float tileMinWx = tx * 256.0f;
|
const float tileMinWx = tx * 256.0f;
|
||||||
const float tileMaxWx = tileMinWx + 256.0f;
|
const float tileMaxWx = tileMinWx + 256.0f;
|
||||||
const float tileMinWy = ty * 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)
|
// Collect unique zooms, sort descending (highest detail first)
|
||||||
int zooms[16] = {};
|
int zooms[16] = {};
|
||||||
int nzooms = 0;
|
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;
|
bool found = false;
|
||||||
for (int j = 0; j < nzooms; j++) {
|
for (int j = 0; j < nzooms; j++) {
|
||||||
if (zooms[j] == map_tile_zooms[i]) {
|
if (zooms[j] == tileMetadataZoomAt(i)) {
|
||||||
found = true;
|
found = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!found)
|
if (!found)
|
||||||
zooms[nzooms++] = map_tile_zooms[i];
|
zooms[nzooms++] = tileMetadataZoomAt(i);
|
||||||
}
|
}
|
||||||
for (int i = 0; i < nzooms - 1; i++) {
|
for (int i = 0; i < nzooms - 1; i++) {
|
||||||
for (int j = i + 1; j < nzooms; j++) {
|
for (int j = i + 1; j < nzooms; j++) {
|
||||||
|
|||||||
@@ -1,9 +1,18 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
static const int map_tile_count = 0;
|
static const uint8_t map_tile_layout = 0;
|
||||||
static const int map_tile_zooms[] = {};
|
static const uint8_t map_tile_grid_cols = 0;
|
||||||
static const int map_tile_tx[] = {};
|
static const uint8_t map_tile_grid_rows = 0;
|
||||||
static const int map_tile_ty[] = {};
|
static const uint8_t map_tile_block_count = 0;
|
||||||
static const int map_tile_sizes[] = {};
|
static const uint16_t map_tile_count = 0;
|
||||||
static const uint8_t *map_tile_data[] = {};
|
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[] = {};
|
||||||
Reference in New Issue
Block a user