From 760e4ebc9d89edb274cf6578f152a04ae4fb0566 Mon Sep 17 00:00:00 2001 From: Marcos Del Sol Vives Date: Sun, 7 Jan 2024 20:32:31 +0100 Subject: [PATCH] Increase precision in color matching --- client/src/imgutils.c | 33 ++++++++++++++++++--------------- tools/pm3_tests.sh | 2 +- 2 files changed, 19 insertions(+), 16 deletions(-) diff --git a/client/src/imgutils.c b/client/src/imgutils.c index 1ebcddbb6..a58a5b29a 100644 --- a/client/src/imgutils.c +++ b/client/src/imgutils.c @@ -64,6 +64,9 @@ gdImagePtr img_palettize(gdImagePtr rgb, int * palette, int palette_size) { * * Note that we are storing two extra values so we don't have to do boundary checking at * the left and right edges of the image. + * + * To reduce shifts and increase accuracy, each entry is stored with 16x times the error, + * and gets divided by that amount when it is read. */ struct ycbcr_t * forward = calloc(gdImageSX(rgb) + 2, sizeof(struct ycbcr_t)); if (!forward) { @@ -89,9 +92,9 @@ gdImagePtr img_palettize(gdImagePtr rgb, int * palette, int palette_size) { rgb_to_ycbcr(gdImageGetTrueColorPixel(rgb, x, y), &pix); // Add error for current pixel - pix.y += row_err.y; - pix.cb += row_err.cb; - pix.cr += row_err.cr; + pix.y += row_err.y / 16; + pix.cb += row_err.cb / 16; + pix.cr += row_err.cr / 16; // Cap in case it went to imaginary color territory cap_comp(&pix.y); @@ -129,24 +132,24 @@ gdImagePtr img_palettize(gdImagePtr rgb, int * palette, int palette_size) { gdImageSetPixel(res, x, y, best_idx); // Propagate error within the current row, to the pixel to the right - row_err.y = best_err.y * 7 / 16 + forward[x + 2].y; - row_err.cb = best_err.cb * 7 / 16 + forward[x + 2].cb; - row_err.cr = best_err.cr * 7 / 16 + forward[x + 2].cr; + row_err.y = best_err.y * 7 + forward[x + 2].y; + row_err.cb = best_err.cb * 7 + forward[x + 2].cb; + row_err.cr = best_err.cr * 7 + forward[x + 2].cr; // Add error to bottom left - forward[x + 0].y += best_err.y * 3 / 16; - forward[x + 0].cb += best_err.cb * 3 / 16; - forward[x + 0].cr += best_err.cr * 3 / 16; + forward[x + 0].y += best_err.y * 3; + forward[x + 0].cb += best_err.cb * 3; + forward[x + 0].cr += best_err.cr * 3; // Add error to bottom center - forward[x + 1].y += best_err.y * 5 / 16; - forward[x + 1].cb += best_err.cb * 5 / 16; - forward[x + 1].cr += best_err.cr * 5 / 16; + forward[x + 1].y += best_err.y * 5; + forward[x + 1].cb += best_err.cb * 5; + forward[x + 1].cr += best_err.cr * 5; // Set error to bottom right - forward[x + 2].y = best_err.y * 1 / 16; - forward[x + 2].cb = best_err.cb * 1 / 16; - forward[x + 2].cr = best_err.cr * 1 / 16; + forward[x + 2].y = best_err.y * 1; + forward[x + 2].cb = best_err.cb * 1; + forward[x + 2].cr = best_err.cr * 1; } } diff --git a/tools/pm3_tests.sh b/tools/pm3_tests.sh index 2e32b39bb..e1d574738 100755 --- a/tools/pm3_tests.sh +++ b/tools/pm3_tests.sh @@ -535,7 +535,7 @@ while true; do if ! CheckExecute "emv test" "$CLIENTBIN -c 'emv test'" "Test\(s\) \[ ok"; then break; fi if ! CheckExecute "hf cipurse test" "$CLIENTBIN -c 'hf cipurse test'" "Tests \[ ok"; then break; fi if ! CheckExecute "hf mfdes test" "$CLIENTBIN -c 'hf mfdes test'" "Tests \[ ok"; then break; fi - if ! CheckExecute "hf waveshare load" "$CLIENTBIN -c 'hf waveshare load -m 6 -f tools/lena.bmp -s dither.bmp' && echo '9cee7dcc285f59f88c7cbc9de1dc02b4 dither.bmp' | md5sum -c" "dither.bmp: OK"; then break; fi + if ! CheckExecute "hf waveshare load" "$CLIENTBIN -c 'hf waveshare load -m 6 -f tools/lena.bmp -s dither.bmp' && echo '34ff55fe7257876acf30dae00eb0e439 dither.bmp' | md5sum -c" "dither.bmp: OK"; then break; fi fi echo -e "\n------------------------------------------------------------" echo -e "Tests [ ${C_GREEN}OK${C_NC} ] ${C_OK}\n"