Skip to content

Commit 777c9e9

Browse files
authored
Merge pull request #230 from TheHans255/thehans255/increase-dithering-resolution
Increase resolution of the dither buffer
2 parents cbb736f + 4aa38f2 commit 777c9e9

File tree

6 files changed

+50
-45
lines changed

6 files changed

+50
-45
lines changed

src/include/Image.h

Lines changed: 4 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,7 @@ class Image : virtual public NetworkClient, virtual public Adafruit_GFX
110110

111111
void getPointsForPosition(const Position &position, const uint16_t imageWidth, const uint16_t imageHeight,
112112
const uint16_t screenWidth, const uint16_t screenHeight, uint16_t *posX, uint16_t *posY);
113-
uint8_t findClosestPalette(uint32_t c);
113+
uint8_t findClosestPalette(int16_t r, int16_t g, int16_t b);
114114

115115
private:
116116
virtual void startWrite(void) = 0;
@@ -130,11 +130,7 @@ class Image : virtual public NetworkClient, virtual public Adafruit_GFX
130130
#endif
131131

132132
#if defined(ARDUINO_INKPLATECOLOR) || defined(ARDUINO_INKPLATE4) || defined(ARDUINO_INKPLATE7)
133-
int8_t ditherBuffer[3][16][E_INK_WIDTH + 20];
134-
135-
int8_t (*ditherBuffer_r)[E_INK_WIDTH + 20] = ditherBuffer[0];
136-
int8_t (*ditherBuffer_g)[E_INK_WIDTH + 20] = ditherBuffer[1];
137-
int8_t (*ditherBuffer_b)[E_INK_WIDTH + 20] = ditherBuffer[2];
133+
int16_t ditherBuffer[3][8][E_INK_WIDTH + 20];
138134

139135
const int kernelWidth = _kernelWidth;
140136
const int kernelHeight = _kernelHeight;
@@ -144,11 +140,7 @@ class Image : virtual public NetworkClient, virtual public Adafruit_GFX
144140

145141
const unsigned char (*kernel)[_kernelWidth] = _kernel;
146142
#elif ARDUINO_INKPLATE2
147-
int8_t ditherBuffer[3][16][E_INK_HEIGHT + 20];
148-
149-
int8_t (*ditherBuffer_r)[E_INK_HEIGHT + 20] = ditherBuffer[0];
150-
int8_t (*ditherBuffer_g)[E_INK_HEIGHT + 20] = ditherBuffer[1];
151-
int8_t (*ditherBuffer_b)[E_INK_HEIGHT + 20] = ditherBuffer[2];
143+
int16_t ditherBuffer[3][8][E_INK_WIDTH + 20];
152144

153145
const int kernelWidth = _kernelWidth;
154146
const int kernelHeight = _kernelHeight;
@@ -202,4 +194,4 @@ class Image : virtual public NetworkClient, virtual public Adafruit_GFX
202194
// -------------------------------------------
203195
};
204196

205-
#endif
197+
#endif

src/include/ImageBMP.cpp

Lines changed: 4 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,7 @@ void Image::readBmpHeader(uint8_t *buf, bitmapHeader *_h)
112112

113113
#if defined(ARDUINO_INKPLATECOLOR)
114114
c = c >> 8;
115-
palette[i >> 1] |= findClosestPalette(c) << (i & 1 ? 0 : 4);
115+
palette[i >> 1] |= findClosestPalette(RED8(c), GREEN8(c), BLUE8(c)) << (i & 1 ? 0 : 4);
116116
ditherPalette[i] = c;
117117
#else
118118
uint8_t r = (c & 0xFF000000) >> 24;
@@ -411,13 +411,6 @@ void Image::displayBmpLine(int16_t x, int16_t y, bitmapHeader *bmpHeader, bool d
411411
val = RGB3BIT(r, g, b);
412412
#endif
413413
}
414-
415-
#if defined(ARDUINO_INKPLATECOLOR) || defined(ARDUINO_INKPLATE2) || defined(ARDUINO_INKPLATE4) || \
416-
defined(ARDUINO_INKPLATE7)
417-
val = findClosestPalette((r << 16) | (g << 8) | (b));
418-
#else
419-
val = RGB3BIT(r, g, b);
420-
#endif
421414
writePixel(x + j, (h - y - 1), val);
422415
break;
423416
}
@@ -439,7 +432,7 @@ void Image::displayBmpLine(int16_t x, int16_t y, bitmapHeader *bmpHeader, bool d
439432
{
440433
#if defined(ARDUINO_INKPLATECOLOR) || defined(ARDUINO_INKPLATE2) || defined(ARDUINO_INKPLATE4) || \
441434
defined(ARDUINO_INKPLATE7)
442-
val = findClosestPalette((r << 16) | (g << 8) | (b));
435+
val = findClosestPalette(r, g, b);
443436
#else
444437
val = RGB3BIT(r, g, b);
445438
#endif
@@ -474,7 +467,7 @@ void Image::displayBmpLine(int16_t x, int16_t y, bitmapHeader *bmpHeader, bool d
474467
{
475468
#if defined(ARDUINO_INKPLATECOLOR) || defined(ARDUINO_INKPLATE2) || defined(ARDUINO_INKPLATE4) || \
476469
defined(ARDUINO_INKPLATE7)
477-
val = findClosestPalette((r << 16) | (g << 8) | (b));
470+
val = findClosestPalette(r, g, b);
478471
#else
479472
val = RGB3BIT(r, g, b);
480473
#endif
@@ -578,4 +571,4 @@ bool Image::drawBmpFromSdAtPosition(const char *fileName, const Position &positi
578571
}
579572

580573
return 1;
581-
}
574+
}

src/include/ImageDitherColor.cpp

Lines changed: 34 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -55,16 +55,34 @@ static unsigned int width = E_INK_WIDTH, height = E_INK_HEIGHT;
5555
*
5656
* @return closest color in pallete array
5757
*/
58-
uint8_t Image::findClosestPalette(uint32_t c)
58+
uint8_t Image::findClosestPalette(int16_t r, int16_t g, int16_t b)
5959
{
60-
int mi = 0;
61-
for (int i = 1; i < sizeof pallete / sizeof pallete[0]; ++i)
60+
int64_t minDistance = 0x7fffffffffffffff;
61+
uint8_t contenderCount = 0;
62+
uint8_t contenderList[sizeof pallete / sizeof pallete[0]];
63+
64+
for (int i = 0; i < sizeof pallete / sizeof pallete[0]; ++i)
6265
{
63-
if (COLORDISTSQR(c, pallete[i]) < COLORDISTSQR(c, pallete[mi]))
64-
mi = i;
66+
int16_t pr = RED8(pallete[i]);
67+
int16_t pg = GREEN8(pallete[i]);
68+
int16_t pb = BLUE8(pallete[i]);
69+
int32_t currentDistance = SQR(r - pr) + SQR(g - pg) + SQR(b - pb);
70+
if (currentDistance < minDistance) {
71+
minDistance = currentDistance;
72+
contenderList[0] = i;
73+
contenderCount = 1;
74+
} else if (currentDistance == minDistance) {
75+
contenderList[contenderCount] = i;
76+
contenderCount++;
77+
}
6578
}
6679

67-
return mi;
80+
// If your project has a good way to seed rand(),
81+
// you can use rand() here to improve dithering quality
82+
// when using shades that are exactly between palette colors.
83+
//return contenderList[contenderCount <= 1 ? 0 : rand() % contenderCount];
84+
85+
return contenderList[0];
6886
}
6987

7088
/**
@@ -88,19 +106,19 @@ uint8_t Image::ditherGetPixelBmp(uint32_t px, int i, int j, int w, bool paletted
88106
if (paletted)
89107
px = ditherPalette[px];
90108

91-
int16_t r = RED8(px) + ditherBuffer[0][j % 15][i];
92-
int16_t g = GREEN8(px) + ditherBuffer[1][j % 15][i];
93-
int16_t b = BLUE8(px) + ditherBuffer[2][j % 15][i];
109+
int16_t r = RED8(px) + ditherBuffer[0][j % 8][i];
110+
int16_t g = GREEN8(px) + ditherBuffer[1][j % 8][i];
111+
int16_t b = BLUE8(px) + ditherBuffer[2][j % 8][i];
94112

95-
ditherBuffer[0][j % 15][i] = 0;
96-
ditherBuffer[1][j % 15][i] = 0;
97-
ditherBuffer[2][j % 15][i] = 0;
113+
ditherBuffer[0][j % 8][i] = 0;
114+
ditherBuffer[1][j % 8][i] = 0;
115+
ditherBuffer[2][j % 8][i] = 0;
98116

99117
r = max((int16_t)0, min((int16_t)255, r));
100118
g = max((int16_t)0, min((int16_t)255, g));
101119
b = max((int16_t)0, min((int16_t)255, b));
102120

103-
int closest = findClosestPalette(((uint32_t)r << 16) | ((uint32_t)g << 8) | ((uint32_t)b));
121+
int closest = findClosestPalette(r, g, b);
104122

105123
int32_t rErr = r - (int32_t)((pallete[closest] >> 16) & 0xFF);
106124
int32_t gErr = g - (int32_t)((pallete[closest] >> 8) & 0xFF);
@@ -112,9 +130,9 @@ uint8_t Image::ditherGetPixelBmp(uint32_t px, int i, int j, int w, bool paletted
112130
{
113131
if (!(0 <= i + l && i + l < w))
114132
continue;
115-
ditherBuffer[0][(j + k) % 15][i + l] += (kernel[k][l + kernelX] * rErr) / coef;
116-
ditherBuffer[1][(j + k) % 15][i + l] += (kernel[k][l + kernelX] * gErr) / coef;
117-
ditherBuffer[2][(j + k) % 15][i + l] += (kernel[k][l + kernelX] * bErr) / coef;
133+
ditherBuffer[0][(j + k) % 8][i + l] += (kernel[k][l + kernelX] * rErr) / coef;
134+
ditherBuffer[1][(j + k) % 8][i + l] += (kernel[k][l + kernelX] * gErr) / coef;
135+
ditherBuffer[2][(j + k) % 8][i + l] += (kernel[k][l + kernelX] * bErr) / coef;
118136
}
119137
}
120138

src/include/ImageDitherColorKernels.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@
2525
// Floyd Steinberg
2626
const int _coef = 16;
2727
const int _kernelX = 1;
28-
const unsigned char _kernel[3][4] = {
28+
const unsigned char _kernel[2][3] = {
2929
{0, 0, 7},
3030
{3, 5, 1},
3131
};
@@ -52,6 +52,7 @@ const unsigned char _kernel[3][4] = {
5252
};
5353
*/
5454

55+
5556
/*
5657
// Burkes
5758
const int _coef = 32;
@@ -87,4 +88,5 @@ const unsigned char _kernel[3][3] = {
8788
const int _kernelWidth = (sizeof _kernel[0] / sizeof _kernel[0][0]);
8889
const int _kernelHeight = (sizeof _kernel / sizeof _kernel[0]);
8990

90-
#endif
91+
#endif
92+

src/include/ImageJPEG.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -390,7 +390,7 @@ bool Image::drawJpegChunk(int16_t x, int16_t y, uint16_t w, uint16_t h, uint16_t
390390
}
391391
else
392392
{
393-
val = _imagePtrJpeg->findClosestPalette(((uint32_t)r << 16) | ((uint32_t)g << 8) | ((uint32_t)b));
393+
val = _imagePtrJpeg->findClosestPalette(r, g, b);
394394
}
395395

396396
_imagePtrJpeg->writePixel(x + i, y + j, val);
@@ -421,4 +421,4 @@ bool Image::drawJpegChunk(int16_t x, int16_t y, uint16_t w, uint16_t h, uint16_t
421421
#endif
422422

423423
return 1;
424-
}
424+
}

src/include/ImagePNG.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ void pngle_on_draw(pngle_t *pngle, uint32_t x, uint32_t y, uint32_t w, uint32_t
7777
b = 255 - b;
7878
}
7979

80-
uint8_t px = _imagePtrPng->findClosestPalette((r << 16) | (g << 8) | (b));
80+
uint8_t px = _imagePtrPng->findClosestPalette(r, g, b);
8181
#else
8282
uint8_t px = RGB3BIT(r, g, b);
8383
#endif
@@ -403,4 +403,4 @@ bool Image::drawPngFromSdAtPosition(const char *fileName, const Position &positi
403403
_pngPosition = _npos;
404404

405405
return ret;
406-
}
406+
}

0 commit comments

Comments
 (0)