Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Annotate hex codes in the web app #21

Merged
merged 6 commits into from
Sep 17, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 7 additions & 3 deletions CONTRIBUTING.rst
Original file line number Diff line number Diff line change
Expand Up @@ -49,17 +49,21 @@ To set up `img2cmap` for local development:

Now you can make your changes locally.

4. When you're done making changes run all the checks and docs builder with `tox <https://tox.readthedocs.io/en/latest/install.html>`_ one command::
4. Install development requirements::

pip install img2cmap[dev]

5. When you're done making changes run all the checks and docs builder with `tox <https://tox.readthedocs.io/en/latest/install.html>`_ one command::

tox

5. Commit your changes and push your branch to GitHub::
6. Commit your changes and push your branch to GitHub::

git add .
git commit -m "Your detailed description of your changes."
git push origin name-of-your-bugfix-or-feature

6. Submit a pull request through the GitHub website.
7. Submit a pull request through the GitHub website.

Pull Request Guidelines
-----------------------
Expand Down
6 changes: 4 additions & 2 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,11 @@ EXPOSE 8501
WORKDIR /app
COPY . /app

RUN apt-get update \
&& apt-get install --yes --no-install-recommends \
gcc g++ libffi-dev
RUN pip install --upgrade pip
RUN pip install streamlit
RUN pip install -e .
RUN pip install .[streamlit]

ENTRYPOINT [ "streamlit", "run"]
CMD ["/app/streamlit/app.py"]
19 changes: 15 additions & 4 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,6 @@ img2cmap
Usage
=====

Basic
-----

**Create colormaps from images in three lines of code!**

| First, ``ImageConverter`` class converts images to arrays of RGB values.
Expand Down Expand Up @@ -157,7 +154,7 @@ of the image.
hexcodes
^^^^^^^^

When running the ``generate_cmap`` or the ``generate_optimal_cmap`` methods the ImageConverter object will automatically
When running the ``generate_cmap`` or the ``generate_optimal_cmap`` methods the ImageConverter object will automatically
capture the resulting hexcodes from the colormap and store them as an attribute.

.. code-block:: python3
Expand Down Expand Up @@ -196,6 +193,14 @@ Documentation
https://img2cmap.readthedocs.io/


Web App
=======

Check out the web app at https://img2cmap.fly.dev

.. image:: images/webapp_image.png
:align: center

Status
======

Expand Down Expand Up @@ -248,6 +253,12 @@ Status
Development
===========

Install the development requirements:

::

pip install img2cmap[dev]

To run all the tests run::

tox
Expand Down
Binary file added images/webapp_image.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
7 changes: 3 additions & 4 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -73,9 +73,8 @@ def read(*names, **kwargs):
"kneed",
],
extras_require={
"dev": ["black", "requests"],
# eg:
# 'rst': ['docutils>=0.11'],
# ':python_version=="2.6"': ['argparse'],
"dev": ["black", "requests", "tox"],
"streamlit": ["streamlit", "st-annotated-text"],
"all": ["black", "requests", "tox", "streamlit", "st-annotated-text"],
},
)
50 changes: 40 additions & 10 deletions streamlit/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,33 @@
import matplotlib.patches as patches
import matplotlib.pyplot as plt
import numpy as np
from annotated_text import annotated_text
from mpl_toolkits.axes_grid1 import make_axes_locatable

import streamlit as st
from img2cmap import ImageConverter


def colorpicker(color):
"""Logic to decide between black or white text for a given background color.
https://stackoverflow.com/a/3943023/4541548
"""
red, green, blue = mpl.colors.to_rgb(color)
newrgb = []
for c in red, green, blue:
c = c / 255.0
if c <= 0.04045:
newrgb.append(c / 12.92)
else:
newrgb.append(((c + 0.055) / 1.055) ^ 2.4)
L = 0.2126 * newrgb[0] + 0.7152 * newrgb[1] + 0.0722 * newrgb[2]
# why did I have to use 179 instead of 0.179?
if L > 0.179 / 1000:
return "#000000"
else:
return "#ffffff"


# @profile
def main():
warnings.filterwarnings("ignore")
Expand Down Expand Up @@ -38,7 +59,9 @@ def main():
if user_image is not None:
user_image = BytesIO(user_image.getvalue())
elif file_or_url == "url":
user_image = st.sidebar.text_input("Paste an image URL", "https://static1.bigstockphoto.com/3/2/3/large1500/323952496.jpg")
user_image = st.sidebar.text_input(
"Paste an image URL", "https://static1.bigstockphoto.com/3/2/3/large1500/323952496.jpg"
)
else:
st.warning("Please select an option")

Expand Down Expand Up @@ -85,21 +108,26 @@ def get_image_converter(user_image, remove_transparent):
cb.set_ticks([])
st.pyplot(fig1)

st.caption(
"The original image has been resized to a smaller size, if you want to see "
"the colormap for the full size image, use the Python package."
)

colors1 = [mpl.colors.rgb2hex(c) for c in cmap.colors]
st.text("Hex Codes (click to copy on far right)")

# determine whether to show the text in white or black
bw_mask = [colorpicker(c) for c in colors1]

st.header("Hex Codes")
annotated_text(*[(hexcode, "", hexcode, text_color) for hexcode, text_color in zip(colors1, bw_mask)])
Copy link
Collaborator

@mpkrass7 mpkrass7 Sep 17, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What a one liner, really like how clean this shows on the app

st.code(colors1)
st.caption("Click copy button on far right to copy hex codes to clipboard.")

st.header("Detect optimal number of colors")
max_colors = st.number_input("Max number of colors in cmap (more colors = longer runtime)", min_value=2, max_value=20, value=10)
max_colors = st.number_input(
"Max number of colors in cmap (more colors = longer runtime)", min_value=2, max_value=20, value=10
)
optimize = st.button("Optimize")
if optimize:
with st.spinner("Optimizing... (this can take up to a minute)"):
cmaps, best_n_colors, ssd = converter.generate_optimal_cmap(max_colors=max_colors, palette_name="", random_state=random_state)
cmaps, best_n_colors, ssd = converter.generate_optimal_cmap(
max_colors=max_colors, palette_name="", random_state=random_state
)

figopt, ax = plt.subplots(figsize=(7, 5))

Expand All @@ -124,7 +152,9 @@ def get_image_converter(user_image, remove_transparent):
ax.set_xticks([])

# best
rect = patches.Rectangle((0, best_n_colors), ymax, 1, linewidth=1, facecolor="none", edgecolor="black", linestyle="--")
rect = patches.Rectangle(
(0, best_n_colors), ymax, 1, linewidth=1, facecolor="none", edgecolor="black", linestyle="--"
)
ax.add_patch(rect)

# minus 2, one for starting at 2 and one for 0-indexing
Expand Down