From 7a591a17a18e0da99bb26b1da880cb48f9931f27 Mon Sep 17 00:00:00 2001 From: Tyler DeVos Date: Sat, 11 Nov 2017 22:00:04 -0600 Subject: [PATCH 1/2] Added brick count statistics --- README.md | 3 ++- legofy/__init__.py | 33 +++++++++++++++++++++------- legofy/cli.py | 6 ++++-- legofy/palettes.py | 54 +++++++++++++++++++++++++++++++++++++++++++++- 4 files changed, 84 insertions(+), 12 deletions(-) diff --git a/README.md b/README.md index 687ab05..c0df144 100644 --- a/README.md +++ b/README.md @@ -43,7 +43,8 @@ Options: --dither / --no-dither Use dither algorithm to spread the color approximation error. --palette [all|effects|mono|solid|transparent] Palette to use based on real Lego colors. - --help Show this message and exit. + --help Show this message and exit.xxsx + --stats Shows the count of brick colors ``` #### Palette diff --git a/legofy/__init__.py b/legofy/__init__.py index f459694..88decfb 100644 --- a/legofy/__init__.py +++ b/legofy/__init__.py @@ -48,12 +48,22 @@ def make_lego_image(thumbnail_image, brick_image): lego_image = Image.new("RGB", (base_width * brick_width, base_height * brick_height), "white") + brick_stats = {} for brick_x in range(base_width): for brick_y in range(base_height): color = rgb_image.getpixel((brick_x, brick_y)) + + '''Increment color count''' + for color_label in palettes.LEGOS_LABEL: + if str(palettes.LEGOS_LABEL[color_label]['rgb']) == str(color): + if color_label in brick_stats: + brick_stats[color_label] += 1 + else: + brick_stats[color_label] = 1 + lego_image.paste(apply_color_overlay(brick_image, color), (brick_x * brick_width, brick_y * brick_height)) - return lego_image + return lego_image, brick_stats def get_new_filename(file_path, ext_override=None): @@ -100,7 +110,7 @@ def apply_thumbnail_effects(image, palette, dither): Image.FLOYDSTEINBERG if dither else Image.NONE, palette_image.im) -def legofy_gif(base_image, brick_image, output_path, size, palette_mode, dither): +def legofy_gif(base_image, brick_image, output_path, size, palette_mode, dither, stats): '''Alternative function that legofies animated gifs, makes use of images2gif - uses numpy!''' im = base_image @@ -124,24 +134,31 @@ def legofy_gif(base_image, brick_image, output_path, size, palette_mode, dither) if palette_mode: palette = get_lego_palette(palette_mode) frame = apply_thumbnail_effects(frame, palette, dither) - new_frame = make_lego_image(frame, brick_image) + new_frame, brick_stats = make_lego_image(frame, brick_image) frames_converted.append(new_frame) + if stats == True: + print(brick_stats) + # Make use of images to gif function images2gif.writeGif(output_path, frames_converted, duration=original_duration/1000.0, dither=0, subRectangles=False) -def legofy_image(base_image, brick_image, output_path, size, palette_mode, dither): +def legofy_image(base_image, brick_image, output_path, size, palette_mode, dither, stats): '''Legofy an image''' new_size = get_new_size(base_image, brick_image, size) base_image.thumbnail(new_size, Image.ANTIALIAS) if palette_mode: palette = get_lego_palette(palette_mode) base_image = apply_thumbnail_effects(base_image, palette, dither) - make_lego_image(base_image, brick_image).save(output_path) + lego_image, brick_stats = make_lego_image(base_image, brick_image) + if stats == True: + print(brick_stats) + lego_image.save(output_path) def main(image_path, output_path=None, size=None, - palette_mode=None, dither=False): + palette_mode=None, dither=False, stats=None): + '''Legofy image or gif with brick_path mask''' image_path = os.path.realpath(image_path) if not os.path.isfile(image_path): @@ -167,12 +184,12 @@ def main(image_path, output_path=None, size=None, if output_path is None: output_path = get_new_filename(image_path) print("Animated gif detected, will now legofy to {0}".format(output_path)) - legofy_gif(base_image, brick_image, output_path, size, palette_mode, dither) + legofy_gif(base_image, brick_image, output_path, size, palette_mode, dither, stats) else: if output_path is None: output_path = get_new_filename(image_path, '.png') print("Static image detected, will now legofy to {0}".format(output_path)) - legofy_image(base_image, brick_image, output_path, size, palette_mode, dither) + legofy_image(base_image, brick_image, output_path, size, palette_mode, dither, stats) base_image.close() brick_image.close() diff --git a/legofy/cli.py b/legofy/cli.py index 7ed88a4..0229652 100644 --- a/legofy/cli.py +++ b/legofy/cli.py @@ -17,7 +17,9 @@ @click.option('--palette', default=None, type=click.Choice(palettes.legos().keys()), help='Palette to use based on real Lego colors.') -def main(image, output, size, palette, dither): +@click.option('--stats/--statistics', default=False, + help='Print statistics of brick count with colors.') +def main(image, output, size, palette, dither, stats): '''Legofy an image!''' legofy.main(image, output_path=output, size=size, - palette_mode=palette, dither=dither) + palette_mode=palette, dither=dither, stats=stats) diff --git a/legofy/palettes.py b/legofy/palettes.py index 52f1bc6..0d28643 100644 --- a/legofy/palettes.py +++ b/legofy/palettes.py @@ -17,6 +17,59 @@ """ from __future__ import division +LEGOS_LABEL = { + 'white': {'rgb': (244, 244, 244) }, + 'brick-yellow': {'rgb': (217, 187, 124) }, + 'nougat': {'rgb': (214, 115, 65) }, + 'bright-red': { 'rgb': (222, 1, 14) }, + 'bright-blue': { 'rgb': (1, 88, 168) }, + 'bright-yellow': { 'rgb': (254, 196, 1) }, + 'black': { 'rgb': (2, 2, 2) }, + 'dark-green': { 'rgb': (1, 124, 41) }, + 'bright-green': { 'rgb': (1, 150, 37) }, + 'dark-orange': { 'rgb': (168, 62, 22) }, + 'transparent': { 'rgb': (238, 238, 238) }, + 'transparent-red': { 'rgb': (224, 42, 41) }, + 'transparent-light-blue': { 'rgb': (182, 224, 234) }, + 'transparent-blue': { 'rgb': (80, 177, 232) }, + 'transparent-yellow': { 'rgb': (249, 239, 105) }, + 'transparent-flourescent-reddish-orange': { 'rgb': (231, 102, 72) }, + 'transparent-green': { 'rgb': (99, 178, 110) }, + 'transparent-flourescent-green': { 'rgb': (241, 237, 91) }, + 'medium-blue': { 'rgb': (72, 140, 198) }, + 'bright-orange': { 'rgb': (231, 100, 25) }, + 'transparent-brown': { 'rgb': (166, 145, 130) }, + 'transparent-med-reddish-violet': { 'rgb': (238, 157, 195) }, + 'transparent-yellowish-green': { 'rgb': (149, 185, 12) }, + 'transparent-reddish-violet': { 'rgb': (156, 1, 198) }, + 'transparent-bluish-violet': { 'rgb': (156, 149, 199) }, + 'silver': { 'rgb': (141, 148, 150) }, + 'sand-blue': { 'rgb': (95, 117, 140) }, + 'sand-yellow': { 'rgb': (141, 117, 83) }, + 'earth-blue': { 'rgb': (1, 38, 66) }, + 'earth-green': { 'rgb': (1, 53, 23) }, + 'transparent-flourescent-blue': { 'rgb': (206, 227, 246) }, + 'metallic-dark-grey': { 'rgb': (73, 63, 59) }, + 'sand-green': { 'rgb': (96, 130, 102) }, + 'dark-red': { 'rgb': (128, 9, 28) }, + 'transparent-bright-orange': { 'rgb': (236, 118, 14) }, + 'flame-yellowish-orange': { 'rgb': (244, 155, 1) }, + 'reddish-brown': { 'rgb': (92, 29, 13) }, + 'medium-stone-grey': { 'rgb': (156, 146, 145) }, + 'dark-stone-grey': { 'rgb': (77, 94, 87) }, + 'light-stone-grey': { 'rgb': (228, 228, 218) }, + 'light-royal-blue': { 'rgb': (135, 192, 234) }, + 'bright-purple': { 'rgb': (222, 56, 139) }, + 'light-purple': { 'rgb': (238, 157, 195) }, + 'cool-yellow': { 'rgb': (255, 255, 153) }, + 'medium-lilac': { 'rgb': (45, 22, 120) }, + 'light-nougat': { 'rgb': (245, 193, 137) }, + 'phosph-green': { 'rgb': (254, 252, 213) }, + 'warm-gold': { 'rgb': (170, 127, 46) }, + 'dark-brown': { 'rgb': (49, 16, 7) }, + 'transparent-bright-green': { 'rgb': (153, 255, 102) }, + 'medium-nougat': { 'rgb': (170, 126, 86) } +} LEGOS = { 'solid': { @@ -99,7 +152,6 @@ def legos(): """Build flattened lego palettes.""" return _flatten_palettes(LEGOS.copy()) - def _flatten_palettes(palettes): """Convert palette mappings into color list.""" flattened = {} From 5db0a9730d4ce875921273783e973279622a5ead Mon Sep 17 00:00:00 2001 From: Tyler DeVos Date: Sun, 12 Nov 2017 09:07:23 -0600 Subject: [PATCH 2/2] Fixed pull request styling comments --- README.md | 4 ++-- legofy/__init__.py | 8 +++++--- legofy/palettes.py | 1 + 3 files changed, 8 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index c0df144..af8acdd 100644 --- a/README.md +++ b/README.md @@ -43,8 +43,8 @@ Options: --dither / --no-dither Use dither algorithm to spread the color approximation error. --palette [all|effects|mono|solid|transparent] Palette to use based on real Lego colors. - --help Show this message and exit.xxsx - --stats Shows the count of brick colors + --stats Shows the count of brick colors. + --help Show this message and exit. ``` #### Palette diff --git a/legofy/__init__.py b/legofy/__init__.py index 88decfb..997b5f6 100644 --- a/legofy/__init__.py +++ b/legofy/__init__.py @@ -134,10 +134,10 @@ def legofy_gif(base_image, brick_image, output_path, size, palette_mode, dither, if palette_mode: palette = get_lego_palette(palette_mode) frame = apply_thumbnail_effects(frame, palette, dither) + new_frame, brick_stats = make_lego_image(frame, brick_image) frames_converted.append(new_frame) - - if stats == True: + if stats: print(brick_stats) # Make use of images to gif function @@ -150,9 +150,11 @@ def legofy_image(base_image, brick_image, output_path, size, palette_mode, dithe if palette_mode: palette = get_lego_palette(palette_mode) base_image = apply_thumbnail_effects(base_image, palette, dither) + lego_image, brick_stats = make_lego_image(base_image, brick_image) - if stats == True: + if stats: print(brick_stats) + lego_image.save(output_path) diff --git a/legofy/palettes.py b/legofy/palettes.py index 0d28643..bd4d544 100644 --- a/legofy/palettes.py +++ b/legofy/palettes.py @@ -152,6 +152,7 @@ def legos(): """Build flattened lego palettes.""" return _flatten_palettes(LEGOS.copy()) + def _flatten_palettes(palettes): """Convert palette mappings into color list.""" flattened = {}