Skip to content

Commit

Permalink
Flip row/col in visualizer
Browse files Browse the repository at this point in the history
  • Loading branch information
inFocus7 committed Jan 15, 2024
1 parent 6593f0e commit 72d3eb8
Show file tree
Hide file tree
Showing 9 changed files with 273 additions and 174 deletions.
61 changes: 30 additions & 31 deletions processing/image.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,32 +35,32 @@ def render_image_output() -> (gr.Image, gr.Textbox, gr.Dropdown, gr.Button):
return image_output, image_name, image_suffix, save_image_button


def render_text_editor_parameters(name: str) -> ((gr.Dropdown, gr.Dropdown, gr.ColorPicker, gr.Slider, gr.Number),
(gr.Checkbox, gr.ColorPicker, gr.Slider, gr.Number),
(gr.Checkbox, gr.ColorPicker, gr.Slider)):
def render_text_editor_parameters(name: str) -> (dataclasses.FontGradioComponents,
dataclasses.FontDropShadowGradioComponents,
dataclasses.FontBackgroundGradioComponents):
"""
Renders the text editor parameters.
:param name: The name of the text editor parameters. This is used as the label for the accordion.
:return: A tuple containing the font, drop shadow, and background components.
:return: Classes containing the font, drop shadow, and background components.
"""
with gr.Accordion(label=name):
with gr.Column():
font_family, font_style, font_color, font_opacity, font_size = gru.render_font_picker()
font_data = gru.render_font_picker()
with gr.Group():
drop_shadow_checkbox = gr.Checkbox(False, label="Enable Drop Shadow", interactive=True)
with gr.Group(visible=drop_shadow_checkbox.value) as additional_options:
drop_shadow_enabled = gr.Checkbox(False, label="Enable Drop Shadow", interactive=True)
with gr.Group(visible=drop_shadow_enabled.value) as additional_options:
drop_shadow_color, drop_shadow_opacity = gru.render_color_opacity_picker()
drop_shadow_radius = gr.Number(0, label="Shadow Radius")
gru.bind_checkbox_to_visibility(drop_shadow_checkbox, additional_options)
gru.bind_checkbox_to_visibility(drop_shadow_enabled, additional_options)
with gr.Group():
background_checkbox = gr.Checkbox(False, label="Enable Background", interactive=True)
with gr.Group(visible=background_checkbox.value) as additional_options:
background_enabled = gr.Checkbox(False, label="Enable Background", interactive=True)
with gr.Group(visible=background_enabled.value) as additional_options:
background_color, background_opacity = gru.render_color_opacity_picker()
gru.bind_checkbox_to_visibility(background_checkbox, additional_options)
gru.bind_checkbox_to_visibility(background_enabled, additional_options)

return ((font_family, font_style, font_size, font_color, font_opacity),
(drop_shadow_checkbox, drop_shadow_color, drop_shadow_opacity, drop_shadow_radius),
(background_checkbox, background_color, background_opacity))
return (font_data, dataclasses.FontDropShadowGradioComponents(drop_shadow_enabled, drop_shadow_color,
drop_shadow_opacity, drop_shadow_radius),
dataclasses.FontBackgroundGradioComponents(background_enabled, background_color, background_opacity))


