deploy-ng: use median cut algorithm when palettizing icon

This prevents infrequently occurring colors from being washed out.

See #718
This commit is contained in:
rdb 2019-08-28 22:51:28 +02:00
parent 28d9a33db4
commit d843c5c198

View File

@ -384,35 +384,14 @@ class Icon:
elif bpp == 8: elif bpp == 8:
# We'll have to generate a palette of 256 colors. # We'll have to generate a palette of 256 colors.
hist = PNMImage.Histogram() hist = PNMImage.Histogram()
if image.hasAlpha(): image2 = PNMImage(image)
# Make a copy without alpha channel. if image2.hasAlpha():
image2 = PNMImage(image)
image2.premultiplyAlpha() image2.premultiplyAlpha()
image2.removeAlpha() image2.removeAlpha()
else: image2.quantize(256)
image2 = image
image2.make_histogram(hist) image2.make_histogram(hist)
colors = list(hist.get_pixels()) colors = list(hist.get_pixels())
if len(colors) > 256: assert len(colors) <= 256
# Palette too large; remove infrequent colors.
colors.sort(key=hist.get_count, reverse=True)
# Find the closest color on the palette matching each color
# that didn't fit. This is certainly not the best palette
# generation code, but it'll do for now.
closest_indices = []
for color in colors[256:]:
closest_index = 0
closest_diff = 1025
for i, closest_color in enumerate(colors[:256]):
diff = abs(color.get_red() - closest_color.get_red()) \
+ abs(color.get_green() - closest_color.get_green()) \
+ abs(color.get_blue() - closest_color.get_blue())
if diff < closest_diff:
closest_index = i
closest_diff = diff
assert closest_diff < 100
closest_indices.append(closest_index)
# Write the palette. # Write the palette.
i = 0 i = 0