I am working on a project where I am trying to display an image as beautifully as possible on an E Ink display. I achieved the best results using the normal Floyd Steinberg algorithm employed in GIMP (indexed mode).
However, all attempts to create an algorithm that produces comparable images have failed.
I am now trying to identify and integrate this specific algorithm into my code, but so far, I have not had much luck. I found one in dither.c
, but when I tried to apply it, the results were unsuccessful.
My e-ink display supports these 8 colors:
[0, 0, 0], # Black
[255, 255, 255], # White
[67, 138, 28], # Dark Green
[100, 64, 255], # Blue Violet
[191, 0, 0], # Dark Red
[255, 243, 56], # Light Yellow
[232, 126, 0], # Orange
[194, 164, 244] # Light Violet
When comparing the two dithered images, you can see that the one from GIMP contains significantly less green. The one from GIMP uses much more red, orange, and black for the skin:
[GIMP_algorithm]
[own_algorithm]
my algorithm:
def get_nearest_color(r, g, b, palette):
min_diff = float('inf')
nearest_color = palette[0]
for color in palette:
diff = (r - color[0])**2 + (g - color[1])**2 + (b - color[2])**2
# Prioritize orange over green in case of close matches
if (color == [232, 126, 0]) and (color[1] > r): # Give Orange a slight bias
diff -= 1000 # Adjust this value as needed
if diff < min_diff:
min_diff = diff
nearest_color = color
return nearest_color
def apply_dithering(image, palette, dither_method="floyd_steinberg", intensity=0.1):
pixels = np.array(image, dtype=np.float32)
height, width, _ = pixels.shape
for y in range(height):
for x in range(width):
r, g, b = pixels[y, x][:3]
nearest_color = get_nearest_color(r, g, b, palette)
r_diff = r - nearest_color[0]
g_diff = g - nearest_color[1]
b_diff = b - nearest_color[2]
pixels[y, x][:3] = nearest_color
if dither_method == "floyd_steinberg":
if x + 1 < width:
pixels[y, x + 1][:3] += intensity * np.array([r_diff * 7 / 16, g_diff * 7 / 16, b_diff * 7 / 16])
if y + 1 < height:
if x > 0:
pixels[y + 1, x - 1][:3] += intensity * np.array([r_diff * 3 / 16, g_diff * 3 / 16, b_diff * 3 / 16])
pixels[y + 1, x][:3] += intensity * np.array([r_diff * 5 / 16, g_diff * 5 / 16, b_diff * 5 / 16])
if x + 1 < width:
pixels[y + 1, x + 1][:3] += intensity * np.array([r_diff * 1 / 16, g_diff * 1 / 16, b_diff * 1 / 16])
dithered_image = np.clip(pixels, 0, 255).astype(np.uint8)
return Image.fromarray(dithered_image)
I am grateful for any help!