Last active
April 5, 2024 19:38
-
-
Save JPLeBreton/6e1081803473b2e7792a00526a7c4d57 to your computer and use it in GitHub Desktop.
colorblox.py - converts given image into emoji color blocks
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import sys, os | |
from PIL import Image | |
MAX_SIZE = 16 # max output dimension in characters | |
RESAMPLE_TYPE = Image.NEAREST # alternately, Image.BICUBIC | |
DITHER_TYPE = Image.NONE # alternately, Image.FLOYDSTEINBERG | |
TRANSP = (0, 0, 0, 0) | |
RED = (221, 46, 68, 255) | |
ORANGE = (244, 144, 12, 255) | |
YELLOW = (253, 203, 88, 255) | |
GREEN = (120, 177, 89, 255) | |
BLUE = (85, 172, 238, 255) | |
PURPLE = (170, 142, 214, 255) | |
BROWN = (193, 105, 79, 255) | |
BLACK = (65, 65, 65, 255) | |
WHITE = (243, 243, 243, 255) | |
COLORS = [TRANSP, RED, ORANGE, YELLOW, GREEN, BLUE, PURPLE, BROWN, BLACK, WHITE] | |
# different "blank" characters work better with different fonts :/ | |
#TRANSP_CHAR = ' ' # regular ol' space | |
#TRANSP_CHAR = ' ' # U+2003 "em space" | |
#TRANSP_CHAR = '' # U+200B "zero width sapce" | |
TRANSP_CHAR = ' ' # U+3000 "ideographic space" - still not the same size as a color block in many fonts :[ | |
CHARS = [TRANSP_CHAR, '🟥', '🟧', '🟨', '🟩', '🟦', '🟪', '🟫', '⬛', '⬜'] | |
if __name__ == '__main__': | |
if len(sys.argv) <= 1: | |
print('Please specify an image.') | |
sys.exit() | |
filename = ' '.join(sys.argv[1:]) | |
if not os.path.exists(filename): | |
print("Couldn't find image file %s" % filename) | |
sys.exit() | |
# build palette | |
pal_img = Image.new('P', (1, 1)) | |
# pal = [*(c[0], c[1], c[2]) for c in COLORS] # "iterable unpacking cannot be used in comprehension" :[ | |
pal = [] | |
for c in COLORS: | |
pal += [c[0], c[1], c[2], c[3]] | |
# PIL will fill out <256 color palettes with bogus values :/ | |
while len(pal) < 256 * 4: | |
for i in range(4): | |
pal.append(0) | |
# palette for PIL must be exactly 256 colors | |
pal = pal[:256*4] | |
pal_img.putpalette(pal, rawmode='RGBA') | |
try: | |
src_img = Image.open(filename) | |
src_img = src_img.convert('RGB') | |
src_w, src_h = src_img.size | |
if src_w >= src_h: | |
aspect = src_h / src_w | |
w = MAX_SIZE | |
h = int(w * aspect) | |
else: | |
aspect = src_w / src_h | |
h = MAX_SIZE | |
w = int(h * aspect) | |
src_img = src_img.resize((w, h), resample=RESAMPLE_TYPE) | |
src_img = src_img.quantize(colors=len(COLORS), palette=pal_img, dither=DITHER_TYPE) | |
except: | |
print('Failed opening image %s' % filename) | |
sys.exit() | |
for y in range(h): | |
line = '' | |
for x in range(w): | |
p = src_img.getpixel((x, y)) | |
line += CHARS[p] | |
print(line) | |
print(filename) | |
print('%s x %s -> %s x %s (%s chars total)' % (src_w, src_h, w, h, w * h)) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment