Esempio n. 1
0
def reduce_palette(palette, image):
    # No-op if palette is smol
    if len(palette) <= 256:
        return palette

    palette_triplets = [x["rgb"] for x in palette]
    best_colours = set()

    # Get image palette in RGB triplets
    im = image.convert("P", palette=Image.ADAPTIVE, colors=256)
    image_palette = im.getpalette()
    my_colours = []
    for i in range(0, len(image_palette), 3):
        my_colours.append(image_palette[i:i + 3])

    # Get nearest colour https://stackoverflow.com/a/22478139
    tree = sp.KDTree(palette_triplets)
    for colour in my_colours:
        _, result = tree.query(colour)
        best_colours.add(rgb2hex(palette_triplets[result]))

    # Stick best_colours at the front of our palette
    first_colours = []
    for item in palette:
        if item["hex"] in best_colours:
            first_colours.append(item)

    first_colours += palette

    return first_colours
Esempio n. 2
0
File: chart.py Progetto: glasnt/ih
def generate_term_chart(chartimage, pal, render, palette_name, data):
    def c(text, bg=None, fg=None):
        def color(rgb, code):
            if not rgb:
                return ""
            R, G, B = rgb
            return f"\033[{code};2;{R};{G};{B}m"

        def foreground(rgb=None):
            return color(rgb, "38")

        def background(rgb=None):
            return color(rgb, "48")

        def reset():
            return "\033[0;00m"

        result = foreground(fg) + background(bg) + text + reset()
        return result

    def star(rgb, render=False):
        p = helpers.rgb2hex(rgb)
        if render:
            return c("  ", bg=rgb)
        else:
            return c(legend[p], fg=rgb) + " "

    legend, styles, histogram = get_legend(chartimage)

    headers = [
        "*",
        palette.get_identity_name(palette_name), f"{palette_name} code"
    ]
    table = []
    result = "\n"

    for idx, h in enumerate(reversed(histogram)):
        count, rgb = h
        color = helpers.rgb2hex(rgb)
        thread = palette.thread_name(rgb, pal)
        code = thread["code"]
        symbol = star(rgb, render=render)

        table.append([symbol, str(count), code])

    result += tabulate(table, headers=headers)
    result += "\n\n"

    for y in range(0, chartimage.height):
        row = []
        for x in range(0, chartimage.width):
            rgb = chartimage.getpixel((x, y))
            row.append(star(rgb, render=render))

        result += "".join(row) + "\n"
    result += "\n" + data
    return result
Esempio n. 3
0
File: chart.py Progetto: glasnt/ih
def get_legend(chartimage):
    legend = {}
    styles = {}
    histogram = sorted(chartimage.getcolors())
    STARS = helpers.STARS
    for idx, x in enumerate(histogram):
        rgb = x[1]
        h = helpers.rgb2hex(rgb)
        star = STARS[idx % len(STARS)]
        sclass = helpers.col_class(h)

        # Choose the best text colour
        if (rgb[0] * 0.299 + rgb[1] * 0.587 + rgb[2] * 0.114) > 186:
            color = "black"
        else:
            color = "lightgray"

        styles[sclass] = {"bg": h, "rgb": rgb, "c": color, "star": star}

        legend[helpers.rgb2hex(x[1])] = STARS[idx % len(STARS)]
    return legend, styles, histogram
Esempio n. 4
0
File: chart.py Progetto: glasnt/ih
 def star(rgb, render=False):
     p = helpers.rgb2hex(rgb)
     if render:
         return c("  ", bg=rgb)
     else:
         return c(legend[p], fg=rgb) + " "
