feat(sleep): pre-calculate EPUB cover dimensions for FIT/CROP modes

- Add JpegToBmpConverter::getJpegDimensions() to extract JPEG dimensions
- Fix getCoverBmpPath() ternary operator precedence bug
- Pre-calculate exact dimensions per mode:
  * FIT: width=480px, height=(480*jpegHeight)/jpegWidth
  * CROP: height=800px, width=(800*jpegWidth)/jpegHeight
- Generate separate cache files (cover_fit.bmp vs cover_crop.bmp)
- Eliminates runtime scaling artifacts, improves sleep screen clarity
This commit is contained in:
pablohc 2026-01-23 23:53:24 +01:00 committed by cottongin
parent e3ae125f3c
commit 881f866d86
No known key found for this signature in database
GPG Key ID: 0ECC91FE4655C262
3 changed files with 58 additions and 3 deletions

View File

@ -425,8 +425,7 @@ const std::string& Epub::getLanguage() const {
}
std::string Epub::getCoverBmpPath(bool cropped) const {
const auto coverFileName = "cover" + cropped ? "_crop" : "";
return cachePath + "/" + coverFileName + ".bmp";
return cropped ? (cachePath + "/cover_crop.bmp") : (cachePath + "/cover_fit.bmp");
}
bool Epub::generateCoverBmp(bool cropped) const {
@ -462,12 +461,37 @@ bool Epub::generateCoverBmp(bool cropped) const {
return false;
}
// Get JPEG dimensions to calculate target dimensions for FIT/CROP
int jpegWidth, jpegHeight;
if (!JpegToBmpConverter::getJpegDimensions(coverJpg, jpegWidth, jpegHeight)) {
Serial.printf("[%lu] [EBP] Failed to get JPEG dimensions\n", millis());
coverJpg.close();
return false;
}
// Calculate target dimensions based on FIT/CROP mode
// FIT: ancho fijo 480px, alto proporcional = 480 * (jpegHeight / jpegWidth)
// CROP: alto fijo 800px, ancho proporcional = 800 * (jpegWidth / jpegHeight)
int targetWidth, targetHeight;
if (cropped) {
// CROP mode: height = 800, width proportional
targetHeight = 800;
targetWidth = (800 * jpegWidth) / jpegHeight;
} else {
// FIT mode: width = 480, height proportional
targetWidth = 480;
targetHeight = (480 * jpegHeight) / jpegWidth;
}
Serial.printf("[%lu] [EBP] Calculated %s dimensions: %dx%d (original JPEG: %dx%d)\n", millis(),
cropped ? "CROP" : "FIT", targetWidth, targetHeight, jpegWidth, jpegHeight);
FsFile coverBmp;
if (!SdMan.openFileForWrite("EBP", getCoverBmpPath(cropped), coverBmp)) {
coverJpg.close();
return false;
}
const bool success = JpegToBmpConverter::jpegFileToBmpStream(coverJpg, coverBmp);
const bool success = JpegToBmpConverter::jpegFileToBmpStreamWithSize(coverJpg, coverBmp, targetWidth, targetHeight);
coverJpg.close();
coverBmp.close();
SdMan.remove(coverJpgTempPath.c_str());

View File

@ -565,3 +565,32 @@ bool JpegToBmpConverter::jpegFileTo1BitBmpStreamWithSize(FsFile& jpegFile, Print
int targetMaxHeight) {
return jpegFileToBmpStreamInternal(jpegFile, bmpOut, targetMaxWidth, targetMaxHeight, true);
}
// Get JPEG dimensions without full conversion
bool JpegToBmpConverter::getJpegDimensions(FsFile& jpegFile, int& width, int& height) {
// Reset file position to beginning
if (!jpegFile.seek(0)) {
Serial.printf("[%lu] [JPG] Failed to seek to beginning of JPEG file\n", millis());
return false;
}
// Initialize JPEG decoder
pjpeg_image_info_t imageInfo = {};
JpegReadContext context{jpegFile, {}, 0, 0};
const int decodeStatus = pjpeg_decode_init(&imageInfo, jpegReadCallback, &context, false);
if (decodeStatus != 0) {
Serial.printf("[%lu] [JPG] pjpeg_decode_init failed with status %d\n", millis(), decodeStatus);
return false;
}
// Get dimensions from image info
width = imageInfo.m_width;
height = imageInfo.m_height;
Serial.printf("[%lu] [JPG] Read JPEG dimensions: %dx%d\n", millis(), width, height);
// Reset file position after reading
jpegFile.seek(0);
return true;
}

View File

@ -16,4 +16,6 @@ class JpegToBmpConverter {
static bool jpegFileToBmpStreamWithSize(FsFile& jpegFile, Print& bmpOut, int targetMaxWidth, int targetMaxHeight);
// Convert to 1-bit BMP (black and white only, no grays) for fast home screen rendering
static bool jpegFileTo1BitBmpStreamWithSize(FsFile& jpegFile, Print& bmpOut, int targetMaxWidth, int targetMaxHeight);
// Get JPEG dimensions without full conversion
static bool getJpegDimensions(FsFile& jpegFile, int& width, int& height);
};