feat: Add EPUB embedded image support (JPEG/PNG)
Cherry-pick merge from pablohc/crosspoint-reader@2d8cbcf, based on upstream PR #556 by martinbrook with pablohc's refresh optimization. - Add JPEG decoder (picojpeg) and PNG decoder (PNGdec) with 4-level grayscale Bayer dithering for e-ink display - Add pixel caching system (.pxc files) for fast image re-rendering - Integrate image extraction from EPUB HTML parser (<img> tag support) - Add ImageBlock/PageImage types with serialization support - Add image-aware refresh optimization (double FAST_REFRESH technique) - Add experimental displayWindow() partial refresh support - Bump section cache version 12->13 to invalidate stale caches - Resolve TAG_PageImage=3 to avoid conflict with mod's TAG_PageTableRow=2 Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -22,6 +22,11 @@
|
||||
#include "util/BookmarkStore.h"
|
||||
#include "util/Dictionary.h"
|
||||
|
||||
// Image refresh optimization strategy:
|
||||
// 0 = Use double FAST_REFRESH technique (default, feels snappier)
|
||||
// 1 = Use displayWindow() for partial refresh (experimental)
|
||||
#define USE_IMAGE_DOUBLE_FAST_REFRESH 0
|
||||
|
||||
namespace {
|
||||
// pagesPerRefresh now comes from SETTINGS.getRefreshFrequency()
|
||||
constexpr unsigned long skipChapterMs = 700;
|
||||
@@ -972,6 +977,14 @@ void EpubReaderActivity::saveProgress(int spineIndex, int currentPage, int pageC
|
||||
void EpubReaderActivity::renderContents(std::unique_ptr<Page> page, const int orientedMarginTop,
|
||||
const int orientedMarginRight, const int orientedMarginBottom,
|
||||
const int orientedMarginLeft) {
|
||||
// Determine if this page needs special image handling
|
||||
bool pageHasImages = page->hasImages();
|
||||
bool useAntiAliasing = SETTINGS.textAntiAliasing;
|
||||
|
||||
// Force half refresh for pages with images when anti-aliasing is on,
|
||||
// as grayscale tones require half refresh to display correctly
|
||||
bool forceFullRefresh = pageHasImages && useAntiAliasing;
|
||||
|
||||
page->render(renderer, SETTINGS.getReaderFontId(), orientedMarginLeft, orientedMarginTop);
|
||||
|
||||
// Draw bookmark ribbon indicator in top-right corner if current page is bookmarked
|
||||
@@ -990,10 +1003,42 @@ void EpubReaderActivity::renderContents(std::unique_ptr<Page> page, const int or
|
||||
}
|
||||
|
||||
renderStatusBar(orientedMarginRight, orientedMarginBottom, orientedMarginLeft);
|
||||
|
||||
// Check if half-refresh is needed (either entering Reader or pages counter reached)
|
||||
if (pagesUntilFullRefresh <= 1) {
|
||||
renderer.displayBuffer(HalDisplay::HALF_REFRESH);
|
||||
pagesUntilFullRefresh = SETTINGS.getRefreshFrequency();
|
||||
} else if (forceFullRefresh) {
|
||||
// OPTIMIZATION: For image pages with anti-aliasing, use fast double-refresh technique
|
||||
// to reduce perceived lag. Only when pagesUntilFullRefresh > 1 (screen already clean).
|
||||
int imgX, imgY, imgW, imgH;
|
||||
if (page->getImageBoundingBox(imgX, imgY, imgW, imgH)) {
|
||||
int screenX = imgX + orientedMarginLeft;
|
||||
int screenY = imgY + orientedMarginTop;
|
||||
LOG_DBG("ERS", "Image page: fast double-refresh (page bbox: %d,%d %dx%d, screen: %d,%d %dx%d)",
|
||||
imgX, imgY, imgW, imgH, screenX, screenY, imgW, imgH);
|
||||
|
||||
#if USE_IMAGE_DOUBLE_FAST_REFRESH == 0
|
||||
// Method A: Fill blank area + two FAST_REFRESH operations
|
||||
renderer.fillRect(screenX, screenY, imgW, imgH, false);
|
||||
renderer.displayBuffer(HalDisplay::FAST_REFRESH);
|
||||
page->render(renderer, SETTINGS.getReaderFontId(), orientedMarginLeft, orientedMarginTop);
|
||||
renderStatusBar(orientedMarginRight, orientedMarginBottom, orientedMarginLeft);
|
||||
renderer.displayBuffer(HalDisplay::FAST_REFRESH);
|
||||
#else
|
||||
// Method B (experimental): Use displayWindow() for partial refresh
|
||||
renderer.displayBuffer(HalDisplay::FAST_REFRESH);
|
||||
page->render(renderer, SETTINGS.getReaderFontId(), orientedMarginLeft, orientedMarginTop);
|
||||
renderStatusBar(orientedMarginRight, orientedMarginBottom, orientedMarginLeft);
|
||||
renderer.displayWindow(screenX, screenY, imgW, imgH, HalDisplay::FAST_REFRESH);
|
||||
#endif
|
||||
} else {
|
||||
LOG_DBG("ERS", "Image page but no bbox, using standard half refresh");
|
||||
renderer.displayBuffer(HalDisplay::HALF_REFRESH);
|
||||
}
|
||||
pagesUntilFullRefresh--;
|
||||
} else {
|
||||
// Normal page without images, or images without anti-aliasing
|
||||
renderer.displayBuffer();
|
||||
pagesUntilFullRefresh--;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user