Esempio n. 5
0
File: chart.py Progetto: glasnt/ih
def generate_html_chart(
    image_name,
    chartimage,
    palette_name,
    pal,
    render=False,
    guidelines=False,
    data="",
):

    html = [
        f'<html><meta charset="UTF-8" /><title>ih - {nicename(image_name)}</title>'
    ]
    html.append(
        '<link rel="icon" href="data:image/svg+xml,%3csvg xmlns=%22http://www.w3.org/2000/svg%22 viewBox=%220 0 100 100%22%3e%3ctext y=%22.9em%22 font-size=%2290%22%3e%f0%9f%a7%b6%3c/text%3e%3c/svg%3e" />'
    )

    with open(helpers.base_path("styling").joinpath("styling.css")) as s:
        html.append("<style>")
        if guidelines:
            html.append(":root { --border: lightgrey; }")
        else:
            html.append(":root { --border: black; }")
        html.append("".join(s.readlines()) + "</style>")

    if render:
        html.append(
            dedent("""
            <style>
            .s {  
                background-image: url('%s'); 
                background-size: cover; 
                border: none; 
            }
            .r { border: none }
            .chart { border: 1px solid black }
            </style>
            """ % palette.get_thread_image(palette_name)))

    legend, styles, histogram = get_legend(chartimage)
    after = {}

    html.append("<style>")
    for _, x in enumerate(styles):
        y = styles[x]

        html.append(".%s { background-color: %s; color: %s }" %
                    (x, y["bg"], y["c"]))
        if not render:
            html.append('.%s::after { content: "%s\ufe0e" }' % (x, y["star"]))

    if not render:
        html.append('.%s::after { content: "%s" }' %
                    (helpers.col_class(helpers.WHITECOL), helpers.WHITESTAR))

    html.append("</style>")

    html.append('<div class="container">')
    html.append('<div class="left-content">')
    html.append('<div class="legend_div"><table class="legend">')
    html.append((
        f"<tr><td>X</td><td class='label'>{palette.get_identity_name(palette_name)}</td>"
        f"<td class='label'>{palette_name} code</td></tr>"))

    # Generate legend
    for idx, h in enumerate(reversed(histogram)):
        count, rgb = h
        color = helpers.rgb2hex(rgb)
        thread = palette.thread_name(rgb, pal)
        code = thread["code"]

        html.append("<tr>" + helpers.color_cell(
            color=color, star=legend[color], thread=False, legend=True) +
                    "<td>{}</td><td>{}</td></tr>".format(count, code))

    html.append("</table></div>")

    html.append(f'<div class="debug">{data}</div>')

    # If using guidelines, enable printhacks
    if guidelines:
        with open(helpers.base_path("styling").joinpath("styling.html")) as s:
            html.append("".join(s.readlines()))

    html.append("</div>")  # end left-content
    html.append("<div class='page-break'></div>")  # force page break

    html.append('<div class="right-content"><div class="chart">')

    # If using guidelines, expand the image to a whole number of guidelines first.
    if guidelines:
        chartimage = chartimage.convert("RGBA")
        xpad = GUIDE - (chartimage.width % GUIDE)
        ypad = GUIDE - (chartimage.height % GUIDE)

        padding = (floor(ypad / 2), ceil(xpad / 2), ceil(ypad / 2),
                   floor(xpad / 2))

        chartimage = ImageOps.expand(chartimage, padding, fill=GUIDECOL)

    # Generate Chart (TODO(glasnt): make this less terrible)
    CENTER = True
    for y in range(0, chartimage.height):

        row = []

        for x in range(0, chartimage.width):
            guide_x, guide_y = False, False
            if guidelines:
                if x % GUIDE == GUIDE - 1:
                    guide_x = True
                if y % GUIDE == GUIDE - 1:
                    guide_y = True

            rgb = chartimage.getpixel((x, y))

            if rgb == GUIDECOL:
                row.append(helpers.guide_cell([guide_x, guide_y]))
                continue
            p = helpers.rgb2hex(rgb)

            center_flag = False
            if not render:
                if CENTER:
                    if chartimage.height / 2 - 1 <= y and chartimage.width / 2 - 1 <= x:
                        center_flag = True
                        CENTER = False

            row.append(
                helpers.color_cell(
                    color=p,
                    star=legend[p],
                    center=center_flag,
                    guide=[guide_x, guide_y],
                ))

        html.append("<div class='r'>" + "".join(row) + "</div>")
    html.append("</div></div></div></html>")
    return "\n".join(html)