mirror of
https://github.com/thooge/esp32-nmea2000-obp60.git
synced 2026-08-18 10:22:31 +02:00
Color navigation map for PageNavigation.
This commit is contained in:
@@ -13,6 +13,54 @@
|
|||||||
NetworkClient net(JSON_BUFFER); // Define network client
|
NetworkClient net(JSON_BUFFER); // Define network client
|
||||||
ImageDecoder decoder; // Define image decoder
|
ImageDecoder decoder; // Define image decoder
|
||||||
|
|
||||||
|
#ifdef DISPLAY_ST7796
|
||||||
|
// Set to true to render a generated RGB565 color-bar test image.
|
||||||
|
static constexpr bool kShowRgb565StripeTestImage = true;
|
||||||
|
|
||||||
|
static void drawRgb565Image(int16_t x, int16_t y, const uint16_t *img, int16_t w, int16_t h) {
|
||||||
|
if (img == nullptr || w <= 0 || h <= 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for (int16_t yy = 0; yy < h; ++yy) {
|
||||||
|
const uint16_t *row = img + ((size_t)yy * (size_t)w);
|
||||||
|
for (int16_t xx = 0; xx < w; ++xx) {
|
||||||
|
getdisplay().drawPixel(x + xx, y + yy, row[xx]);
|
||||||
|
}
|
||||||
|
if ((yy & 0x0F) == 0) {
|
||||||
|
yield();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void createRgb565StripeImage(uint16_t *img, int16_t w, int16_t h) {
|
||||||
|
if (img == nullptr || w <= 0 || h <= 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
static const uint16_t stripes[] = {
|
||||||
|
0xF800, // red
|
||||||
|
0xFD20, // orange
|
||||||
|
0xFFE0, // yellow
|
||||||
|
0x07E0, // green
|
||||||
|
0x07FF, // cyan
|
||||||
|
0x001F, // blue
|
||||||
|
0xF81F, // magenta
|
||||||
|
0xFFFF // white
|
||||||
|
};
|
||||||
|
const int stripeCount = (int)(sizeof(stripes) / sizeof(stripes[0]));
|
||||||
|
|
||||||
|
for (int16_t y = 0; y < h; ++y) {
|
||||||
|
uint16_t *row = img + ((size_t)y * (size_t)w);
|
||||||
|
for (int16_t x = 0; x < w; ++x) {
|
||||||
|
int idx = ((int)x * stripeCount) / (int)w;
|
||||||
|
if (idx >= stripeCount) {
|
||||||
|
idx = stripeCount - 1;
|
||||||
|
}
|
||||||
|
row[x] = stripes[idx];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
class PageNavigation : public Page
|
class PageNavigation : public Page
|
||||||
{
|
{
|
||||||
// Values for buttons
|
// Values for buttons
|
||||||
@@ -25,13 +73,19 @@ bool showValues = false; // Show values HDT, SOG, DBT in navigation map
|
|||||||
int imageBackupWidth = 0;
|
int imageBackupWidth = 0;
|
||||||
int imageBackupHeight = 0;
|
int imageBackupHeight = 0;
|
||||||
size_t imageBackupSize = 0;
|
size_t imageBackupSize = 0;
|
||||||
|
size_t imageBackupCapacity = 0;
|
||||||
bool hasImageBackup = false;
|
bool hasImageBackup = false;
|
||||||
|
bool imageBackupIsRgb565 = false;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
PageNavigation(CommonData &common){
|
PageNavigation(CommonData &common){
|
||||||
commonData = &common;
|
commonData = &common;
|
||||||
common.logger->logDebug(GwLog::LOG,"Instantiate PageNavigation");
|
common.logger->logDebug(GwLog::LOG,"Instantiate PageNavigation");
|
||||||
imageBackupData = (uint8_t*)heap_caps_malloc((GxEPD_WIDTH * GxEPD_HEIGHT), MALLOC_CAP_SPIRAM);
|
imageBackupCapacity = (size_t)GxEPD_WIDTH * (size_t)GxEPD_HEIGHT;
|
||||||
|
#ifdef DISPLAY_ST7796
|
||||||
|
imageBackupCapacity *= 2U;
|
||||||
|
#endif
|
||||||
|
imageBackupData = (uint8_t*)heap_caps_malloc(imageBackupCapacity, MALLOC_CAP_SPIRAM);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set botton labels
|
// Set botton labels
|
||||||
@@ -395,11 +449,13 @@ bool showValues = false; // Show values HDT, SOG, DBT in navigation map
|
|||||||
int numPix = json["number_pixels"] | 0; // Read number of pixels
|
int numPix = json["number_pixels"] | 0; // Read number of pixels
|
||||||
imgWidth = json["width"] | 0; // Read width of image
|
imgWidth = json["width"] | 0; // Read width of image
|
||||||
imgHeight = json["height"] | 0; // Read height og image
|
imgHeight = json["height"] | 0; // Read height og image
|
||||||
size_t requiredBytes = 0;
|
size_t requiredBytesMono = 0;
|
||||||
|
size_t requiredBytesRgb565 = 0;
|
||||||
if (imgWidth > 0 && imgHeight > 0){
|
if (imgWidth > 0 && imgHeight > 0){
|
||||||
requiredBytes = (size_t)((imgWidth + 7) / 8) * (size_t)imgHeight;
|
requiredBytesMono = (size_t)((imgWidth + 7) / 8) * (size_t)imgHeight;
|
||||||
|
requiredBytesRgb565 = (size_t)imgWidth * (size_t)imgHeight * 2U;
|
||||||
}
|
}
|
||||||
if (requiredBytes == 0){
|
if (requiredBytesMono == 0){
|
||||||
LOG_DEBUG(GwLog::ERROR,"Error PageNavigation: invalid image geometry w=%d h=%d",imgWidth,imgHeight);
|
LOG_DEBUG(GwLog::ERROR,"Error PageNavigation: invalid image geometry w=%d h=%d",imgWidth,imgHeight);
|
||||||
return PAGE_UPDATE;
|
return PAGE_UPDATE;
|
||||||
}
|
}
|
||||||
@@ -420,10 +476,15 @@ bool showValues = false; // Show values HDT, SOG, DBT in navigation map
|
|||||||
|
|
||||||
// Set image buffer in PSRAM
|
// Set image buffer in PSRAM
|
||||||
//size_t imgSize = getdisplay().width() * getdisplay().height();
|
//size_t imgSize = getdisplay().width() * getdisplay().height();
|
||||||
size_t imgSize = (numPix > 0) ? (size_t)numPix : requiredBytes; // Calculate image size
|
size_t imgSize = (numPix > 0) ? (size_t)numPix : requiredBytesMono; // Calculate image size
|
||||||
if (imgSize < requiredBytes){
|
if (imgSize < requiredBytesMono){
|
||||||
imgSize = requiredBytes;
|
imgSize = requiredBytesMono;
|
||||||
}
|
}
|
||||||
|
#ifdef DISPLAY_ST7796
|
||||||
|
if (imgSize < requiredBytesRgb565){
|
||||||
|
imgSize = requiredBytesRgb565;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
uint8_t* imageData = (uint8_t*) heap_caps_malloc(imgSize, MALLOC_CAP_SPIRAM); // Allocate PSRAM for image
|
uint8_t* imageData = (uint8_t*) heap_caps_malloc(imgSize, MALLOC_CAP_SPIRAM); // Allocate PSRAM for image
|
||||||
if (!imageData) {
|
if (!imageData) {
|
||||||
LOG_DEBUG(GwLog::ERROR,"Error PageNavigation: PSRAM alloc image buffer failed");
|
LOG_DEBUG(GwLog::ERROR,"Error PageNavigation: PSRAM alloc image buffer failed");
|
||||||
@@ -434,7 +495,7 @@ bool showValues = false; // Show values HDT, SOG, DBT in navigation map
|
|||||||
// Decode Base64 content to image
|
// Decode Base64 content to image
|
||||||
size_t decodedSize = 0;
|
size_t decodedSize = 0;
|
||||||
bool decodeOk = decoder.decodeBase64(b64, b64len, imageData, imgSize, decodedSize);
|
bool decodeOk = decoder.decodeBase64(b64, b64len, imageData, imgSize, decodedSize);
|
||||||
if (!decodeOk || decodedSize < requiredBytes){
|
if (!decodeOk || decodedSize < requiredBytesMono){
|
||||||
int base64Ret = mbedtls_base64_decode(
|
int base64Ret = mbedtls_base64_decode(
|
||||||
nullptr,
|
nullptr,
|
||||||
0,
|
0,
|
||||||
@@ -446,7 +507,7 @@ bool showValues = false; // Show values HDT, SOG, DBT in navigation map
|
|||||||
"Error PageNavigation: decode failed (ok=%d, decoded=%u, required=%u, b64ret=%d)",
|
"Error PageNavigation: decode failed (ok=%d, decoded=%u, required=%u, b64ret=%d)",
|
||||||
decodeOk ? 1 : 0,
|
decodeOk ? 1 : 0,
|
||||||
(unsigned int)decodedSize,
|
(unsigned int)decodedSize,
|
||||||
(unsigned int)requiredBytes,
|
(unsigned int)requiredBytesMono,
|
||||||
base64Ret
|
base64Ret
|
||||||
);
|
);
|
||||||
free(b64);
|
free(b64);
|
||||||
@@ -454,21 +515,42 @@ bool showValues = false; // Show values HDT, SOG, DBT in navigation map
|
|||||||
return PAGE_UPDATE;
|
return PAGE_UPDATE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool imageIsRgb565 = false;
|
||||||
|
#ifdef DISPLAY_ST7796
|
||||||
|
imageIsRgb565 = (decodedSize >= requiredBytesRgb565);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef DISPLAY_ST7796
|
||||||
|
if (kShowRgb565StripeTestImage) {
|
||||||
|
createRgb565StripeImage(reinterpret_cast<uint16_t*>(imageData), imgWidth, imgHeight);
|
||||||
|
decodedSize = requiredBytesRgb565;
|
||||||
|
imageIsRgb565 = true;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
// Copy actual navigation man to ackup map
|
// Copy actual navigation man to ackup map
|
||||||
imageBackupWidth = imgWidth;
|
imageBackupWidth = imgWidth;
|
||||||
imageBackupHeight = imgHeight;
|
imageBackupHeight = imgHeight;
|
||||||
imageBackupSize = imgSize;
|
imageBackupSize = imgSize;
|
||||||
if (decodedSize > 0 && imageBackupData != nullptr) {
|
if (decodedSize > 0 && imageBackupData != nullptr) {
|
||||||
size_t backupCapacity = (size_t)GxEPD_WIDTH * (size_t)GxEPD_HEIGHT;
|
size_t copySize = (decodedSize > imageBackupCapacity) ? imageBackupCapacity : decodedSize;
|
||||||
size_t copySize = (decodedSize > backupCapacity) ? backupCapacity : decodedSize;
|
|
||||||
memcpy(imageBackupData, imageData, copySize);
|
memcpy(imageBackupData, imageData, copySize);
|
||||||
imageBackupSize = copySize;
|
imageBackupSize = copySize;
|
||||||
}
|
}
|
||||||
|
imageBackupIsRgb565 = imageIsRgb565;
|
||||||
hasImageBackup = (imageBackupData != nullptr);
|
hasImageBackup = (imageBackupData != nullptr);
|
||||||
lostCounter = 0;
|
lostCounter = 0;
|
||||||
|
|
||||||
// Show image (navigation map)
|
// Show image (navigation map)
|
||||||
|
#ifdef DISPLAY_ST7796
|
||||||
|
if (imageIsRgb565) {
|
||||||
|
drawRgb565Image(0, 25, reinterpret_cast<const uint16_t*>(imageData), imgWidth, imgHeight);
|
||||||
|
} else {
|
||||||
|
displayDrawBitmap(0, 25, imageData, imgWidth, imgHeight, commonData->fgcolor);
|
||||||
|
}
|
||||||
|
#else
|
||||||
displayDrawBitmap(0, 25, imageData, imgWidth, imgHeight, commonData->fgcolor);
|
displayDrawBitmap(0, 25, imageData, imgWidth, imgHeight, commonData->fgcolor);
|
||||||
|
#endif
|
||||||
|
|
||||||
// Clean PSRAM
|
// Clean PSRAM
|
||||||
free(b64);
|
free(b64);
|
||||||
@@ -491,7 +573,15 @@ bool showValues = false; // Show values HDT, SOG, DBT in navigation map
|
|||||||
|
|
||||||
// Show backup image (backup navigation map)
|
// Show backup image (backup navigation map)
|
||||||
if (hasImageBackup) {
|
if (hasImageBackup) {
|
||||||
|
#ifdef DISPLAY_ST7796
|
||||||
|
if (imageBackupIsRgb565) {
|
||||||
|
drawRgb565Image(0, 25, reinterpret_cast<const uint16_t*>(imageBackupData), imageBackupWidth, imageBackupHeight);
|
||||||
|
} else {
|
||||||
|
displayDrawBitmap(0, 25, imageBackupData, imageBackupWidth, imageBackupHeight, commonData->fgcolor);
|
||||||
|
}
|
||||||
|
#else
|
||||||
displayDrawBitmap(0, 25, imageBackupData, imageBackupWidth, imageBackupHeight, commonData->fgcolor);
|
displayDrawBitmap(0, 25, imageBackupData, imageBackupWidth, imageBackupHeight, commonData->fgcolor);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
// Show connection lost info when 5 page refreshes has a connection lost to the map server
|
// Show connection lost info when 5 page refreshes has a connection lost to the map server
|
||||||
|
|||||||
Reference in New Issue
Block a user