Implement crop mode for cover image on sleep screen.

This commit is contained in:
Jonas Diemer
2026-01-03 13:48:46 +01:00
parent 5fdf23f1d2
commit a99ad3b6cd
6 changed files with 44 additions and 16 deletions

View File

@@ -152,18 +152,24 @@ void GfxRenderer::drawImage(const uint8_t bitmap[], const int x, const int y, co
einkDisplay.drawImage(bitmap, rotatedX, rotatedY, width, height);
}
void GfxRenderer::drawBitmap(const Bitmap& bitmap, const int x, const int y, const int maxWidth,
const int maxHeight) const {
void GfxRenderer::drawBitmap(const Bitmap& bitmap, const int x, const int y, const int maxWidth, const int maxHeight,
const float cropX, const float cropY) const {
float scale = 1.0f;
bool isScaled = false;
if (maxWidth > 0 && bitmap.getWidth() > maxWidth) {
scale = static_cast<float>(maxWidth) / static_cast<float>(bitmap.getWidth());
int cropPixX = std::floor(bitmap.getWidth() * cropX / 2.0f);
int cropPixY = std::floor(bitmap.getHeight() * cropY / 2.0f);
Serial.printf("[%lu] [GFX] Cropping %dx%d by %dx%d pix, is %s\n", millis(), bitmap.getWidth(), bitmap.getHeight(),
cropPixX, cropPixY, bitmap.isTopDown() ? "top-down" : "bottom-up");
if (maxWidth > 0 && (1.0f - cropX) * bitmap.getWidth() > maxWidth) {
scale = static_cast<float>(maxWidth) / static_cast<float>((1.0f - cropX) * bitmap.getWidth());
isScaled = true;
}
if (maxHeight > 0 && bitmap.getHeight() > maxHeight) {
scale = std::min(scale, static_cast<float>(maxHeight) / static_cast<float>(bitmap.getHeight()));
if (maxHeight > 0 && (1.0f - cropY) * bitmap.getHeight() > maxHeight) {
scale = std::min(scale, static_cast<float>(maxHeight) / static_cast<float>((1.0f - cropY) * bitmap.getHeight()));
isScaled = true;
}
Serial.printf("[%lu] [GFX] Scaling by %f - %s\n", millis(), scale, isScaled ? "scaled" : "not scaled");
// Calculate output row size (2 bits per pixel, packed into bytes)
// IMPORTANT: Use int, not uint8_t, to avoid overflow for images > 1020 pixels wide
@@ -178,10 +184,10 @@ void GfxRenderer::drawBitmap(const Bitmap& bitmap, const int x, const int y, con
return;
}
for (int bmpY = 0; bmpY < bitmap.getHeight(); bmpY++) {
for (int bmpY = 0; bmpY < (bitmap.getHeight() - cropPixY); bmpY++) {
// The BMP's (0, 0) is the bottom-left corner (if the height is positive, top-left if negative).
// Screen's (0, 0) is the top-left corner.
int screenY = y + (bitmap.isTopDown() ? bmpY : bitmap.getHeight() - 1 - bmpY);
int screenY = y - cropPixY + (bitmap.isTopDown() ? bmpY : bitmap.getHeight() - 1 - bmpY);
if (isScaled) {
screenY = std::floor(screenY * scale);
}
@@ -196,8 +202,13 @@ void GfxRenderer::drawBitmap(const Bitmap& bitmap, const int x, const int y, con
return;
}
for (int bmpX = 0; bmpX < bitmap.getWidth(); bmpX++) {
int screenX = x + bmpX;
if (bmpY < cropPixY) {
// Skip the row if it's outside the crop area
continue;
}
for (int bmpX = cropPixX; bmpX < bitmap.getWidth() - cropPixX; bmpX++) {
int screenX = x + bmpX - cropPixX;
if (isScaled) {
screenX = std::floor(screenX * scale);
}