mirror of
https://github.com/daveallie/crosspoint-reader.git
synced 2026-02-05 15:17:37 +03:00
fix(xtc): address PR review feedback for grayscale rendering
- Use FsHelpers::openFileForRead for consistency (XtcParser.cpp) - Simplify file extension checking logic (FileSelectionActivity.cpp) - Fix grayscale rendering bugs (XtcReaderActivity.cpp): - Use drawPixel(x, y, false) for LSB/MSB passes (LUT: 0=apply effect) - Add cleanupGrayscaleWithFrameBuffer() after re-rendering BW - Use conditional HALF_REFRESH based on pagesUntilFullRefresh - Decrement refresh counter instead of resetting - Add cleanupGrayscaleWithFrameBuffer() helper (GfxRenderer)
This commit is contained in:
parent
30c50ef45b
commit
76a1c30a87
@ -369,6 +369,17 @@ void GfxRenderer::restoreBwBuffer() {
|
|||||||
Serial.printf("[%lu] [GFX] Restored and freed BW buffer chunks\n", millis());
|
Serial.printf("[%lu] [GFX] Restored and freed BW buffer chunks\n", millis());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Cleanup grayscale buffers using the current frame buffer.
|
||||||
|
* Use this when BW buffer was re-rendered instead of stored/restored.
|
||||||
|
*/
|
||||||
|
void GfxRenderer::cleanupGrayscaleWithFrameBuffer() const {
|
||||||
|
uint8_t* frameBuffer = einkDisplay.getFrameBuffer();
|
||||||
|
if (frameBuffer) {
|
||||||
|
einkDisplay.cleanupGrayscaleBuffers(frameBuffer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void GfxRenderer::renderChar(const EpdFontFamily& fontFamily, const uint32_t cp, int* x, const int* y,
|
void GfxRenderer::renderChar(const EpdFontFamily& fontFamily, const uint32_t cp, int* x, const int* y,
|
||||||
const bool pixelState, const EpdFontStyle style) const {
|
const bool pixelState, const EpdFontStyle style) const {
|
||||||
const EpdGlyph* glyph = fontFamily.getGlyph(cp, style);
|
const EpdGlyph* glyph = fontFamily.getGlyph(cp, style);
|
||||||
|
|||||||
@ -67,6 +67,7 @@ class GfxRenderer {
|
|||||||
void displayGrayBuffer() const;
|
void displayGrayBuffer() const;
|
||||||
bool storeBwBuffer(); // Returns true if buffer was stored successfully
|
bool storeBwBuffer(); // Returns true if buffer was stored successfully
|
||||||
void restoreBwBuffer();
|
void restoreBwBuffer();
|
||||||
|
void cleanupGrayscaleWithFrameBuffer() const;
|
||||||
|
|
||||||
// Low level functions
|
// Low level functions
|
||||||
uint8_t* getFrameBuffer() const;
|
uint8_t* getFrameBuffer() const;
|
||||||
|
|||||||
@ -7,6 +7,7 @@
|
|||||||
|
|
||||||
#include "XtcParser.h"
|
#include "XtcParser.h"
|
||||||
|
|
||||||
|
#include <FsHelpers.h>
|
||||||
#include <HardwareSerial.h>
|
#include <HardwareSerial.h>
|
||||||
|
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
@ -31,9 +32,7 @@ XtcError XtcParser::open(const char* filepath) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Open file
|
// Open file
|
||||||
m_file = SD.open(filepath, FILE_READ);
|
if (!FsHelpers::openFileForRead("XTC", filepath, m_file)) {
|
||||||
if (!m_file) {
|
|
||||||
Serial.printf("[%lu] [XTC] Failed to open file: %s\n", millis(), filepath);
|
|
||||||
m_lastError = XtcError::FILE_NOT_FOUND;
|
m_lastError = XtcError::FILE_NOT_FOUND;
|
||||||
return m_lastError;
|
return m_lastError;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -40,18 +40,11 @@ void FileSelectionActivity::loadFiles() {
|
|||||||
|
|
||||||
if (file.isDirectory()) {
|
if (file.isDirectory()) {
|
||||||
files.emplace_back(filename + "/");
|
files.emplace_back(filename + "/");
|
||||||
} else if (filename.length() >= 5 && filename.substr(filename.length() - 5) == ".epub") {
|
} else {
|
||||||
|
std::string ext4 = filename.length() >= 4 ? filename.substr(filename.length() - 4) : "";
|
||||||
|
std::string ext5 = filename.length() >= 5 ? filename.substr(filename.length() - 5) : "";
|
||||||
|
if (ext5 == ".epub" || ext5 == ".xtch" || ext4 == ".xtc") {
|
||||||
files.emplace_back(filename);
|
files.emplace_back(filename);
|
||||||
} else if (filename.length() >= 4) {
|
|
||||||
// Check for XTC format extensions (.xtc, .xtch)
|
|
||||||
std::string ext4 = filename.substr(filename.length() - 4);
|
|
||||||
if (ext4 == ".xtc") {
|
|
||||||
files.emplace_back(filename);
|
|
||||||
} else if (filename.length() >= 5) {
|
|
||||||
std::string ext5 = filename.substr(filename.length() - 5);
|
|
||||||
if (ext5 == ".xtch") {
|
|
||||||
files.emplace_back(filename);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
file.close();
|
file.close();
|
||||||
|
|||||||
@ -236,29 +236,33 @@ void XtcReaderActivity::renderPage() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Display BW first with half refresh (clean base for grayscale overlay)
|
// Display BW with conditional refresh based on pagesUntilFullRefresh
|
||||||
|
if (pagesUntilFullRefresh <= 1) {
|
||||||
renderer.displayBuffer(EInkDisplay::HALF_REFRESH);
|
renderer.displayBuffer(EInkDisplay::HALF_REFRESH);
|
||||||
|
} else {
|
||||||
|
renderer.displayBuffer();
|
||||||
|
}
|
||||||
|
|
||||||
// Pass 2: LSB buffer - mark DARK gray only (XTH value 1)
|
// Pass 2: LSB buffer - mark DARK gray only (XTH value 1)
|
||||||
// README: "mark the **dark** grays pixels with `1`"
|
// In LUT: 0 bit = apply gray effect, 1 bit = untouched
|
||||||
renderer.clearScreen(0x00);
|
renderer.clearScreen(0x00);
|
||||||
for (uint16_t y = 0; y < pageHeight; y++) {
|
for (uint16_t y = 0; y < pageHeight; y++) {
|
||||||
for (uint16_t x = 0; x < pageWidth; x++) {
|
for (uint16_t x = 0; x < pageWidth; x++) {
|
||||||
if (getPixelValue(x, y) == 1) { // Dark grey only
|
if (getPixelValue(x, y) == 1) { // Dark grey only
|
||||||
renderer.drawPixel(x, y, true);
|
renderer.drawPixel(x, y, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
renderer.copyGrayscaleLsbBuffers();
|
renderer.copyGrayscaleLsbBuffers();
|
||||||
|
|
||||||
// Pass 3: MSB buffer - mark LIGHT AND DARK gray (XTH value 1 or 2)
|
// Pass 3: MSB buffer - mark LIGHT AND DARK gray (XTH value 1 or 2)
|
||||||
// README: "mark the **light and dark** grays pixels with `1`"
|
// In LUT: 0 bit = apply gray effect, 1 bit = untouched
|
||||||
renderer.clearScreen(0x00);
|
renderer.clearScreen(0x00);
|
||||||
for (uint16_t y = 0; y < pageHeight; y++) {
|
for (uint16_t y = 0; y < pageHeight; y++) {
|
||||||
for (uint16_t x = 0; x < pageWidth; x++) {
|
for (uint16_t x = 0; x < pageWidth; x++) {
|
||||||
const uint8_t pv = getPixelValue(x, y);
|
const uint8_t pv = getPixelValue(x, y);
|
||||||
if (pv == 1 || pv == 2) { // Dark grey or Light grey
|
if (pv == 1 || pv == 2) { // Dark grey or Light grey
|
||||||
renderer.drawPixel(x, y, true);
|
renderer.drawPixel(x, y, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -277,8 +281,11 @@ void XtcReaderActivity::renderPage() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Reset refresh counter (grayscale display is a full refresh)
|
// Cleanup grayscale buffers with current frame buffer
|
||||||
pagesUntilFullRefresh = pagesPerRefresh;
|
renderer.cleanupGrayscaleWithFrameBuffer();
|
||||||
|
|
||||||
|
// Decrement refresh counter
|
||||||
|
pagesUntilFullRefresh--;
|
||||||
|
|
||||||
free(pageBuffer);
|
free(pageBuffer);
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user