Skip to content

Commit 260ffd2

Browse files
committed
Fix palette matching for quantized images
1 parent ce335b3 commit 260ffd2

1 file changed

Lines changed: 28 additions & 19 deletions

File tree

server/epd.py

Lines changed: 28 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -22,17 +22,17 @@
2222
ENCODING_BWR = np.array([[0, 0], [0, 1], [1, 1]],
2323
dtype=np.uint8)
2424

25-
# 7-color (black, white, green, blue, red, yellow, orange) as an 8-bit RGB
25+
# 7-color (black, white, red, green, blue, yellow, orange) as an 8-bit RGB
2626
# array.
27-
PALETTE_7COLOR = np.array([[16, 16, 16], [239, 239, 239], [27, 120, 27],
28-
[54, 43, 162], [180, 21, 21], [224, 212, 13],
27+
PALETTE_7COLOR = np.array([[16, 16, 16], [239, 239, 239], [180, 21, 21],
28+
[27, 120, 27], [54, 43, 162], [224, 212, 13],
2929
[193, 103, 13]],
3030
dtype=np.uint8)
3131

32-
# 7-color (black, white, green, blue, red, yellow, orange) as a 4-bit index
32+
# 7-color (black, white, red, green, blue, yellow, orange) as a 4-bit index
3333
# array.
34-
ENCODING_7COLOR = np.array([[0, 0, 0, 0], [0, 0, 0, 1], [0, 0, 1, 0],
35-
[0, 0, 1, 1], [0, 1, 0, 0], [0, 1, 0, 1],
34+
ENCODING_7COLOR = np.array([[0, 0, 0, 0], [0, 0, 0, 1], [0, 1, 0, 0],
35+
[0, 0, 1, 0], [0, 0, 1, 1], [0, 1, 0, 1],
3636
[0, 1, 1, 0]],
3737
dtype=np.uint8)
3838

@@ -62,28 +62,37 @@ def _dither(image, palette):
6262
"""Dithers the image using the Floyd-Steinberg algorithm."""
6363

6464
# Call the C extension to iterate over all image pixels efficiently.
65-
pixels = np.array(image.convert('RGB'))
66-
dither(pixels, palette)
65+
with image.convert('RGB') as rgb_image:
66+
pixels = np.array(rgb_image)
67+
dither(pixels, palette)
6768

68-
return Image.fromarray(pixels)
69+
return Image.fromarray(pixels)
6970

7071

7172
def _color_indices(image, variant):
7273
"""Maps each image pixel to the index of the closest palette color."""
7374

74-
# Apply dithering unless the image is already quantized.
75-
palette = epd_palette(variant)
76-
if image.mode not in ('1', 'L', 'P'):
75+
# Figure out if the image is already quantized.
76+
is_quantized = image.mode in ('1', 'L', 'P')
77+
78+
# Apply dithering, if needed.
79+
palette = _epd_palette(variant)
80+
if not is_quantized:
7781
image = _dither(image, palette)
7882

7983
# Map each pixel to the closest palette color.
80-
pixels = np.array(image.convert('RGB')).reshape(-1, 3)
81-
indices = vector_quantize(pixels, palette)
84+
with image.convert('RGB') as rgb_image:
85+
pixels = np.array(rgb_image).reshape(-1, 3)
8286

83-
return indices
87+
# Match against the BWR palette for quantized images. This requires
88+
# other palettes to start with the BWR color sequence in order.
89+
match_palette = PALETTE_BWR if is_quantized else palette
90+
91+
# Quantize the image.
92+
return vector_quantize(pixels, match_palette)
8493

8594

86-
def epd_palette(variant):
95+
def _epd_palette(variant):
8796
"""Returns the RGB palette used by the display."""
8897

8998
if variant == 'bwr':
@@ -94,7 +103,7 @@ def epd_palette(variant):
94103
raise ValueError('Unsupported display variant: %s' % variant)
95104

96105

97-
def epd_encoding(variant):
106+
def _epd_encoding(variant):
98107
"""Returns the color encoding used to send data to the display."""
99108

100109
if variant == 'bwr':
@@ -109,7 +118,7 @@ def to_epd_image(image, variant):
109118
"""Converts the image's colors to the closest palette color."""
110119

111120
indices = _color_indices(image, variant)
112-
palette = epd_palette(variant)
121+
palette = _epd_palette(variant)
113122
epd_image_data = palette[indices.reshape((image.height, image.width))]
114123

115124
return Image.fromarray(epd_image_data)
@@ -119,7 +128,7 @@ def to_epd_bytes(image, variant):
119128
"""Converts the image to the closest 2-bit palette color bytes."""
120129

121130
indices = _color_indices(image, variant)
122-
encoding = epd_encoding(variant)
131+
encoding = _epd_encoding(variant)
123132
epd_image_data = encoding[indices.reshape((image.height * image.width))]
124133

125134
return np.packbits(epd_image_data)

0 commit comments

Comments
 (0)