Improve EPUB cover image quality with pre-scaling and Atkinson dithering (#116)
## Summary * **What is the goal of this PR?** Replace simple threshold-based grayscale quantization with ordered dithering using a 4x4 Bayer matrix. This eliminates color banding artifacts and produces smoother gradients on e-ink display. * **What changes are included?** - Add 4x4 Bayer dithering matrix for 16-level threshold patterns - Modify `grayscaleTo2Bit()` function to accept pixel coordinates and apply position-based dithering - Replace simple `grayscale >> 6` threshold with ordered dithering algorithm that produces smoother gradients ## Additional Context * Bayer matrix approach: The 4x4 Bayer matrix creates a repeating pattern that distributes quantization error spatially, effectively simulating 16 levels of gray using only 4 actual color levels (black, dark gray, light gray, white). * Cache invalidation: Existing cached `cover.bmp` files will need to be deleted to see the improved rendering, as the converter only runs when the cache is missing.
This commit is contained in:
@@ -132,7 +132,9 @@ void GfxRenderer::drawBitmap(const Bitmap& bitmap, const int x, const int y, con
|
||||
isScaled = true;
|
||||
}
|
||||
|
||||
const uint8_t outputRowSize = (bitmap.getWidth() + 3) / 4;
|
||||
// Calculate output row size (2 bits per pixel, packed into bytes)
|
||||
// IMPORTANT: Use int, not uint8_t, to avoid overflow for images > 1020 pixels wide
|
||||
const int outputRowSize = (bitmap.getWidth() + 3) / 4;
|
||||
auto* outputRow = static_cast<uint8_t*>(malloc(outputRowSize));
|
||||
auto* rowBytes = static_cast<uint8_t*>(malloc(bitmap.getRowBytes()));
|
||||
|
||||
@@ -154,7 +156,7 @@ void GfxRenderer::drawBitmap(const Bitmap& bitmap, const int x, const int y, con
|
||||
break;
|
||||
}
|
||||
|
||||
if (bitmap.readRow(outputRow, rowBytes) != BmpReaderError::Ok) {
|
||||
if (bitmap.readRow(outputRow, rowBytes, bmpY) != BmpReaderError::Ok) {
|
||||
Serial.printf("[%lu] [GFX] Failed to read row %d from bitmap\n", millis(), bmpY);
|
||||
free(outputRow);
|
||||
free(rowBytes);
|
||||
|
||||
Reference in New Issue
Block a user