Custom sleep screen support with BMP reading (#57)

## Summary

* Builds on top of
https://github.com/daveallie/crosspoint-reader/pull/16 - adresses
https://github.com/daveallie/crosspoint-reader/discussions/14
* This PR adds the ability for the user to supply a custom `sleep.bmp`
image at the root of the SD card that will be shown instead of the
default sleep screen if present.
* Supports:
  * Different BPPs:
    * 1bit
    * 2bit
    * 8bit
    * 24bit
    * 32bit (with alpha-channel ignored)
  * Grayscale rendering

---------

Co-authored-by: Sam Davis <sam@sjd.co>
This commit is contained in:
Dave Allie
2025-12-19 08:45:14 +11:00
committed by GitHub
parent b2020f5512
commit 1a3d6b125d
6 changed files with 374 additions and 0 deletions

View File

@@ -3,10 +3,26 @@
#include <GfxRenderer.h>
#include "CrossPointSettings.h"
#include "SD.h"
#include "config.h"
#include "images/CrossLarge.h"
void SleepActivity::onEnter() {
// Look for sleep.bmp on the root of the sd card to determine if we should
// render a custom sleep screen instead of the default.
auto file = SD.open("/sleep.bmp");
if (file) {
Bitmap bitmap(file);
if (bitmap.parseHeaders() == BmpReaderError::Ok) {
renderCustomSleepScreen(bitmap);
return;
}
}
renderDefaultSleepScreen();
}
void SleepActivity::renderDefaultSleepScreen() const {
const auto pageWidth = GfxRenderer::getScreenWidth();
const auto pageHeight = GfxRenderer::getScreenHeight();
@@ -22,3 +38,50 @@ void SleepActivity::onEnter() {
renderer.displayBuffer(EInkDisplay::HALF_REFRESH);
}
void SleepActivity::renderCustomSleepScreen(const Bitmap& bitmap) const {
int x, y;
const auto pageWidth = GfxRenderer::getScreenWidth();
const auto pageHeight = GfxRenderer::getScreenHeight();
if (bitmap.getWidth() > pageWidth || bitmap.getHeight() > pageHeight) {
// image will scale, make sure placement is right
const float ratio = static_cast<float>(bitmap.getWidth()) / static_cast<float>(bitmap.getHeight());
const float screenRatio = static_cast<float>(pageWidth) / static_cast<float>(pageHeight);
if (ratio > screenRatio) {
// image wider than viewport ratio, scaled down image needs to be centered vertically
x = 0;
y = (pageHeight - pageWidth / ratio) / 2;
} else {
// image taller than viewport ratio, scaled down image needs to be centered horizontally
x = (pageWidth - pageHeight * ratio) / 2;
y = 0;
}
} else {
// center the image
x = (pageWidth - bitmap.getWidth()) / 2;
y = (pageHeight - bitmap.getHeight()) / 2;
}
renderer.clearScreen();
renderer.drawBitmap(bitmap, x, y, pageWidth, pageHeight);
renderer.displayBuffer(EInkDisplay::HALF_REFRESH);
if (bitmap.hasGreyscale()) {
bitmap.rewindToData();
renderer.clearScreen(0x00);
renderer.setRenderMode(GfxRenderer::GRAYSCALE_LSB);
renderer.drawBitmap(bitmap, x, y, pageWidth, pageHeight);
renderer.copyGrayscaleLsbBuffers();
bitmap.rewindToData();
renderer.clearScreen(0x00);
renderer.setRenderMode(GfxRenderer::GRAYSCALE_MSB);
renderer.drawBitmap(bitmap, x, y, pageWidth, pageHeight);
renderer.copyGrayscaleMsbBuffers();
renderer.displayGrayBuffer();
renderer.setRenderMode(GfxRenderer::BW);
}
}

View File

@@ -1,8 +1,14 @@
#pragma once
#include "../Activity.h"
class Bitmap;
class SleepActivity final : public Activity {
public:
explicit SleepActivity(GfxRenderer& renderer, InputManager& inputManager) : Activity(renderer, inputManager) {}
void onEnter() override;
private:
void renderDefaultSleepScreen() const;
void renderCustomSleepScreen(const Bitmap& bitmap) const;
};