fix: use double FAST_REFRESH to prevent washout on large grey images (#957)

## Summary

Fixes https://github.com/crosspoint-reader/crosspoint-reader/issues/1011

Use double FAST_REFRESH for image pages to prevent grayscale washout,
HALF_REFRESH sets e-ink particles too firmly for the grayscale LUT to
adjust, causing washed-out images (especially large, light-gray ones).
Replace HALF_REFRESH with @pablohc's double FAST_REFRESH technique:
blank only the image bounding box area, then re-render with images. This
clears ghosting while keeping particles loosely set for grayscale.

## Additional Context

---

### 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  >**_
This commit is contained in:
martin brook
2026-02-20 01:05:15 +00:00
committed by Dave Allie
parent 8db3542e90
commit 2cc497cdca
2 changed files with 51 additions and 4 deletions

View File

@@ -49,6 +49,7 @@ class PageImage final : public PageElement {
bool serialize(FsFile& file) override;
PageElementTag getTag() const override { return TAG_PageImage; }
static std::unique_ptr<PageImage> deserialize(FsFile& file);
const ImageBlock& getImageBlock() const { return *imageBlock; }
};
class Page {
@@ -64,4 +65,32 @@ class Page {
return std::any_of(elements.begin(), elements.end(),
[](const std::shared_ptr<PageElement>& el) { return el->getTag() == TAG_PageImage; });
}
// Get bounding box of all images on the page (union of image rects)
// Returns false if no images. Coordinates are relative to page origin.
bool getImageBoundingBox(int16_t& outX, int16_t& outY, int16_t& outW, int16_t& outH) const {
bool found = false;
int16_t minX = INT16_MAX, minY = INT16_MAX, maxX = INT16_MIN, maxY = INT16_MIN;
for (const auto& el : elements) {
if (el->getTag() == TAG_PageImage) {
const auto& img = static_cast<const PageImage&>(*el);
int16_t x = img.xPos;
int16_t y = img.yPos;
int16_t right = x + img.getImageBlock().getWidth();
int16_t bottom = y + img.getImageBlock().getHeight();
minX = std::min(minX, x);
minY = std::min(minY, y);
maxX = std::max(maxX, right);
maxY = std::max(maxY, bottom);
found = true;
}
}
if (found) {
outX = minX;
outY = minY;
outW = maxX - minX;
outH = maxY - minY;
}
return found;
}
};