Skip to content

Delete most code #12

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Mar 25, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 3 additions & 17 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,9 @@ void setSize(uint16_t w, uint16_t h);
bool resizeTilesCache(uint8_t numberOfTiles);
```

- The cache is cleared before resizing.
- Default cache size is 10 tiles.
- Each tile is 128 kB.
- The cache is cleared before resizing.

### Free the memory used by the tile cache

Expand All @@ -63,21 +64,6 @@ bool fetchMap(LGFX_Sprite &map, double longitude, double latitude, uint8_t zoom)
- Overflowing `latitude` are clamped to +-90°.
- Valid range for the `zoom` level is 1-18.

### Save a map to SD card

```c++
bool saveMap(const char *filename, LGFX_Sprite &map, String &result,
uint8_t sdPin = SS, uint32_t frequency = 4000000)
```

- `filename` must start with `/` for example `/map.bmp` or `/images/map.bmp`
- `result` returns something like `SD Card mount failed` or `Screenshot saved`.
- `sdPin` is **optional** and used to set a `SS/CS` pin for the SD slot.
- `frequency` is **optional** and used to set the SD speed.

**Note**: The SD card is managed from `begin()` to `end()` inside the `saveMap()` function.
Do not mount the SD card before this function but unmount if it is mounted else memory will be leaked.

## Example code

### Example returning the default 320x240 map
Expand Down Expand Up @@ -210,7 +196,7 @@ void loop()

```bash
lib_deps =
https://github.com/CelliesProjects/OpenStreetMap-esp32
CelliesProjects/OpenStreetMap-esp32@^1.0.0
lovyan03/LovyanGFX@^1.2.0
bitbank2/PNGdec@^1.0.3
```
127 changes: 0 additions & 127 deletions src/OpenStreetMap-esp32.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -426,130 +426,3 @@ bool OpenStreetMap::fetchTile(CachedTile &tile, uint32_t x, uint32_t y, uint8_t
result = "Added: " + url;
return true;
}

bool OpenStreetMap::writeHeaderToSD(const LGFX_Sprite &map, File &file)
{
uint8_t header[54] = {0}; // BMP header (54 bytes)

// BMP File Header (14 bytes)
header[0] = 'B';
header[1] = 'M';

uint32_t biSizeImage = map.width() * map.height() * 3; // 3 bytes per pixel (RGB888)
uint32_t bfSize = 54 + biSizeImage; // Total file size
uint32_t bfOffBits = 54; // Offset to pixel data

// BMP Info Header (40 bytes)
uint32_t biSize = 40; // Info header size
int32_t biWidth = map.width();
int32_t biHeight = -map.height(); // Negative for top-down order
uint16_t biPlanes = 1;
uint16_t biBitCount = 24; // RGB888 format
uint32_t biCompression = 0;
int32_t biXPelsPerMeter = 0;
int32_t biYPelsPerMeter = 0;
uint32_t biClrUsed = 0;
uint32_t biClrImportant = 0;

auto writeLE = [](uint8_t *buffer, size_t offset, uint32_t value, uint8_t size)
{
for (uint8_t i = 0; i < size; i++)
buffer[offset + i] = static_cast<uint8_t>((value >> (8 * i)) & 0xFF);
};

// Populate the header array with the correct offsets
writeLE(header, 2, bfSize, 4); // File size
writeLE(header, 10, bfOffBits, 4); // Pixel data offset
writeLE(header, 14, biSize, 4); // Info header size
writeLE(header, 18, biWidth, 4); // Image width
writeLE(header, 22, biHeight, 4); // Image height (negative for top-down)
writeLE(header, 26, biPlanes, 2); // Number of planes (always 1)
writeLE(header, 28, biBitCount, 2); // Bits per pixel (24-bit RGB)
writeLE(header, 30, biCompression, 4); // Compression (0 = none)
writeLE(header, 34, biSizeImage, 4); // Image size in bytes
writeLE(header, 38, biXPelsPerMeter, 4); // Horizontal resolution (not used)
writeLE(header, 42, biYPelsPerMeter, 4); // Vertical resolution (not used)
writeLE(header, 46, biClrUsed, 4); // Colors in palette (not used)
writeLE(header, 50, biClrImportant, 4); // Important colors (not used)

return file.write(header, sizeof(header)) == sizeof(header);
}

bool OpenStreetMap::writeMapToSD(LGFX_Sprite &map, File &file, MemoryBuffer &buffer)
{
uint8_t *buf = buffer.get();
const size_t size = buffer.size();
for (uint16_t y = 0; y < map.height(); y++)
{
for (uint16_t x = 0; x < map.width(); x++)
{
uint16_t rgb565Color = map.readPixel(x, y);
uint8_t red8 = ((rgb565Color >> 11) & 0x1F) * 255 / 31;
uint8_t green8 = ((rgb565Color >> 5) & 0x3F) * 255 / 63;
uint8_t blue8 = (rgb565Color & 0x1F) * 255 / 31;

buf[x * 3] = blue8;
buf[x * 3 + 1] = green8;
buf[x * 3 + 2] = red8;
}
if (file.write(buf, size) != size)
return false;
}
return true;
}

bool OpenStreetMap::saveMap(const String &filename, LGFX_Sprite &map, String &result, uint8_t sdPin, uint32_t frequency)
{
return saveMap(filename.c_str(), map, result, sdPin, frequency);
}

bool OpenStreetMap::saveMap(const char *filename, LGFX_Sprite &map, String &result, uint8_t sdPin, uint32_t frequency)
{
if (!map.getBuffer())
{
result = "No data in map";
return false;
}

MemoryBuffer rowBuffer(map.width() * 3);
if (!rowBuffer.isAllocated())
{
result = "Row buffer allocation failed";
return false;
}

if (!SD.begin(sdPin, SPI, frequency))
{
result = "SD Card mount failed";
return false;
}

File file = SD.open(filename, FILE_WRITE);
if (!file)
{
result = "Failed to open file";
SD.end();
return false;
}

if (!writeHeaderToSD(map, file))
{
result = "Failed to write bmp header";
file.close();
SD.end();
return false;
}

if (!writeMapToSD(map, file, rowBuffer))
{
result = "Failed to write map data";
file.close();
SD.end();
return false;
}

file.close();
SD.end();
result = "Map saved as " + String(filename);
return true;
}
4 changes: 0 additions & 4 deletions src/OpenStreetMap-esp32.h
Original file line number Diff line number Diff line change
Expand Up @@ -59,8 +59,6 @@ class OpenStreetMap
bool resizeTilesCache(uint8_t numberOfTiles);
void freeTilesCache();
bool fetchMap(LGFX_Sprite &sprite, double longitude, double latitude, uint8_t zoom);
bool saveMap(const char *filename, LGFX_Sprite &map, String &result, uint8_t sdPin = SS, uint32_t frequency = 4000000);
bool saveMap(const String &filename, LGFX_Sprite &map, String &result, uint8_t sdPin = SS, uint32_t frequency = 4000000);

private:
static OpenStreetMap *currentInstance;
Expand All @@ -75,8 +73,6 @@ class OpenStreetMap
std::optional<std::unique_ptr<MemoryBuffer>> urlToBuffer(const String &url, String &result);
bool fillBuffer(WiFiClient *stream, MemoryBuffer &buffer, size_t contentSize, String &result);
bool composeMap(LGFX_Sprite &mapSprite, const tileList &requiredTiles, uint8_t zoom);
bool writeHeaderToSD(const LGFX_Sprite &map, File &file);
bool writeMapToSD(LGFX_Sprite &map, File &file, MemoryBuffer &buffer);

std::vector<CachedTile> tilesCache;
uint16_t *currentTileBuffer = nullptr;
Expand Down