|
from PIL import Image |
|
|
|
def hex_to_rgb(value): |
|
value = value.lstrip('#') |
|
length = len(value) |
|
return tuple(int(value[i:i + length // 3], 16) for i in range(0, length, length // 3)) |
|
|
|
def luminance(color): |
|
|
|
r, g, b = color |
|
return 0.2126 * r + 0.7152 * g + 0.0722 * b |
|
|
|
|
|
|
|
|
|
def quadratic_interpolate(factor): |
|
|
|
return factor ** 2 |
|
|
|
def interpolate_color(color1, color2, factor): |
|
adjusted_factor = quadratic_interpolate(factor) |
|
return tuple(int(c1 * (1 - adjusted_factor) + c2 * adjusted_factor) for c1, c2 in zip(color1, color2)) |
|
|
|
|
|
def remap_image_colors(image_path, hex_palette): |
|
|
|
img = Image.fromarray(image_path) |
|
|
|
rgb_palette = [hex_to_rgb(hex_code) for hex_code in hex_palette] |
|
|
|
sorted_palette = sorted(rgb_palette, key=luminance) |
|
|
|
img_rgb = img.convert("RGB") |
|
pixels = img_rgb.load() |
|
|
|
for y in range(img.height): |
|
for x in range(img.width): |
|
original_color = pixels[x, y] |
|
lum = luminance(original_color) |
|
|
|
|
|
prev_color = sorted_palette[0] |
|
next_color = sorted_palette[-1] |
|
for i in range(1, len(sorted_palette)): |
|
if luminance(sorted_palette[i]) > lum: |
|
next_color = sorted_palette[i] |
|
prev_color = sorted_palette[i-1] |
|
break |
|
|
|
|
|
lum_range = luminance(next_color) - luminance(prev_color) |
|
if lum_range == 0: |
|
mapped_color = prev_color |
|
else: |
|
factor = (lum - luminance(prev_color)) / lum_range |
|
mapped_color = interpolate_color(prev_color, next_color, factor) |
|
|
|
pixels[x, y] = mapped_color |
|
|
|
img_rgb.save("result.jpg") |
|
|
|
|
|
|
|
|