def add_background(image_pil: Image, draw: ImageDraw, position: tuple[int, int], text: str, font: ImageFont,
Expand Down Expand Up @@ -256,8 +256,6 @@ def add_text(image: Union[Image.Image, np.ndarray], text: str, position: Tuple[i
font = ImageFont.truetype(font_path, font_size)
draw = ImageDraw.Draw(txt_layer)

img_width, _ = image_pil.size

if max_width: # Prepare for text wrapping if max_width is provided
wrapped_text = textwrap.fill(text, width=max_width)
else:
Expand All @@ -266,31 +264,32 @@ def add_text(image: Union[Image.Image, np.ndarray], text: str, position: Tuple[i
lines = wrapped_text.split('\n')

y_offset = 0
max_line_width = 0 # Keep track of the widest line
total_height = 0 # Accumulate total height of text block
# max_line_width = 0 # Keep track of the widest line
# total_height = 0 # Accumulate total height of text block
text_container = dataclasses.Size(width=0, height=0)
for line in lines:
bbox = draw.textbbox((0, 0), line, font=font)
line_width = bbox[2] - bbox[0]
line_height = bbox[3] - bbox[1]
max_line_width = max(max_line_width, line_width)
total_height += line_height
line_size = dataclasses.Size(width=bbox[2] - bbox[0], height=bbox[3] - bbox[1])
text_container.width = max(text_container.width, line_size.width)
text_container.height += line_size.height

text_x = position[0]
pos = dataclasses.Position
pos.x = position[0]
if x_center:
text_x = (img_width - line_width) / 2
line_y = position[1] + y_offset
y_offset += (line_height + 6)
pos.x = (image_pil.width - line_size.width) / 2
pos.y = position[1] + y_offset
y_offset += (line_size.height + 6)

if show_background:
(text_x, line_y), _ = add_background(image_pil, draw, (text_x, line_y), line, font,
fill_color=background_color, border_radius=10)
(pos.x, pos.y), _ = add_background(image_pil, draw, (pos.x, pos.y), line, font,
fill_color=background_color, border_radius=10)

if show_shadow:
shadow_position = (text_x, line_y)
shadow_position = (pos.x, pos.y)
add_blurred_shadow(image_pil, line, shadow_position, font, shadow_color=shadow_color,
blur_radius=shadow_radius)

draw.text((text_x, line_y), line, font=font, fill=font_color)
draw.text((pos.x, pos.y), line, font=font, fill=font_color)

image_pil = Image.alpha_composite(image_pil, txt_layer)
return np.array(image_pil), (max_line_width, total_height)
return np.array(image_pil), (text_container.width, text_container.height)
7 changes: 4 additions & 3 deletions ui/components/openai.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,16 @@
This module contains ui components for the OpenAI API.
"""
import gradio as gr
from utils import dataclasses


def render_openai_setup(show_text_model: bool = True, show_image_model: bool = True) \
-> (gr.Textbox, gr.Dropdown, gr.Dropdown):
-> dataclasses.OpenAIGradioComponents:
"""
Renders the OpenAI API setup components.
:param show_text_model: Whether to show the text model dropdown.
:param show_image_model: Whether to show the image model dropdown.
:return: A tuple containing the API key, text model, and image model components.
:return: A class containing the API key, text model, and image model components.
"""
api_text_model = None
api_image_model = None
Expand All @@ -25,4 +26,4 @@ def render_openai_setup(show_text_model: bool = True, show_image_model: bool = T
api_image_model = gr.Dropdown(["dall-e-2", "dall-e-3"], label="API Image Model", value="dall-e-2",
interactive=True)

return api_key, api_text_model, api_image_model
return dataclasses.OpenAIGradioComponents(api_key, api_text_model, api_image_model)
48 changes: 29 additions & 19 deletions ui/listicles/interface.py
Original file line number Diff line number Diff line change
Expand Up @@ -81,15 +81,11 @@ def set_json(json_file):
with gr.Column(scale=3):
gr.Markdown("# Parameters")
with gr.Row(equal_height=False):
(nf_family, nf_style, nfs, nfc, nfo), (nse, nsc, nso, nsr), (
nbe, nbc, nbo) = image_processing.render_text_editor_parameters("Name")
(df_family, df_style, dfs, dfc, dfo), (dse, dsc, dso, dsr), (
dbe, dbc, dbo) = image_processing.render_text_editor_parameters("Description")
name_font, name_shadow, name_background = image_processing.render_text_editor_parameters("Name")
desc_font, desc_shadow, desc_background = image_processing.render_text_editor_parameters("Description")
with gr.Row(equal_height=False):
(mf_family, mf_style, mfs, mfc, mfo), (mse, msc, mso, msr), (
mbe, mbc, mbo) = image_processing.render_text_editor_parameters("Association")
(rf_family, rf_style, rfs, rfc, rfo), (rse, rsc, rso, rsr), (
rbe, rbc, rbo) = image_processing.render_text_editor_parameters("Rating")
asc_font, asc_shadow, asc_background = image_processing.render_text_editor_parameters("Association")
rate_font, rate_shadow, rate_background = image_processing.render_text_editor_parameters("Rating")

with gr.Column(scale=1):
gr.Markdown("# Output")
Expand All @@ -103,14 +99,26 @@ def set_json(json_file):
save_button.click(image_processing.save_images_to_disk, inputs=[output_preview, image_type],
outputs=[])
process_button.click(listicle_utils.process, inputs=[input_batch_images, input_batch_json,
nf_family, nf_style, nfs, nfc, nfo, nse, nsc, nso, nsr, nbe,
nbc, nbo,
df_family, df_style, dfs, dfc, dfo, dse, dsc, dso, dsr, dbe,
dbc, dbo,
mf_family, mf_style, mfs, mfc, mfo, mse, msc, mso, msr, mbe,
mbc, mbo,
rf_family, rf_style, rfs, rfc, rfo, rse, rsc, rso, rsr, rbe,
rbc, rbo
name_font.family, name_font.style, name_font.size,
name_font.color, name_font.opacity, name_shadow.enabled,
name_shadow.color, name_shadow.opacity, name_shadow.radius,
name_background.enabled, name_background.color,
name_background.opacity,
desc_font.family, desc_font.style, desc_font.size,
desc_font.color, desc_font.opacity, desc_shadow.enabled,
desc_shadow.color, desc_shadow.opacity, desc_shadow.radius,
desc_background.enabled, desc_background.color,
desc_background.opacity,
asc_font.family, asc_font.style, asc_font.size,
asc_font.color, asc_font.opacity, asc_shadow.enabled,
asc_shadow.color, asc_shadow.opacity, asc_shadow.radius,
asc_background.enabled, asc_background.color,
asc_background.opacity,
rate_font.family, rate_font.style, rate_font.size,
rate_font.color, rate_font.opacity, rate_shadow.enabled,
rate_shadow.color, rate_shadow.opacity, rate_shadow.radius,
rate_background.enabled, rate_background.color,
rate_background.opacity,
], outputs=[output_preview])

return input_batch_images, input_batch_json
Expand All @@ -121,7 +129,8 @@ def render_generate_section() -> (gr.Button, gr.Gallery, gr.Code):
Renders the Generate Artifacts section of the web app.
:return: The send artifacts to batch button, the listicle image output gallery, and the listicle json output.
"""
api_key, api_text_model, api_image_model = openai_components.render_openai_setup()
# api_key, api_text_model, api_image_model = openai_components.render_openai_setup()
open_ai_components = openai_components.render_openai_setup()
with gr.Row(equal_height=False):
with gr.Group():
with gr.Group():
Expand Down Expand Up @@ -159,8 +168,9 @@ def render_generate_section() -> (gr.Button, gr.Gallery, gr.Code):
send_artifacts_to_batch_button = gr.Button("Send Artifacts to 'Batch Processing'",
variant="secondary")
generate_listicle_button.click(listicle_utils.generate_listicle,
inputs=[api_key, api_text_model, api_image_model, num_items, topic,
association, rating_type, details, generate_artifacts],
inputs=[open_ai_components.api_key, open_ai_components.api_text_model,
open_ai_components.api_image_model, num_items, topic, association,
rating_type, details, generate_artifacts],
outputs=[listicle_output, listicle_json_output, listicle_image_output])
download_artifacts_button.click(
listicle_utils.save_artifacts,
Expand Down
38 changes: 15 additions & 23 deletions ui/listicles/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -83,24 +83,16 @@ def process(image_files: list[Any], json_data: str,
return None

font_families = font_manager.get_fonts()
nff = font_families[nf_family][nf_style]
dff = font_families[df_family][df_style]
mff = font_families[mf_family][mf_style]
rff = font_families[rf_family][rf_style]

images = []

rating_offset = 34
text_offset = 49
json_data = json.loads(json_data)

if len(image_files) != len(json_data["items"]):
gr.Warning(
f"Number of images ({len(image_files)}) does not match the number of items in the JSON ({len(json_data)}).")

# We skip any entries that don't have an image field.
json_data_items = json_data["items"]
json_dict = {item["image"]: item for item in json_data_items if "image" in item}
json_dict = {item["image"]: item for item in json_data["items"] if "image" in item}

for image_file in image_files:
img_name = os.path.basename(image_file.name)
Expand All @@ -112,31 +104,31 @@ def process(image_files: list[Any], json_data: str,
img = image_processing.read_image_from_disk(image_file.name, size=(1080, 1920))
item = json_dict[img_name]

# Calculate positions for the text
# Calculate y-positions for the text
top_center = (0, int(img.shape[0] * 0.13))
bottom_center = (0, int(img.shape[0] * 0.70))

# Add association and rating at the top center, one above the other
img, (_, association_height) = image_processing.add_text(img, item["association"], top_center, mff,
font_size=mfs,
img, (_, association_height) = image_processing.add_text(img, item["association"], top_center,
font_families[mf_family][mf_style], font_size=mfs,
font_color=image_utils.get_rgba(mfc, mfo),
show_shadow=mse,
shadow_radius=msr,
show_shadow=mse, shadow_radius=msr,
shadow_color=image_utils.get_rgba(msc, mso),
show_background=mbe,
background_color=image_utils.get_rgba(mbc, mbo),
x_center=True)

img, (_, _) = image_processing.add_text(img, f'{json_data["rating_type"]}: {item["rating"]}%',
(0, top_center[1] + association_height + rating_offset),
rff, font_size=rfs, font_color=image_utils.get_rgba(rfc, rfo),
show_shadow=rse, shadow_radius=rsr,
shadow_color=image_utils.get_rgba(rsc, rso),
(0, top_center[1] + association_height + 34),
font_families[rf_family][rf_style], font_size=rfs,
font_color=image_utils.get_rgba(rfc, rfo), show_shadow=rse,
shadow_radius=rsr, shadow_color=image_utils.get_rgba(rsc, rso),
show_background=rbe, background_color=image_utils.get_rgba(rbc, rbo),
x_center=True)

# Add name and description at the bottom center, one above the other
img, (_, name_height) = image_processing.add_text(img, item["name"], bottom_center, nff, font_size=nfs,
img, (_, name_height) = image_processing.add_text(img, item["name"], bottom_center,
font_families[nf_family][nf_style], font_size=nfs,
font_color=image_utils.get_rgba(nfc, nfo),
max_width=15,
show_shadow=nse, shadow_radius=nsr,
Expand All @@ -145,10 +137,10 @@ def process(image_files: list[Any], json_data: str,
background_color=image_utils.get_rgba(nbc, nbo),
x_center=True)
img, (_, _) = image_processing.add_text(img, f'"{item["description"]}"',
(0, bottom_center[1] + name_height + text_offset), dff,
font_size=dfs, font_color=image_utils.get_rgba(dfc, dfo),
show_shadow=dse, shadow_radius=dsr,
shadow_color=image_utils.get_rgba(dsc, dso),
(0, bottom_center[1] + name_height + 49),
font_families[df_family][df_style], font_size=dfs,
font_color=image_utils.get_rgba(dfc, dfo), show_shadow=dse,
shadow_radius=dsr, shadow_color=image_utils.get_rgba(dsc, dso),
show_background=dbe, background_color=image_utils.get_rgba(dbc, dbo),
max_width=43, x_center=True)

Expand Down
Loading

0 comments on commit 72d3eb8

Please sign in to comment.