mirror of
https://github.com/daveallie/crosspoint-reader.git
synced 2026-02-04 14:47:37 +03:00
feat: Add support to B&W filters to image covers (#476)
## Summary * **What is the goal of this PR?** (e.g., Implements the new feature for file uploading.) Implementation of a new feature in Display options as Image Filter * **What changes are included?** Black & White and Inverted Black & White options are added. ## Additional Context Here are some examples: | None | Contrast | Inverted | | --- | --- | --- | | <img alt="image" src="https://github.com/user-attachments/assets/fe02dd9b-f647-41bd-8495-c262f73177c4" /> | <img alt="image" src="https://github.com/user-attachments/assets/2d17747d-3ff6-48a9-b9b9-eb17cccf19cf" /> | <img alt="image" src="https://github.com/user-attachments/assets/792dea50-f003-4634-83fe-77849ca49095" /> | | <img alt="image" src="https://github.com/user-attachments/assets/28395b63-14f8-41e2-886b-8ddf3faeafc4" /> | <img alt="image" src="https://github.com/user-attachments/assets/71a569c8-fc54-4647-ad4c-ec96e220cddb" /> | <img alt="image" src="https://github.com/user-attachments/assets/9139e32c-9175-433e-8372-45fa042d3dc9" /> | * Add any other information that might be helpful for the reviewer (e.g., performance implications, potential risks, specific areas to focus on). I have also tried adding Color inversion, but could not see much difference with that. It might be because my implementation was wrong. --- ### AI Usage While CrossPoint doesn't have restrictions on AI tools in contributing, please be transparent about their usage as it helps set the right context for reviewers. Did you use AI tools to help write this code? _** PARTIALLY **_ --------- Co-authored-by: Dave Allie <dave@daveallie.com>
This commit is contained in:
parent
e1849983b8
commit
5fa58a002c
@ -105,6 +105,10 @@ The Settings screen allows you to configure the device's behavior. There are a f
|
|||||||
- **Sleep Screen Cover Mode**: How to display the book cover when "Cover" sleep screen is selected:
|
- **Sleep Screen Cover Mode**: How to display the book cover when "Cover" sleep screen is selected:
|
||||||
- "Fit" (default) - Scale the image down to fit centered on the screen, padding with white borders as necessary
|
- "Fit" (default) - Scale the image down to fit centered on the screen, padding with white borders as necessary
|
||||||
- "Crop" - Scale the image down and crop as necessary to try to to fill the screen (Note: this is experimental and may not work as expected)
|
- "Crop" - Scale the image down and crop as necessary to try to to fill the screen (Note: this is experimental and may not work as expected)
|
||||||
|
- **Sleep Screen Cover Filter**: What filter will be applied to the book cover when "Cover" sleep screen is selected
|
||||||
|
- "None" (default) - The cover image will be converted to a grayscale image and displayed as it is
|
||||||
|
- "Contrast" - The image will be displayed as a black & white image without grayscale conversion
|
||||||
|
- "Inverted" - The image will be inverted as in white&black and will be displayed without grayscale conversion
|
||||||
- **Status Bar**: Configure the status bar displayed while reading:
|
- **Status Bar**: Configure the status bar displayed while reading:
|
||||||
- "None" - No status bar
|
- "None" - No status bar
|
||||||
- "No Progress" - Show status bar without reading progress
|
- "No Progress" - Show status bar without reading progress
|
||||||
|
|||||||
@ -22,7 +22,7 @@ void readAndValidate(FsFile& file, uint8_t& member, const uint8_t maxValue) {
|
|||||||
namespace {
|
namespace {
|
||||||
constexpr uint8_t SETTINGS_FILE_VERSION = 1;
|
constexpr uint8_t SETTINGS_FILE_VERSION = 1;
|
||||||
// Increment this when adding new persisted settings fields
|
// Increment this when adding new persisted settings fields
|
||||||
constexpr uint8_t SETTINGS_COUNT = 22;
|
constexpr uint8_t SETTINGS_COUNT = 23;
|
||||||
constexpr char SETTINGS_FILE[] = "/.crosspoint/settings.bin";
|
constexpr char SETTINGS_FILE[] = "/.crosspoint/settings.bin";
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
@ -57,9 +57,10 @@ bool CrossPointSettings::saveToFile() const {
|
|||||||
serialization::writePod(outputFile, hideBatteryPercentage);
|
serialization::writePod(outputFile, hideBatteryPercentage);
|
||||||
serialization::writePod(outputFile, longPressChapterSkip);
|
serialization::writePod(outputFile, longPressChapterSkip);
|
||||||
serialization::writePod(outputFile, hyphenationEnabled);
|
serialization::writePod(outputFile, hyphenationEnabled);
|
||||||
// New fields added at end for backward compatibility
|
|
||||||
serialization::writeString(outputFile, std::string(opdsUsername));
|
serialization::writeString(outputFile, std::string(opdsUsername));
|
||||||
serialization::writeString(outputFile, std::string(opdsPassword));
|
serialization::writeString(outputFile, std::string(opdsPassword));
|
||||||
|
serialization::writePod(outputFile, sleepScreenCoverFilter);
|
||||||
|
// New fields added at end for backward compatibility
|
||||||
outputFile.close();
|
outputFile.close();
|
||||||
|
|
||||||
Serial.printf("[%lu] [CPS] Settings saved to file\n", millis());
|
Serial.printf("[%lu] [CPS] Settings saved to file\n", millis());
|
||||||
@ -131,7 +132,6 @@ bool CrossPointSettings::loadFromFile() {
|
|||||||
if (++settingsRead >= fileSettingsCount) break;
|
if (++settingsRead >= fileSettingsCount) break;
|
||||||
serialization::readPod(inputFile, hyphenationEnabled);
|
serialization::readPod(inputFile, hyphenationEnabled);
|
||||||
if (++settingsRead >= fileSettingsCount) break;
|
if (++settingsRead >= fileSettingsCount) break;
|
||||||
// New fields added at end for backward compatibility
|
|
||||||
{
|
{
|
||||||
std::string usernameStr;
|
std::string usernameStr;
|
||||||
serialization::readString(inputFile, usernameStr);
|
serialization::readString(inputFile, usernameStr);
|
||||||
@ -146,6 +146,9 @@ bool CrossPointSettings::loadFromFile() {
|
|||||||
opdsPassword[sizeof(opdsPassword) - 1] = '\0';
|
opdsPassword[sizeof(opdsPassword) - 1] = '\0';
|
||||||
}
|
}
|
||||||
if (++settingsRead >= fileSettingsCount) break;
|
if (++settingsRead >= fileSettingsCount) break;
|
||||||
|
readAndValidate(inputFile, sleepScreenCoverFilter, SLEEP_SCREEN_COVER_FILTER_COUNT);
|
||||||
|
if (++settingsRead >= fileSettingsCount) break;
|
||||||
|
// New fields added at end for backward compatibility
|
||||||
} while (false);
|
} while (false);
|
||||||
|
|
||||||
inputFile.close();
|
inputFile.close();
|
||||||
|
|||||||
@ -17,6 +17,12 @@ class CrossPointSettings {
|
|||||||
|
|
||||||
enum SLEEP_SCREEN_MODE { DARK = 0, LIGHT = 1, CUSTOM = 2, COVER = 3, BLANK = 4, SLEEP_SCREEN_MODE_COUNT };
|
enum SLEEP_SCREEN_MODE { DARK = 0, LIGHT = 1, CUSTOM = 2, COVER = 3, BLANK = 4, SLEEP_SCREEN_MODE_COUNT };
|
||||||
enum SLEEP_SCREEN_COVER_MODE { FIT = 0, CROP = 1, SLEEP_SCREEN_COVER_MODE_COUNT };
|
enum SLEEP_SCREEN_COVER_MODE { FIT = 0, CROP = 1, SLEEP_SCREEN_COVER_MODE_COUNT };
|
||||||
|
enum SLEEP_SCREEN_COVER_FILTER {
|
||||||
|
NO_FILTER = 0,
|
||||||
|
BLACK_AND_WHITE = 1,
|
||||||
|
INVERTED_BLACK_AND_WHITE = 2,
|
||||||
|
SLEEP_SCREEN_COVER_FILTER_COUNT
|
||||||
|
};
|
||||||
|
|
||||||
// Status bar display type enum
|
// Status bar display type enum
|
||||||
enum STATUS_BAR_MODE {
|
enum STATUS_BAR_MODE {
|
||||||
@ -95,6 +101,8 @@ class CrossPointSettings {
|
|||||||
uint8_t sleepScreen = DARK;
|
uint8_t sleepScreen = DARK;
|
||||||
// Sleep screen cover mode settings
|
// Sleep screen cover mode settings
|
||||||
uint8_t sleepScreenCoverMode = FIT;
|
uint8_t sleepScreenCoverMode = FIT;
|
||||||
|
// Sleep screen cover filter
|
||||||
|
uint8_t sleepScreenCoverFilter = NO_FILTER;
|
||||||
// Status bar settings
|
// Status bar settings
|
||||||
uint8_t statusBar = FULL;
|
uint8_t statusBar = FULL;
|
||||||
// Text rendering settings
|
// Text rendering settings
|
||||||
|
|||||||
@ -179,10 +179,19 @@ void SleepActivity::renderBitmapSleepScreen(const Bitmap& bitmap) const {
|
|||||||
|
|
||||||
Serial.printf("[%lu] [SLP] drawing to %d x %d\n", millis(), x, y);
|
Serial.printf("[%lu] [SLP] drawing to %d x %d\n", millis(), x, y);
|
||||||
renderer.clearScreen();
|
renderer.clearScreen();
|
||||||
|
|
||||||
|
const bool hasGreyscale = bitmap.hasGreyscale() &&
|
||||||
|
SETTINGS.sleepScreenCoverFilter == CrossPointSettings::SLEEP_SCREEN_COVER_FILTER::NO_FILTER;
|
||||||
|
|
||||||
renderer.drawBitmap(bitmap, x, y, pageWidth, pageHeight, cropX, cropY);
|
renderer.drawBitmap(bitmap, x, y, pageWidth, pageHeight, cropX, cropY);
|
||||||
|
|
||||||
|
if (SETTINGS.sleepScreenCoverFilter == CrossPointSettings::SLEEP_SCREEN_COVER_FILTER::INVERTED_BLACK_AND_WHITE) {
|
||||||
|
renderer.invertScreen();
|
||||||
|
}
|
||||||
|
|
||||||
renderer.displayBuffer(EInkDisplay::HALF_REFRESH);
|
renderer.displayBuffer(EInkDisplay::HALF_REFRESH);
|
||||||
|
|
||||||
if (bitmap.hasGreyscale()) {
|
if (hasGreyscale) {
|
||||||
bitmap.rewindToData();
|
bitmap.rewindToData();
|
||||||
renderer.clearScreen(0x00);
|
renderer.clearScreen(0x00);
|
||||||
renderer.setRenderMode(GfxRenderer::GRAYSCALE_LSB);
|
renderer.setRenderMode(GfxRenderer::GRAYSCALE_LSB);
|
||||||
|
|||||||
@ -11,11 +11,13 @@
|
|||||||
const char* SettingsActivity::categoryNames[categoryCount] = {"Display", "Reader", "Controls", "System"};
|
const char* SettingsActivity::categoryNames[categoryCount] = {"Display", "Reader", "Controls", "System"};
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
constexpr int displaySettingsCount = 5;
|
constexpr int displaySettingsCount = 6;
|
||||||
const SettingInfo displaySettings[displaySettingsCount] = {
|
const SettingInfo displaySettings[displaySettingsCount] = {
|
||||||
// Should match with SLEEP_SCREEN_MODE
|
// Should match with SLEEP_SCREEN_MODE
|
||||||
SettingInfo::Enum("Sleep Screen", &CrossPointSettings::sleepScreen, {"Dark", "Light", "Custom", "Cover", "None"}),
|
SettingInfo::Enum("Sleep Screen", &CrossPointSettings::sleepScreen, {"Dark", "Light", "Custom", "Cover", "None"}),
|
||||||
SettingInfo::Enum("Sleep Screen Cover Mode", &CrossPointSettings::sleepScreenCoverMode, {"Fit", "Crop"}),
|
SettingInfo::Enum("Sleep Screen Cover Mode", &CrossPointSettings::sleepScreenCoverMode, {"Fit", "Crop"}),
|
||||||
|
SettingInfo::Enum("Sleep Screen Cover Filter", &CrossPointSettings::sleepScreenCoverFilter,
|
||||||
|
{"None", "Contrast", "Inverted"}),
|
||||||
SettingInfo::Enum("Status Bar", &CrossPointSettings::statusBar,
|
SettingInfo::Enum("Status Bar", &CrossPointSettings::statusBar,
|
||||||
{"None", "No Progress", "Full w/ Percentage", "Full w/ Progress Bar", "Progress Bar"}),
|
{"None", "No Progress", "Full w/ Percentage", "Full w/ Progress Bar", "Progress Bar"}),
|
||||||
SettingInfo::Enum("Hide Battery %", &CrossPointSettings::hideBatteryPercentage, {"Never", "In Reader", "Always"}),
|
SettingInfo::Enum("Hide Battery %", &CrossPointSettings::hideBatteryPercentage, {"Never", "In Reader", "Always"}),
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user