@@ -412,88 +412,100 @@ bool OpenStreetMap::downloadAndDecodeTile(CachedTile &tile, uint32_t x, uint32_t
412412 return true ;
413413}
414414
415- bool OpenStreetMap::saveMap (const char *filename, LGFX_Sprite &map, String &result, uint8_t sdPin)
415+ bool OpenStreetMap::saveMap (const char *filename, LGFX_Sprite &map, String &result, uint8_t sdPin, uint32_t frequency )
416416{
417417 log_i (" Saving map, this may take a while..." );
418418
419419 if (!map.getBuffer ())
420420 {
421- result = " No data in map! " ;
421+ result = " No data in map" ;
422422 return false ;
423423 }
424424
425- if (!SD.begin (sdPin))
425+ if (!SD.begin (sdPin, SPI, frequency ))
426426 {
427- result = " SD Card mount failed! " ;
427+ result = " SD Card mount failed" ;
428428 return false ;
429429 }
430430
431431 File file = SD.open (filename, FILE_WRITE);
432432 if (!file)
433433 {
434- result = " Failed to open file! " ;
434+ result = " Failed to open file" ;
435435 SD.end ();
436436 return false ;
437437 }
438438
439- // BMP header (54 bytes)
440- uint16_t bfType = 0x4D42 ; // "BM"
441- uint32_t bfSize = 54 + map.width () * map.height () * 3 ; // Header + pixel data ( 3 bytes per pixel for RGB888)
442- uint16_t bfReserved = 0 ;
443- uint32_t bfOffBits = 54 ; // Offset to pixel data
439+ // BMP Header (54 bytes)
440+ uint16_t bfType = 0x4D42 ; // "BM"
441+ uint32_t biSizeImage = map.width () * map.height () * 3 ; // 3 bytes per pixel ( RGB888)
442+ uint32_t bfSize = 54 + biSizeImage; // Total file size
443+ uint32_t bfOffBits = 54 ; // Offset to pixel data
444444
445445 uint32_t biSize = 40 ; // Info header size
446446 int32_t biWidth = map.width ();
447- int32_t biHeight = -map.height (); // Negative to flip vertically
447+ int32_t biHeight = -map.height (); // Negative to store in top-down order
448448 uint16_t biPlanes = 1 ;
449449 uint16_t biBitCount = 24 ; // RGB888 format
450450 uint32_t biCompression = 0 ;
451- uint32_t biSizeImage = map.width () * map.height () * 3 ; // 3 bytes per pixel
452451 int32_t biXPelsPerMeter = 0 ;
453452 int32_t biYPelsPerMeter = 0 ;
454453 uint32_t biClrUsed = 0 ;
455454 uint32_t biClrImportant = 0 ;
456455
457- // Write BMP header
458- file.write (reinterpret_cast <const uint8_t *>(&bfType), sizeof (bfType));
459- file.write (reinterpret_cast <const uint8_t *>(&bfSize), sizeof (bfSize));
460- file.write (reinterpret_cast <const uint8_t *>(&bfReserved), sizeof (bfReserved));
461- file.write (reinterpret_cast <const uint8_t *>(&bfOffBits), sizeof (bfOffBits));
462-
463- file.write (reinterpret_cast <const uint8_t *>(&biSize), sizeof (biSize));
464- file.write (reinterpret_cast <const uint8_t *>(&biWidth), sizeof (biWidth));
465- file.write (reinterpret_cast <const uint8_t *>(&biHeight), sizeof (biHeight));
466- file.write (reinterpret_cast <const uint8_t *>(&biPlanes), sizeof (biPlanes));
467- file.write (reinterpret_cast <const uint8_t *>(&biBitCount), sizeof (biBitCount));
468- file.write (reinterpret_cast <const uint8_t *>(&biCompression), sizeof (biCompression));
469- file.write (reinterpret_cast <const uint8_t *>(&biSizeImage), sizeof (biSizeImage));
470- file.write (reinterpret_cast <const uint8_t *>(&biXPelsPerMeter), sizeof (biXPelsPerMeter));
471- file.write (reinterpret_cast <const uint8_t *>(&biYPelsPerMeter), sizeof (biYPelsPerMeter));
472- file.write (reinterpret_cast <const uint8_t *>(&biClrUsed), sizeof (biClrUsed));
473- file.write (reinterpret_cast <const uint8_t *>(&biClrImportant), sizeof (biClrImportant));
456+ // Write BMP header (Ensuring little-endian format)
457+ auto writeLE = [&](uint32_t value, uint8_t size)
458+ {
459+ for (uint8_t i = 0 ; i < size; i++)
460+ file.write (static_cast <uint8_t >(value >> (8 * i)));
461+ };
462+
463+ writeLE (bfType, 2 );
464+ writeLE (bfSize, 4 );
465+ writeLE (0 , 2 ); // bfReserved
466+ writeLE (0 , 2 );
467+ writeLE (bfOffBits, 4 );
468+
469+ writeLE (biSize, 4 );
470+ writeLE (biWidth, 4 );
471+ writeLE (biHeight, 4 );
472+ writeLE (biPlanes, 2 );
473+ writeLE (biBitCount, 2 );
474+ writeLE (biCompression, 4 );
475+ writeLE (biSizeImage, 4 );
476+ writeLE (biXPelsPerMeter, 4 );
477+ writeLE (biYPelsPerMeter, 4 );
478+ writeLE (biClrUsed, 4 );
479+ writeLE (biClrImportant, 4 );
480+
481+ MemoryBuffer rowBuffer (map.width () * 3 );
482+ if (!rowBuffer.isAllocated ())
483+ {
484+ result = " Row buffer allocation failed" ;
485+ file.close ();
486+ SD.end ();
487+ return false ;
488+ }
474489
490+ uint8_t *buf = rowBuffer.get ();
475491 for (int y = 0 ; y < map.height (); y++)
476492 {
477493 for (int x = 0 ; x < map.width (); x++)
478494 {
479- uint16_t rgb565Color = map.readPixel (x, y); // Read pixel color (RGB565 format)
480- uint8_t red5 = (rgb565Color >> 11 ) & 0x1F ;
481- uint8_t green6 = (rgb565Color >> 5 ) & 0x3F ;
482- uint8_t blue5 = rgb565Color & 0x1F ;
483-
484- // Convert RGB565 to RGB888
485- uint8_t red8 = (red5 * 255 ) / 31 ;
486- uint8_t green8 = (green6 * 255 ) / 63 ;
487- uint8_t blue8 = (blue5 * 255 ) / 31 ;
488-
489- file.write (blue8);
490- file.write (green8);
491- file.write (red8);
495+ uint16_t rgb565Color = map.readPixel (x, y);
496+ uint8_t red8 = ((rgb565Color >> 11 ) & 0x1F ) * 255 / 31 ;
497+ uint8_t green8 = ((rgb565Color >> 5 ) & 0x3F ) * 255 / 63 ;
498+ uint8_t blue8 = (rgb565Color & 0x1F ) * 255 / 31 ;
499+
500+ buf[x * 3 ] = blue8;
501+ buf[x * 3 + 1 ] = green8;
502+ buf[x * 3 + 2 ] = red8;
492503 }
504+ file.write (buf, rowBuffer.size ()); // Write entire row at once
493505 }
494506
495507 file.close ();
496508 SD.end ();
497509 result = " Screenshot saved" ;
498510 return true ;
499- }
511+ }
0 commit comments