diff --git a/src/OpenStreetMap-esp32.cpp b/src/OpenStreetMap-esp32.cpp index d1bfe94..4c50109 100644 --- a/src/OpenStreetMap-esp32.cpp +++ b/src/OpenStreetMap-esp32.cpp @@ -377,7 +377,7 @@ bool OpenStreetMap::downloadAndDecodeTile(CachedTile &tile, uint32_t x, uint32_t if (!readTileDataToBuffer(stream, buffer, contentSize, result)) { http.end(); - log_e("%s", result); + log_e("%s", result.c_str()); return false; } @@ -412,37 +412,8 @@ bool OpenStreetMap::downloadAndDecodeTile(CachedTile &tile, uint32_t x, uint32_t return true; } -bool OpenStreetMap::saveMap(const char *filename, LGFX_Sprite &map, String &result, uint8_t sdPin, uint32_t frequency) +bool OpenStreetMap::writeHeader(const LGFX_Sprite &map, File &file) { - log_i("Saving map as %s", filename); - - 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; - } - // BMP Header (54 bytes) uint16_t bfType = 0x4D42; // "BM" uint32_t biSizeImage = map.width() * map.height() * 3; // 3 bytes per pixel (RGB888) @@ -460,32 +431,57 @@ bool OpenStreetMap::saveMap(const char *filename, LGFX_Sprite &map, String &resu uint32_t biClrUsed = 0; uint32_t biClrImportant = 0; - // Write BMP header (Ensuring little-endian format) - auto writeLE = [&](uint32_t value, uint8_t size) + auto writeLE = [&](uint32_t value, uint8_t size) -> bool { for (uint8_t i = 0; i < size; i++) - file.write(static_cast(value >> (8 * i))); + if (file.write(static_cast(value >> (8 * i))) != 1) + return false; + + return true; }; - writeLE(bfType, 2); - writeLE(bfSize, 4); - writeLE(0, 2); // bfReserved - writeLE(0, 2); - writeLE(bfOffBits, 4); - - writeLE(biSize, 4); - writeLE(biWidth, 4); - writeLE(biHeight, 4); - writeLE(biPlanes, 2); - writeLE(biBitCount, 2); - writeLE(biCompression, 4); - writeLE(biSizeImage, 4); - writeLE(biXPelsPerMeter, 4); - writeLE(biYPelsPerMeter, 4); - writeLE(biClrUsed, 4); - writeLE(biClrImportant, 4); - - uint8_t *buf = rowBuffer.get(); + bool success = true; + + if (!(success &= writeLE(bfType, 2))) + return false; + if (!(success &= writeLE(bfSize, 4))) + return false; + if (!(success &= writeLE(0, 2))) + return false; + if (!(success &= writeLE(0, 2))) + return false; + if (!(success &= writeLE(bfOffBits, 4))) + return false; + if (!(success &= writeLE(biSize, 4))) + return false; + if (!(success &= writeLE(biWidth, 4))) + return false; + if (!(success &= writeLE(biHeight, 4))) + return false; + if (!(success &= writeLE(biPlanes, 2))) + return false; + if (!(success &= writeLE(biBitCount, 2))) + return false; + if (!(success &= writeLE(biCompression, 4))) + return false; + if (!(success &= writeLE(biSizeImage, 4))) + return false; + if (!(success &= writeLE(biXPelsPerMeter, 4))) + return false; + if (!(success &= writeLE(biYPelsPerMeter, 4))) + return false; + if (!(success &= writeLE(biClrUsed, 4))) + return false; + if (!(success &= writeLE(biClrImportant, 4))) + return false; + + return success; +} + +bool OpenStreetMap::writeMap(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++) @@ -499,7 +495,57 @@ bool OpenStreetMap::saveMap(const char *filename, LGFX_Sprite &map, String &resu buf[x * 3 + 1] = green8; buf[x * 3 + 2] = red8; } - file.write(buf, rowBuffer.size()); + if (file.write(buf, size) != size) + return false; + } + return true; +} + +bool OpenStreetMap::saveMap(const char *filename, LGFX_Sprite &map, String &result, uint8_t sdPin, uint32_t frequency) +{ + log_i("Saving map as %s", filename); + + 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 (!writeHeader(map, file)) + { + result = "Failed to write bmp header"; + file.close(); + SD.end(); + return false; + } + + if (!writeMap(map, file, rowBuffer)) + { + result = "Failed to write map data"; + file.close(); + SD.end(); + return false; } file.close(); diff --git a/src/OpenStreetMap-esp32.h b/src/OpenStreetMap-esp32.h index 5712345..988a15a 100644 --- a/src/OpenStreetMap-esp32.h +++ b/src/OpenStreetMap-esp32.h @@ -70,6 +70,8 @@ class OpenStreetMap bool downloadAndDecodeTile(CachedTile &tile, uint32_t x, uint32_t y, uint8_t zoom, String &result); bool readTileDataToBuffer(WiFiClient *stream, MemoryBuffer &buffer, size_t contentSize, String &result); bool composeMap(LGFX_Sprite &mapSprite, const tileList &requiredTiles, uint8_t zoom); + bool writeHeader(const LGFX_Sprite &map, File &file); + bool writeMap(LGFX_Sprite &map, File &file, MemoryBuffer &buffer); std::vector tilesCache; uint16_t *currentTileBuffer = nullptr; @@ -84,7 +86,7 @@ class OpenStreetMap int32_t startTileIndexX = 0; int32_t startTileIndexY = 0; - uint16_t numberOfColums = 0; + uint16_t numberOfColums = 0; }; #endif