(Conditionally) add further dithering algorithms

This commit is contained in:
jpirnay
2026-04-06 17:23:29 +02:00
parent 0ba4626157
commit 4f031b00b1
8 changed files with 102 additions and 6 deletions
+4
View File
@@ -137,12 +137,16 @@ class CrossPointSettings {
// Image rendering in EPUB reader
enum IMAGE_RENDERING { IMAGES_DISPLAY = 0, IMAGES_PLACEHOLDER = 1, IMAGES_SUPPRESS = 2, IMAGE_RENDERING_COUNT };
#ifdef ENABLE_IMAGE_DITHERING_EXTENSION
enum IMAGE_DITHERING {
IMAGE_DITHER_BAYER = 0,
IMAGE_DITHER_ATKINSON = 1,
IMAGE_DITHER_DIFFUSED_BAYER = 2,
IMAGE_DITHERING_COUNT
};
#else
enum IMAGE_DITHERING { IMAGE_DITHER_BAYER = 0, IMAGE_DITHERING_COUNT };
#endif
// Timezone options (POSIX TZ rules for DST support)
enum TIMEZONE {
+2
View File
@@ -69,10 +69,12 @@ inline const std::vector<SettingInfo>& getSettingsList() {
SettingInfo::Enum(StrId::STR_IMAGES, &CrossPointSettings::imageRendering,
{StrId::STR_IMAGES_DISPLAY, StrId::STR_IMAGES_PLACEHOLDER, StrId::STR_IMAGES_SUPPRESS},
"imageRendering", StrId::STR_CAT_READER),
#ifdef ENABLE_IMAGE_DITHERING_EXTENSION
SettingInfo::Enum(
StrId::STR_IMAGE_DITHERING, &CrossPointSettings::imageDithering,
{StrId::STR_IMAGE_DITHER_BAYER, StrId::STR_IMAGE_DITHER_ATKINSON, StrId::STR_IMAGE_DITHER_DIFFUSED_BAYER},
"imageDithering", StrId::STR_CAT_READER),
#endif
SettingInfo::Toggle(StrId::STR_CREATE_FALLBACK_FOR_INVALID_TOC, &CrossPointSettings::syntheticTocFallback,
"syntheticTocFallback", StrId::STR_CAT_READER),
// --- Controls ---
+27 -2
View File
@@ -20,7 +20,9 @@ constexpr const char* SLEEP_BMP_PATH = "/sleep.bmp";
constexpr const char* SLEEP_BMP_TMP_PATH = "/sleep.bmp.tmp";
constexpr const char* SLEEP_BMP_BACKUP_PATH = "/sleep.bmp.bak";
#ifdef ENABLE_IMAGE_DITHERING_EXTENSION
uint8_t normalizeImageDitherModeValue(uint8_t mode) { return static_cast<uint8_t>(imageDitherModeFromSetting(mode)); }
#endif
bool isBmpFile(const std::string& path) { return FsHelpers::hasBmpExtension(path); }
@@ -87,8 +89,15 @@ bool replaceSleepBmpFromTemp() {
BmpViewerActivity::BmpViewerActivity(GfxRenderer& renderer, MappedInputManager& mappedInput, std::string path)
: Activity("BmpViewer", renderer, mappedInput),
filePath(std::move(path)),
imageDitherMode(normalizeImageDitherModeValue(SETTINGS.imageDithering)) {}
filePath(std::move(path))
#ifdef ENABLE_IMAGE_DITHERING_EXTENSION
,
imageDitherMode(normalizeImageDitherModeValue(SETTINGS.imageDithering)) {
}
#else
{
}
#endif
bool BmpViewerActivity::renderCurrentImage(const bool showControls) {
return isBmpFile(filePath) ? renderBmpImage(showControls) : renderDecodedImage(showControls);
@@ -139,8 +148,12 @@ bool BmpViewerActivity::renderBmpImage(const bool showControls) {
renderer.clearScreen();
renderer.drawBitmap(bitmap, x, y, pageWidth, pageHeight, 0, 0);
if (showControls) {
#ifdef ENABLE_IMAGE_DITHERING_EXTENSION
const auto labels =
mappedInput.mapLabels(tr(STR_BACK), "", I18N.get(getCurrentDitherModeLabel()), tr(STR_SET_SLEEP_SCREEN));
#else
const auto labels = mappedInput.mapLabels(tr(STR_BACK), "", "", tr(STR_SET_SLEEP_SCREEN));
#endif
GUI.drawButtonHints(renderer, labels.btn1, labels.btn2, labels.btn3, labels.btn4);
}
renderer.displayBuffer(HalDisplay::HALF_REFRESH);
@@ -179,21 +192,30 @@ bool BmpViewerActivity::renderDecodedImage(const bool showControls) {
config.useExactDimensions = true;
config.useGrayscale = true;
config.useDithering = true;
#ifdef ENABLE_IMAGE_DITHERING_EXTENSION
config.ditherMode = imageDitherModeFromSetting(imageDitherMode);
#else
config.ditherMode = ImageDitherMode::Bayer;
#endif
if (!decoder->decodeToFramebuffer(filePath, renderer, config)) {
return false;
}
if (showControls) {
#ifdef ENABLE_IMAGE_DITHERING_EXTENSION
const auto labels =
mappedInput.mapLabels(tr(STR_BACK), "", I18N.get(getCurrentDitherModeLabel()), tr(STR_SET_SLEEP_SCREEN));
#else
const auto labels = mappedInput.mapLabels(tr(STR_BACK), "", "", tr(STR_SET_SLEEP_SCREEN));
#endif
GUI.drawButtonHints(renderer, labels.btn1, labels.btn2, labels.btn3, labels.btn4);
}
renderer.displayBuffer(HalDisplay::HALF_REFRESH);
return true;
}
#ifdef ENABLE_IMAGE_DITHERING_EXTENSION
StrId BmpViewerActivity::getCurrentDitherModeLabel() const {
switch (imageDitherModeFromSetting(imageDitherMode)) {
case ImageDitherMode::Atkinson:
@@ -216,6 +238,7 @@ void BmpViewerActivity::cycleDitherMode() {
renderError("Could not render image");
}
}
#endif
void BmpViewerActivity::renderError(const char* message) {
const auto pageHeight = renderer.getScreenHeight();
@@ -278,10 +301,12 @@ void BmpViewerActivity::loop() {
return;
}
#ifdef ENABLE_IMAGE_DITHERING_EXTENSION
if (mappedInput.wasReleased(MappedInputManager::Button::Left)) {
cycleDitherMode();
return;
}
#endif
// Next/Right button: set this image as the sleep screen
if (mappedInput.wasReleased(MappedInputManager::Button::Right)) {
+4
View File
@@ -19,12 +19,16 @@ class BmpViewerActivity final : public Activity {
private:
std::string filePath;
#ifdef ENABLE_IMAGE_DITHERING_EXTENSION
uint8_t imageDitherMode;
#endif
bool renderCurrentImage(bool showControls = true);
bool renderBmpImage(bool showControls = true);
bool renderDecodedImage(bool showControls = true);
#ifdef ENABLE_IMAGE_DITHERING_EXTENSION
void cycleDitherMode();
StrId getCurrentDitherModeLabel() const;
#endif
void renderError(const char* message);
void setAsSleepScreen();
};