diff --git a/README.md b/README.md index caee6fb..3b8705d 100644 --- a/README.md +++ b/README.md @@ -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 @@ -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 @@ -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 ``` diff --git a/src/OpenStreetMap-esp32.cpp b/src/OpenStreetMap-esp32.cpp index bda3c5b..153c366 100644 --- a/src/OpenStreetMap-esp32.cpp +++ b/src/OpenStreetMap-esp32.cpp @@ -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((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; -} diff --git a/src/OpenStreetMap-esp32.h b/src/OpenStreetMap-esp32.h index 12491c0..8c4a83b 100644 --- a/src/OpenStreetMap-esp32.h +++ b/src/OpenStreetMap-esp32.h @@ -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; @@ -75,8 +73,6 @@ class OpenStreetMap std::optional> 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 tilesCache; uint16_t *currentTileBuffer = nullptr;