Surn commited on
Commit
cbf9ae2
·
1 Parent(s): 4d9275b

Cherry Pick readmeMarketing Information Update

Browse files
Files changed (3) hide show
  1. README.md +39 -0
  2. app.py +590 -127
  3. requirements.txt +7 -2
README.md CHANGED
@@ -4,6 +4,7 @@ emoji: 🐝
4
  colorFrom: yellow
5
  colorTo: purple
6
  sdk: gradio
 
7
  sdk_version: 5.12.0
8
  app_file: app.py
9
  pinned: false
@@ -24,4 +25,42 @@ thumbnail: >-
24
  https://cdn-uploads.huggingface.co/production/uploads/6346595c9e5f0fe83fc60444/s0fQvcoiSBlH36AXpVwPi.png
25
  ---
26
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
27
  Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
 
4
  colorFrom: yellow
5
  colorTo: purple
6
  sdk: gradio
7
+ python_version: 3.10.13
8
  sdk_version: 5.12.0
9
  app_file: app.py
10
  pinned: false
 
25
  https://cdn-uploads.huggingface.co/production/uploads/6346595c9e5f0fe83fc60444/s0fQvcoiSBlH36AXpVwPi.png
26
  ---
27
 
28
+ Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
29
+
30
+ # HexaGrid Creator
31
+ ## Description
32
+ Welcome to HexaGrid Creator, the ultimate tool for transforming your images into mesmerizing hexagon grid masterpieces! Whether you're a tabletop game enthusiast, a digital artist, or just someone who loves unique patterns, HexaGrid Creator has something for you.
33
+
34
+ ### What Can You Do?
35
+ - **Generate Hexagon Grids:** Create stunning hexagon grid overlays on any image with fully customizable parameters.
36
+ - **AI-Powered Image Generation:** Use AI to generate images based on your prompts and apply hexagon grids to them.
37
+ - **Color Exclusion:** Pick and exclude specific colors from your hexagon grid for a cleaner and more refined look.
38
+ - **Interactive Customization:** Adjust hexagon size, border size, rotation, background color, and more in real-time.
39
+ - **Depth and 3D Model Generation:** Generate depth maps and 3D models from your images for enhanced visualization.
40
+ - **Image Filter [Look-Up Table (LUT)] Application:** Apply filters (LUTs) to your images for color grading and enhancement.
41
+ - **Pre-rendered Maps:** Access a library of pre-rendered hexagon maps for quick and easy customization.
42
+ - **Add Margins:** Add customizable margins around your images for a polished finish.
43
+
44
+ ### Why You'll Love It
45
+ - **Fun and Easy to Use:** With an intuitive interface and real-time previews, creating hexagon grids has never been this fun!
46
+ - **Endless Creativity:** Unleash your creativity with endless customization options and see your images transform in unique ways.
47
+ - **Bee-Inspired Theme:** Enjoy a delightful yellow and purple theme inspired by bees and hexagons! 🐝
48
+ - **Advanced AI Models:** Leverage advanced AI models and LoRA weights for high-quality image generation and customization.
49
+
50
+ ### Get Started
51
+ 1. **Upload or Generate an Image:** Start by uploading your own image or generate one using our AI-powered tool.
52
+ 2. **Customize Your Grid:** Play around with the settings to create the perfect hexagon grid overlay.
53
+ 3. **Download and Share:** Once you're happy with your creation, download it and share it with the world!
54
+
55
+ ### Advanced Features
56
+ - **Generative AI Integration:** Utilize models like `black-forest-labs/FLUX.1-dev` and various LoRA weights for generating unique images.
57
+ - **Pre-rendered Maps:** Access a library of pre-rendered hexagon maps for quick and easy customization.
58
+ - **Image Filter [Look-Up Table (LUT)] Application:** Apply filters (LUTs) to your images for color grading and enhancement.
59
+ - **Depth and 3D Model Generation:** Create depth maps and 3D models from your images for enhanced visualization.
60
+ - **Add Margins:** Customize margins around your images for a polished finish.
61
+
62
+ Join the hive and start creating with HexaGrid Creator today!
63
+
64
+ ## Contributions
65
+ Thanks to [@Surn](https://huggingface.co/spaces/Surn/beeuty) for adding this gradio theme!
66
  Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
app.py CHANGED
@@ -1,155 +1,618 @@
1
- import gradio as gr
2
- import numpy as np
 
 
 
 
 
3
  import random
4
- import spaces
 
5
 
6
- # import spaces #[uncomment to use ZeroGPU]
7
- from diffusers import DiffusionPipeline
8
- import torch
9
 
10
- device = "cuda" if torch.cuda.is_available() else "cpu"
11
- model_repo_id = "stabilityai/sdxl-turbo" # Replace to the model you would like to use
12
 
13
- if torch.cuda.is_available():
14
- torch_dtype = torch.float16
15
- else:
16
- torch_dtype = torch.float32
 
 
 
 
17
 
18
- pipe = DiffusionPipeline.from_pretrained(model_repo_id, torch_dtype=torch_dtype)
19
- pipe = pipe.to(device)
 
 
 
 
 
 
 
 
 
 
20
 
21
- MAX_SEED = np.iinfo(np.int32).max
22
- MAX_IMAGE_SIZE = 1024
 
 
23
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
24
 
25
  @spaces.GPU(duration=128)
26
- def infer(
27
- prompt,
28
- negative_prompt,
29
- seed,
30
- randomize_seed,
31
- width,
32
- height,
33
- guidance_scale,
34
- num_inference_steps,
35
- progress=gr.Progress(track_tqdm=True),
36
- ):
37
- if randomize_seed:
38
- seed = random.randint(0, MAX_SEED)
39
-
40
- generator = torch.Generator().manual_seed(seed)
41
-
42
- image = pipe(
43
- prompt=prompt,
44
- negative_prompt=negative_prompt,
45
- guidance_scale=guidance_scale,
46
- num_inference_steps=num_inference_steps,
47
- width=width,
 
 
 
 
 
 
48
  height=height,
49
- generator=generator,
50
- ).images[0]
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
51
 
52
- return image, seed
 
 
 
 
 
 
53
 
 
 
54
 
55
- examples = [
56
- "Astronaut in a jungle, cold color palette, muted colors, detailed, 8k",
57
- "An astronaut riding a green horse",
58
- "A delicious ceviche cheesecake slice",
59
- ]
 
 
60
 
61
- css = """
62
- #col-container {
63
- margin: 0 auto;
64
- max-width: 640px;
65
- }
66
- """
67
 
68
- with gr.Blocks(css=css) as demo:
69
- with gr.Column(elem_id="col-container"):
70
- gr.Markdown(" # Text-to-Image Gradio Template")
 
 
71
 
72
- with gr.Row():
73
- prompt = gr.Text(
74
- label="Prompt",
75
- show_label=False,
76
- max_lines=1,
77
- placeholder="Enter your prompt",
78
- container=False,
79
- )
80
 
81
- run_button = gr.Button("Run", scale=0, variant="primary")
 
 
 
 
 
 
 
 
 
82
 
83
- result = gr.Image(label="Result", show_label=False)
84
 
85
- with gr.Accordion("Advanced Settings", open=False):
86
- negative_prompt = gr.Text(
87
- label="Negative prompt",
88
- max_lines=1,
89
- placeholder="Enter a negative prompt",
90
- visible=False,
91
- )
 
 
 
 
 
 
 
 
 
 
 
 
 
92
 
93
- seed = gr.Slider(
94
- label="Seed",
95
- minimum=0,
96
- maximum=MAX_SEED,
97
- step=1,
98
- value=0,
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
99
  )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
100
 
101
- randomize_seed = gr.Checkbox(label="Randomize seed", value=True)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
102
 
 
 
103
  with gr.Row():
104
- width = gr.Slider(
105
- label="Width",
106
- minimum=256,
107
- maximum=MAX_IMAGE_SIZE,
108
- step=32,
109
- value=1024, # Replace with defaults that work for your model
110
- )
111
-
112
- height = gr.Slider(
113
- label="Height",
114
- minimum=256,
115
- maximum=MAX_IMAGE_SIZE,
116
- step=32,
117
- value=1024, # Replace with defaults that work for your model
118
- )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
119
 
120
- with gr.Row():
121
- guidance_scale = gr.Slider(
122
- label="Guidance scale",
123
- minimum=0.0,
124
- maximum=10.0,
125
- step=0.1,
126
- value=0.0, # Replace with defaults that work for your model
127
- )
128
-
129
- num_inference_steps = gr.Slider(
130
- label="Number of inference steps",
131
- minimum=1,
132
- maximum=50,
133
- step=1,
134
- value=2, # Replace with defaults that work for your model
135
- )
136
-
137
- gr.Examples(examples=examples, inputs=[prompt])
138
- gr.on(
139
- triggers=[run_button.click, prompt.submit],
140
- fn=infer,
141
- inputs=[
142
- prompt,
143
- negative_prompt,
144
- seed,
145
- randomize_seed,
146
- width,
147
- height,
148
- guidance_scale,
149
- num_inference_steps,
150
- ],
151
- outputs=[result, seed],
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
152
  )
153
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
154
  if __name__ == "__main__":
155
- demo.launch()
 
 
1
+ import gradio as gr
2
+ from PIL import Image, ImageDraw, ImageChops, ImageColor
3
+ from haishoku.haishoku import Haishoku
4
+ import os
5
+ from tempfile import NamedTemporaryFile
6
+ from pathlib import Path
7
+ import atexit
8
  import random
9
+ # Import constants
10
+ import utils.constants as constants
11
 
12
+ IS_SHARED_SPACE = constants.IS_SHARED_SPACE
 
 
13
 
14
+ # Import functions from modules
15
+ from utils.file_utils import cleanup_temp_files
16
 
17
+ from utils.color_utils import (
18
+ rgb_to_hex,
19
+ hex_to_rgb,
20
+ detect_color_format,
21
+ update_color_opacity,
22
+ )
23
+ from utils.misc import (get_filename, pause, convert_ratio_to_dimensions)
24
+ from utils.depth_estimation import estimate_depth, create_3d_model, generate_depth_and_3d, generate_depth_button_click
25
 
26
+ from utils.image_utils import (
27
+ change_color,
28
+ open_image,
29
+ build_prerendered_images,
30
+ upscale_image,
31
+ lerp_imagemath,
32
+ shrink_and_paste_on_blank,
33
+ show_lut,
34
+ apply_lut_to_image_path,
35
+ multiply_and_blend_images,
36
+ alpha_composite_with_control
37
+ )
38
 
39
+ from utils.hex_grid import (
40
+ generate_hexagon_grid,
41
+ generate_hexagon_grid_interface,
42
+ )
43
 
44
+ from utils.excluded_colors import (
45
+ add_color,
46
+ delete_color,
47
+ build_dataframe,
48
+ on_input,
49
+ excluded_color_list,
50
+ on_color_display_select
51
+ )
52
+
53
+ from utils.ai_generator import (
54
+ generate_ai_image,
55
+ )
56
+ from utils.version_info import (
57
+ versions_html,
58
+ get_torch_info
59
+ )
60
+ from utils.lora_details import (
61
+ upd_prompt_notes
62
+ )
63
+
64
+ input_image_palette = []
65
+ current_prerendered_image = gr.State("./images/images/Beeuty-1.png")
66
+
67
+ # Register the cleanup function
68
+ atexit.register(cleanup_temp_files)
69
+
70
+ def hex_create(hex_size, border_size, input_image_path, start_x, start_y, end_x, end_y, rotation, background_color_hex, background_opacity, border_color_hex, border_opacity, fill_hex, excluded_colors_var, filter_color, x_spacing, y_spacing, add_hex_text_option=None, custom_text_list=None, custom_text_color_list=None):
71
+ global input_image_palette
72
+
73
+ try:
74
+ # Load and process the input image
75
+ input_image = Image.open(input_image_path).convert("RGBA")
76
+ except Exception as e:
77
+ print(f"Failed to convert image to RGBA: {e}")
78
+ # Open the original image without conversion
79
+ input_image = Image.open(input_image_path)
80
+ # Ensure the canvas is at least 1344x768 pixels
81
+ min_width, min_height = 1344, 768
82
+ canvas_width = max(min_width, input_image.width)
83
+ canvas_height = max(min_height, input_image.height)
84
+
85
+ # Create a transparent canvas with the required dimensions
86
+ new_canvas = Image.new("RGBA", (canvas_width, canvas_height), (0, 0, 0, 0))
87
+
88
+ # Calculate position to center the input image on the canvas
89
+ paste_x = (canvas_width - input_image.width) // 2
90
+ paste_y = (canvas_height - input_image.height) // 2
91
+
92
+ # Paste the input image onto the canvas
93
+ new_canvas.paste(input_image, (paste_x, paste_y))
94
+
95
+ # Save the 'RGBA' image to a temporary file and update 'input_image_path'
96
+ with NamedTemporaryFile(delete=False, suffix=".png") as tmp_file:
97
+ new_canvas.save(tmp_file.name, format="PNG")
98
+ input_image_path = tmp_file.name
99
+ constants.temp_files.append(tmp_file.name)
100
+
101
+ # Update 'input_image' with the new image as a file path
102
+ input_image = Image.open(input_image_path)
103
+
104
+ # Use Haishoku to get the palette from the new image
105
+ input_palette = Haishoku.loadHaishoku(input_image_path)
106
+ input_image_palette = input_palette.palette
107
+
108
+ # Update colors with opacity
109
+ background_color = update_color_opacity(
110
+ hex_to_rgb(background_color_hex),
111
+ int(background_opacity * (255 / 100))
112
+ )
113
+ border_color = update_color_opacity(
114
+ hex_to_rgb(border_color_hex),
115
+ int(border_opacity * (255 / 100))
116
+ )
117
+
118
+ # Prepare excluded colors list
119
+ excluded_color_list = [tuple(lst) for lst in excluded_colors_var]
120
+
121
+ # Generate the hexagon grid images
122
+ grid_image = generate_hexagon_grid_interface(
123
+ hex_size,
124
+ border_size,
125
+ input_image,
126
+ start_x,
127
+ start_y,
128
+ end_x,
129
+ end_y,
130
+ rotation,
131
+ background_color,
132
+ border_color,
133
+ fill_hex,
134
+ excluded_color_list,
135
+ filter_color,
136
+ x_spacing,
137
+ y_spacing,
138
+ add_hex_text_option,
139
+ custom_text_list,
140
+ custom_text_color_list
141
+ )
142
+
143
+ return grid_image
144
+
145
+ def get_model_and_lora(model_textbox):
146
+ """
147
+ Determines the model and LoRA weights based on the model_textbox input.
148
+ wieghts must be in an array ["Borcherding/FLUX.1-dev-LoRA-FractalLand-v0.1"]
149
+ """
150
+ # If the input is in the list of models, return it with None as LoRA weights
151
+ if model_textbox in constants.MODELS:
152
+ return model_textbox, []
153
+ # If the input is in the list of LoRA weights, get the corresponding model
154
+ elif model_textbox in constants.LORA_WEIGHTS:
155
+ model = constants.LORA_TO_MODEL.get(model_textbox)
156
+ return model, model_textbox.split()
157
+ else:
158
+ # Default to a known model if input is unrecognized
159
+ default_model = model_textbox
160
+ return default_model, []
161
 
162
  @spaces.GPU(duration=128)
163
+ def generate_input_image_click(map_option, prompt_textbox_value, negative_prompt_textbox_value, model_textbox_value, use_conditioned_image=False, strength=0.5, image_format="16:9", scale_factor=3):
164
+ # Get the model and LoRA weights
165
+ model, lora_weights = get_model_and_lora(model_textbox_value)
166
+ global current_prerendered_image
167
+ conditioned_image=None
168
+
169
+ if use_conditioned_image:
170
+ print(f"Conditioned path: {current_prerendered_image.value}.. converting to RGB\n")
171
+ # ensure the conditioned image is an image and not a string, cannot use RGBA
172
+ if isinstance(current_prerendered_image.value, str):
173
+ conditioned_image = open_image(current_prerendered_image.value).convert("RGB")
174
+ print(f"Conditioned Image: {conditioned_image.size}.. converted to RGB\n")
175
+
176
+ # Convert image_format from a string split by ":" into two numbers divided
177
+ width_ratio, height_ratio = map(int, image_format.split(":"))
178
+ aspect_ratio = width_ratio / height_ratio
179
+
180
+ width, height = convert_ratio_to_dimensions(aspect_ratio, 512)
181
+
182
+ # Generate the AI image and get the image path
183
+ image_path = generate_ai_image(
184
+ map_option,
185
+ prompt_textbox_value,
186
+ negative_prompt_textbox_value,
187
+ model,
188
+ lora_weights,
189
+ conditioned_image,
190
+ stength=strength,
191
  height=height,
192
+ width=width
193
+ )
194
+
195
+ # Open the generated image
196
+ try:
197
+ image = Image.open(image_path).convert("RGBA")
198
+ except Exception as e:
199
+ print(f"Failed to open generated image: {e}")
200
+ return image_path # Return the original image path if opening fails
201
+
202
+ # Upscale the image
203
+ upscaled_image = upscale_image(image, scale_factor)
204
+
205
+ # Save the upscaled image to a temporary file
206
+ with NamedTemporaryFile(delete=False, suffix=".png") as tmp_upscaled:
207
+ upscaled_image.save(tmp_upscaled.name, format="PNG")
208
+ constants.temp_files.append(tmp_upscaled.name)
209
+ print(f"Upscaled image saved to {tmp_upscaled.name}")
210
+
211
+ # Return the path of the upscaled image
212
+ return tmp_upscaled.name
213
 
214
+ def update_prompt_visibility(map_option):
215
+ is_visible = (map_option == "Prompt")
216
+ return (
217
+ gr.update(visible=is_visible),
218
+ gr.update(visible=is_visible),
219
+ gr.update(visible=is_visible)
220
+ )
221
 
222
+ def update_prompt_notes(model_textbox_value):
223
+ return upd_prompt_notes(model_textbox_value)
224
 
225
+ def on_prerendered_gallery_selection(event_data: gr.SelectData):
226
+ global current_prerendered_image
227
+ selected_index = event_data.index
228
+ selected_image = constants.pre_rendered_maps_paths[selected_index]
229
+ print(f"Gallery Image Selected: {selected_image}\n")
230
+ current_prerendered_image.value = selected_image
231
+ return current_prerendered_image
232
 
233
+ def combine_images_with_lerp(input_image, output_image, alpha):
234
+ in_image = open_image(input_image)
235
+ out_image = open_image(output_image)
236
+ print(f"Combining images with alpha: {alpha}")
237
+ return lerp_imagemath(in_image, out_image, alpha)
 
238
 
239
+ def add_border(image, mask_width, mask_height, blank_color):
240
+ bordered_image_output = Image.open(image).convert("RGBA")
241
+ margin_color = detect_color_format(blank_color)
242
+ print(f"Adding border to image with width: {mask_width}, height: {mask_height}, color: {margin_color}")
243
+ return shrink_and_paste_on_blank(bordered_image_output, mask_width, mask_height, margin_color)
244
 
245
+ title = "HexaGrid Creator"
246
+ description = "Customizable Hexagon Grid Image Generator"
247
+ examples = [["assets//examples//hex_map_p1.png", 32, 1, 0, 0, 0, 0, 0, "#ede9ac44","#12165380", True]]
 
 
 
 
 
248
 
249
+ gr.set_static_paths(paths=["images/","images/images","images/prerendered","LUT/","fonts/"])
250
+ # Gradio Blocks Interface
251
+ with gr.Blocks(css_paths="style_20250128.css", title="HexaGrid Creator", theme='Surn/beeuty') as beeuty:
252
+ with gr.Row():
253
+ gr.Markdown ("""
254
+ # HexaGrid Creator
255
+ ## Transform Your Images into Mesmerizing Hexagon Grid Masterpieces! ⬢
256
+ <details>
257
+ <summary>
258
+ Welcome to HexaGrid Creator, the ultimate tool for transforming your images into stunning hexagon grid artworks. Whether you're a tabletop game enthusiast, a digital artist, or someone who loves unique patterns, HexaGrid Creator has something for you.
259
 
260
+ ## Drop an image into the Input Image and get started!
261
 
262
+ </summary>
263
+
264
+ ## What is HexaGrid Creator?
265
+ HexaGrid Creator is a web-based application that allows you to apply a hexagon grid overlay to any image. You can customize the size, color, and opacity of the hexagons, as well as the background and border colors. The result is a visually striking image that looks like it was made from hexagonal tiles!
266
+
267
+ ### What Can You Do?
268
+ - **Generate Hexagon Grids:** Create beautiful hexagon grid overlays on any image with fully customizable parameters.
269
+ - **AI-Powered Image Generation:** Use advanced AI models to generate images based on your prompts and apply hexagon grids to them.
270
+ - **Color Exclusion:** Select and exclude specific colors from your hexagon grid for a cleaner and more refined look.
271
+ - **Interactive Customization:** Adjust hexagon size, border size, rotation, background color, and more in real-time.
272
+ - **Depth and 3D Model Generation:** Generate depth maps and 3D models from your images for enhanced visualization.
273
+ - **Image Filter [Look-Up Table (LUT)] Application:** Apply filters (LUTs) to your images for color grading and enhancement.
274
+ - **Pre-rendered Maps:** Access a library of pre-rendered hexagon maps for quick and easy customization.
275
+ - **Add Margins:** Add customizable margins around your images for a polished finish.
276
+
277
+ ### Why You'll Love It
278
+ - **Fun and Easy to Use:** With an intuitive interface and real-time previews, creating hexagon grids has never been this fun!
279
+ - **Endless Creativity:** Unleash your creativity with endless customization options and see your images transform in unique ways.
280
+ - **Hexagon-Inspired Theme:** Enjoy a delightful yellow and purple theme inspired by hexagons! ⬢
281
+ - **Advanced AI Models:** Leverage advanced AI models and LoRA weights for high-quality image generation and customization.
282
 
283
+ ### Get Started
284
+ 1. **Upload or Generate an Image:** Start by uploading your own image or generate one using our AI-powered tool.
285
+ 2. **Customize Your Grid:** Play around with the settings to create the perfect hexagon grid overlay.
286
+ 3. **Download and Share:** Once you're happy with your creation, download it and share it with the world!
287
+
288
+ ### Advanced Features
289
+ - **Generative AI Integration:** Utilize models like `black-forest-labs/FLUX.1-dev` and various LoRA weights for generating unique images.
290
+ - **Pre-rendered Maps:** Access a library of pre-rendered hexagon maps for quick and easy customization.
291
+ - **Image Filter [Look-Up Table (LUT)] Application:** Apply filters (LUTs) to your images for color grading and enhancement.
292
+ - **Depth and 3D Model Generation:** Create depth maps and 3D models from your images for enhanced visualization.
293
+ - **Add Margins:** Customize margins around your images for a polished finish.
294
+
295
+ Join the hive and start creating with HexaGrid Creator today!
296
+ </details>
297
+ """, elem_classes="intro")
298
+ with gr.Row():
299
+ with gr.Column(scale=2):
300
+ input_image = gr.Image(
301
+ label="Input Image",
302
+ type="filepath",
303
+ interactive=True,
304
+ elem_classes="centered solid imgcontainer",
305
+ key="imgInput",
306
+ image_mode="RGBA",
307
+ format="PNG"
308
  )
309
+ with gr.Column():
310
+ with gr.Accordion("Hex Coloring and Exclusion", open = False):
311
+ with gr.Row():
312
+ with gr.Column():
313
+ color_picker = gr.ColorPicker(label="Pick a color to exclude",value="#505050")
314
+ with gr.Column():
315
+ filter_color = gr.Checkbox(label="Filter Excluded Colors from Sampling", value=False,)
316
+ exclude_color_button = gr.Button("Exclude Color", elem_id="exlude_color_button", elem_classes="solid")
317
+ color_display = gr.DataFrame(label="List of Excluded RGBA Colors", headers=["R", "G", "B", "A"], elem_id="excluded_colors", type="array", value=build_dataframe(excluded_color_list), interactive=True, elem_classes="solid centered")
318
+ selected_row = gr.Number(0, label="Selected Row", visible=False)
319
+ delete_button = gr.Button("Delete Row", elem_id="delete_exclusion_button", elem_classes="solid")
320
+ fill_hex = gr.Checkbox(label="Fill Hex with color from Image", value=True)
321
+ with gr.Accordion("Image Filters", open = False):
322
+ with gr.Row():
323
+ with gr.Column():
324
+ composite_color = gr.ColorPicker(label="Color", value="#ede9ac44")
325
+ with gr.Column():
326
+ composite_opacity = gr.Slider(label="Opacity %", minimum=0, maximum=100, value=50, interactive=True)
327
+ with gr.Row():
328
+ composite_button = gr.Button("Composite", elem_classes="solid")
329
+ with gr.Row():
330
+ with gr.Column():
331
+ lut_filename = gr.Textbox(
332
+ value="",
333
+ label="Look Up Table (LUT) File Name",
334
+ elem_id="lutFileName")
335
+ with gr.Column():
336
+ lut_file = gr.File(
337
+ value=None,
338
+ file_count="single",
339
+ file_types=[".cube"],
340
+ type="filepath",
341
+ label="LUT cube File")
342
+ with gr.Row():
343
+ lut_example_image = gr.Image(type="pil", label="Filter (LUT) Example Image", value=constants.default_lut_example_img)
344
+ with gr.Row():
345
+ with gr.Column():
346
+ gr.Markdown("""
347
+ ### Included Filters (LUTs)
348
+ There are several included Filters:
349
 
350
+ Try them on the example image before applying to your Input Image.
351
+ """, elem_id="lut_markdown")
352
+ with gr.Column():
353
+ gr.Examples(elem_id="lut_examples",
354
+ examples=[[f] for f in constants.lut_files],
355
+ inputs=[lut_filename],
356
+ outputs=[lut_filename],
357
+ label="Select a Filter (LUT) file. Populate the LUT File Name field"
358
+ )
359
+
360
+ with gr.Row():
361
+ apply_lut_button = gr.Button("Apply Filter (LUT)", elem_classes="solid", elem_id="apply_lut_button")
362
+
363
+ lut_file.change(get_filename, inputs=[lut_file], outputs=[lut_filename])
364
+ lut_filename.change(show_lut, inputs=[lut_filename, lut_example_image], outputs=[lut_example_image])
365
+ apply_lut_button.click(apply_lut_to_image_path, inputs=[lut_filename, input_image], outputs=[input_image],scroll_to_output=True)
366
 
367
+ with gr.Row():
368
+ with gr.Accordion("Generative AI", open = False):
369
  with gr.Row():
370
+ with gr.Column():
371
+ model_options = gr.Dropdown(
372
+ label="Model Options",
373
+ choices=constants.MODELS + constants.LORA_WEIGHTS + ["Manual Entry"],
374
+ value="Cossale/Frames2-Flex.1",
375
+ elem_classes="solid"
376
+ )
377
+ model_textbox = gr.Textbox(
378
+ label="LORA/Model",
379
+ value="Cossale/Frames2-Flex.1",
380
+ elem_classes="solid",
381
+ elem_id="inference_model",
382
+ visible=False
383
+ )
384
+ # Update map_options to a Dropdown with choices from constants.PROMPTS keys
385
+ with gr.Row():
386
+ with gr.Column():
387
+ map_options = gr.Dropdown(
388
+ label="Map Options",
389
+ choices=list(constants.PROMPTS.keys()),
390
+ value="Alien Landscape",
391
+ elem_classes="solid"
392
+ )
393
+ with gr.Column():
394
+ # Add Dropdown for sizing of Images, height and width based on selection. Options are 16x9, 16x10, 4x5, 1x1
395
+ # The values of height and width are based on common resolutions for each aspect ratio
396
+ # Default to 16x9, 912x512
397
+ image_size_ratio = gr.Dropdown(label="Image Size", choices=["16:9", "16:10", "4:5", "4:3", "2:1","3:2","1:1", "9:16", "10:16", "5:4", "3:4","1:2", "2:3"], value="16:9", elem_classes="solid", type="value",interactive=True)
398
+ prompt_textbox = gr.Textbox(
399
+ label="Prompt",
400
+ visible=False,
401
+ elem_classes="solid",
402
+ value="top-down, (tabletop_map built from small hexagon pieces) hexagon map of a Battletech_boardgame forest with lakes, forest, magic fauna, and snow at the top and bottom, (middle is dark, no_reflections, no_shadows) , tall and short hexagon tiles. Viewed from above.",
403
+ lines=4
404
+ )
405
+ negative_prompt_textbox = gr.Textbox(
406
+ label="Negative Prompt",
407
+ visible=False,
408
+ elem_classes="solid",
409
+ value="low quality, bad anatomy, blurry, cropped, worst quality, shadows, people, humans, reflections, shadows, realistic map of the Earth, isometric, text"
410
+ )
411
+ prompt_notes_label = gr.Label(
412
+ "You should use FRM$ as trigger words. @1.5 minutes",
413
+ elem_classes="solid centered small",
414
+ show_label=False,
415
+ visible=False
416
+ )
417
+ # Keep the change event to maintain functionality
418
+ map_options.change(
419
+ fn=update_prompt_visibility,
420
+ inputs=[map_options],
421
+ outputs=[prompt_textbox, negative_prompt_textbox, prompt_notes_label]
422
+ )
423
+ with gr.Row():
424
+ generate_input_image = gr.Button(
425
+ "Generate AI Image",
426
+ elem_id="generate_input_image",
427
+ elem_classes="solid"
428
+ )
429
+ with gr.Column(scale=2):
430
+ with gr.Accordion("Template Image Styles", open = False):
431
+ with gr.Row():
432
+ # Gallery from PRE_RENDERED_IMAGES GOES HERE
433
+ prerendered_image_gallery = gr.Gallery(label="Image Gallery", show_label=True, value=build_prerendered_images(constants.pre_rendered_maps_paths), elem_id="gallery", elem_classes="solid", type="filepath", columns=[3], rows=[3], preview=False ,object_fit="contain", height="auto",file_types=["image"], format="png",allow_preview=False)
434
+ with gr.Row():
435
+ image_guidance_stength = gr.Slider(label="Image Guidance Strength", minimum=0, maximum=1.0, value=0.5, step=0.05, interactive=True)
436
+ with gr.Column():
437
+ replace_input_image_button = gr.Button(
438
+ "Replace Input Image",
439
+ elem_id="prerendered_replace_input_image_button",
440
+ elem_classes="solid"
441
+ )
442
+ with gr.Column():
443
+ generate_input_image_from_gallery = gr.Button(
444
+ "Generate AI Image from Gallery",
445
+ elem_id="generate_input_image_from_gallery",
446
+ elem_classes="solid"
447
+ )
448
 
449
+ with gr.Accordion("Advanced Hexagon Settings", open = False):
450
+ with gr.Row():
451
+ start_x = gr.Number(label="Start X", value=0, minimum=-512, maximum= 512, precision=0)
452
+ start_y = gr.Number(label="Start Y", value=0, minimum=-512, maximum= 512, precision=0)
453
+ end_x = gr.Number(label="End X", value=0, minimum=-512, maximum= 512, precision=0)
454
+ end_y = gr.Number(label="End Y", value=0, minimum=-512, maximum= 512, precision=0)
455
+ with gr.Row():
456
+ x_spacing = gr.Number(label="Adjust Horizontal spacing", value=-1, minimum=-200, maximum=200, precision=1)
457
+ y_spacing = gr.Number(label="Adjust Vertical spacing", value=1, minimum=-200, maximum=200, precision=1)
458
+ with gr.Row():
459
+ rotation = gr.Slider(-90, 180, 0.0, 0.1, label="Hexagon Rotation (degree)")
460
+ add_hex_text = gr.Dropdown(label="Add Text to Hexagons", choices=[None, "Row-Column Coordinates", "Sequential Numbers", "Playing Cards Sequential", "Playing Cards Alternate Red and Black", "Custom List"], value=None)
461
+ with gr.Row():
462
+ custom_text_list = gr.TextArea(label="Custom Text List", value=constants.cards_alternating, visible=False,)
463
+ custom_text_color_list = gr.TextArea(label="Custom Text Color List", value=constants.card_colors_alternating, visible=False)
464
+ with gr.Row():
465
+ hex_text_info = gr.Markdown("""
466
+ ### Text Color uses the Border Color and Border Opacity, unless you use a custom list.
467
+ ### The Custom Text List and Custom Text Color List are comma separated lists.
468
+ ### The custom color list is a comma separated list of hex colors.
469
+ #### Example: "A,2,3,4,5,6,7,8,9,10,J,Q,K", "red,#0000FF,#00FF00,red,#FFFF00,#00FFFF,#FF8000,#FF00FF,#FF0080,#FF8000,#FF0080,lightblue"
470
+ """, elem_id="hex_text_info", visible=False)
471
+ add_hex_text.change(
472
+ fn=lambda x: (
473
+ gr.update(visible=(x == "Custom List")),
474
+ gr.update(visible=(x == "Custom List")),
475
+ gr.update(visible=(x != None))
476
+ ),
477
+ inputs=add_hex_text,
478
+ outputs=[custom_text_list, custom_text_color_list, hex_text_info]
479
+ )
480
+ with gr.Row():
481
+ hex_size = gr.Number(label="Hexagon Size", value=32, minimum=1, maximum=768)
482
+ border_size = gr.Slider(-5,25,value=0,step=1,label="Border Size")
483
+ with gr.Row():
484
+ background_color = gr.ColorPicker(label="Background Color", value="#000000", interactive=True)
485
+ background_opacity = gr.Slider(0,100,0,1,label="Background Opacity %")
486
+ border_color = gr.ColorPicker(label="Border Color", value="#7b7b7b", interactive=True)
487
+ border_opacity = gr.Slider(0,100,0,1,label="Border Opacity %")
488
+ with gr.Row():
489
+ hex_button = gr.Button("Generate Hex Grid!", elem_classes="solid", elem_id="btn-generate")
490
+ with gr.Row():
491
+ output_image = gr.Image(label="Hexagon Grid Image", image_mode = "RGBA", show_download_button=True, show_share_button=True,elem_classes="centered solid imgcontainer", format="PNG", type="filepath", key="ImgOutput")
492
+ overlay_image = gr.Image(label="Hexagon Overlay Image", image_mode = "RGBA", show_share_button=True, elem_classes="centered solid imgcontainer", format="PNG", type="filepath", key="ImgOverlay")
493
+ with gr.Row():
494
+ output_overlay_composite = gr.Slider(0,100,50,0.5, label="Interpolate Intensity")
495
+ output_blend_multiply_composite = gr.Slider(0,100,50,0.5, label="Overlay Intensity")
496
+ output_alpha_composite = gr.Slider(0,100,50,0.5, label="Alpha Composite Intensity")
497
+ with gr.Accordion("Add Margins (bleed)", open=False):
498
+ with gr.Row():
499
+ border_image_source = gr.Radio(label="Add Margins around which Image", choices=["Input Image", "Overlay Image"], value="Overlay Image")
500
+ with gr.Row():
501
+ mask_width = gr.Number(label="Margins Width", value=10, minimum=0, maximum=100, precision=0)
502
+ mask_height = gr.Number(label="Margins Height", value=10, minimum=0, maximum=100, precision=0)
503
+ with gr.Row():
504
+ margin_color = gr.ColorPicker(label="Margin Color", value="#333333FF", interactive=True)
505
+ margin_opacity = gr.Slider(0,100,95,0.5,label="Margin Opacity %")
506
+ with gr.Row():
507
+ add_border_button = gr.Button("Add Margins", elem_classes="solid", variant="secondary")
508
+ with gr.Row():
509
+ bordered_image_output = gr.Image(label="Image with Margins", image_mode="RGBA", show_download_button=True, show_share_button=True, elem_classes="centered solid imgcontainer", format="PNG", type="filepath", key="ImgBordered")
510
+
511
+ with gr.Accordion("Height Maps and 3D", open = False):
512
+ with gr.Row():
513
+ with gr.Column():
514
+ voxel_size_factor = gr.Slider(label="Voxel Size Factor", value=1.00, minimum=0.01, maximum=40.00, step=0.01)
515
+ with gr.Column():
516
+ depth_image_source = gr.Radio(label="Depth Image Source", choices=["Input Image", "Output Image", "Overlay Image","Image with Margins"], value="Input Image")
517
+ with gr.Row():
518
+ generate_depth_button = gr.Button("Generate Depth Map and 3D Model From Selected Image", elem_classes="solid", variant="secondary")
519
+ with gr.Row():
520
+ depth_map_output = gr.Image(label="Depth Map", image_mode="L", elem_classes="centered solid imgcontainer", format="PNG", type="filepath", key="ImgDepth")
521
+ model_output = gr.Model3D(label="3D Model", clear_color=[1.0, 1.0, 1.0, 0.25], key="Img3D", elem_classes="centered solid imgcontainer")
522
+ with gr.Row():
523
+ gr.Examples(examples=[
524
+ ["assets//examples//hex_map_p1.png", False, True, -32,-31,80,80,-1.8,0,35,0,1,"#FFD0D0", 15],
525
+ ["assets//examples//hex_map_p1_overlayed.png", False, False, -32,-31,80,80,-1.8,0,35,0,1,"#FFD0D0", 75],
526
+ ["assets//examples//hex_flower_logo.png", False, True, -95,-95,100,100,-24,-2,190,30,2,"#FF8951", 50],
527
+ ["assets//examples//hexed_fract_1.png", False, True, 0,0,0,0,0,0,10,0,0,"#000000", 5],
528
+ ["assets//examples//tmpzt3mblvk.png", False, True, -20,10,0,0,-6,-2,35,30,1,"#ffffff", 0],
529
+ ],
530
+ inputs=[input_image, filter_color, fill_hex, start_x, start_y, end_x, end_y, x_spacing, y_spacing, hex_size, rotation, border_size, border_color, border_opacity],
531
+ elem_id="examples")
532
+ with gr.Row():
533
+ gr.HTML(value=versions_html(), visible=True, elem_id="versions")
534
+
535
+ color_display.select(on_color_display_select,inputs=[color_display], outputs=[selected_row])
536
+ color_display.input(on_input,inputs=[color_display], outputs=[color_display, gr.State(excluded_color_list)])
537
+
538
+ delete_button.click(fn=delete_color, inputs=[selected_row, color_display], outputs=[color_display])
539
+ exclude_color_button.click(fn=add_color, inputs=[color_picker, gr.State(excluded_color_list)], outputs=[color_display, gr.State(excluded_color_list)])
540
+ hex_button.click(hex_create, inputs=[hex_size, border_size, input_image, start_x, start_y, end_x, end_y, rotation, background_color, background_opacity, border_color, border_opacity, fill_hex, color_display, filter_color, x_spacing, y_spacing, add_hex_text, custom_text_list, custom_text_color_list], outputs=[output_image, overlay_image], scroll_to_output=True)
541
+ generate_input_image.click(
542
+ fn=generate_input_image_click,
543
+ inputs=[map_options, prompt_textbox, negative_prompt_textbox, model_textbox, gr.State(False), gr.State(0.5), image_size_ratio],
544
+ outputs=[input_image], scroll_to_output=True
545
+ )
546
+ generate_depth_button.click(
547
+ fn=generate_depth_button_click,
548
+ inputs=[depth_image_source, voxel_size_factor, input_image, output_image, overlay_image, bordered_image_output],
549
+ outputs=[depth_map_output, model_output], scroll_to_output=True
550
+ )
551
+ model_textbox.change(
552
+ fn=update_prompt_notes,
553
+ inputs=model_textbox,
554
+ outputs=prompt_notes_label,preprocess=False
555
+ )
556
+ model_options.change(
557
+ fn=lambda x: (gr.update(visible=(x == "Manual Entry")), gr.update(value=x) if x != "Manual Entry" else gr.update()),
558
+ inputs=model_options,
559
+ outputs=[model_textbox, model_textbox]
560
+ )
561
+ model_options.change(
562
+ fn=update_prompt_notes,
563
+ inputs=model_options,
564
+ outputs=prompt_notes_label
565
+ )
566
+ composite_button.click(
567
+ fn=change_color,
568
+ inputs=[input_image, composite_color, composite_opacity],
569
+ outputs=[input_image]
570
+ )
571
+
572
+ #use conditioned_image as the input_image for generate_input_image_click
573
+ generate_input_image_from_gallery.click(
574
+ fn=generate_input_image_click,
575
+ inputs=[map_options, prompt_textbox, negative_prompt_textbox, model_textbox, gr.State(True), image_guidance_stength, image_size_ratio],
576
+ outputs=[input_image], scroll_to_output=True
577
  )
578
 
579
+ # Update the state variable with the prerendered image filepath when an image is selected
580
+ prerendered_image_gallery.select(
581
+ fn=on_prerendered_gallery_selection,
582
+ inputs=None,
583
+ outputs=[gr.State(current_prerendered_image)], # Update the state with the selected image
584
+ show_api=False
585
+ )
586
+ # replace input image with selected gallery image
587
+ replace_input_image_button.click(
588
+ lambda: current_prerendered_image.value,
589
+ inputs=None,
590
+ outputs=[input_image], scroll_to_output=True
591
+ )
592
+ output_overlay_composite.change(
593
+ fn=combine_images_with_lerp,
594
+ inputs=[input_image, output_image, output_overlay_composite],
595
+ outputs=[overlay_image], scroll_to_output=True
596
+ )
597
+ output_blend_multiply_composite.change(
598
+ fn=multiply_and_blend_images,
599
+ inputs=[input_image, output_image, output_blend_multiply_composite],
600
+ outputs=[overlay_image],
601
+ scroll_to_output=True
602
+ )
603
+ output_alpha_composite.change(
604
+ fn=alpha_composite_with_control,
605
+ inputs=[input_image, output_image, output_alpha_composite],
606
+ outputs=[overlay_image],
607
+ scroll_to_output=True
608
+ )
609
+ add_border_button.click(
610
+ fn=lambda image_source, mask_w, mask_h, color, opacity, input_img, overlay_img: add_border(input_img if image_source == "Input Image" else overlay_img, mask_w, mask_h, update_color_opacity(detect_color_format(color), opacity * 2.55)),
611
+ inputs=[border_image_source, mask_width, mask_height, margin_color, margin_opacity, input_image, overlay_image],
612
+ outputs=[bordered_image_output],
613
+ scroll_to_output=True
614
+ )
615
+ (())
616
  if __name__ == "__main__":
617
+ beeuty.queue(default_concurrency_limit=1,max_size=12,api_open=False)
618
+ beeuty.launch(allowed_paths=["assets","/","./assets","images","./images", "./images/prerendered"], favicon_path="./assets/favicon.ico", max_file_size="10mb")
requirements.txt CHANGED
@@ -14,11 +14,12 @@ huggingface_hub
14
  transformers==4.48.1
15
  gradio==5.12.0
16
  gradio[oauth]
17
- pillow
18
  numpy==1.26.4
19
  requests
20
  # git+https://github.com/huggingface/diffusers[torch]
21
  diffusers[torch]==0.32.2
 
22
  peft
23
  opencv-python
24
  open3d
@@ -30,4 +31,8 @@ git+https://github.com/asomoza/image_gen_aux.git
30
  # git+https://github.com/triton-lang/triton.git -not windows supported --disable in environment variable
31
  tiktoken
32
  pilmoji[requests]==2.0.4
33
- emoji==2.2.0
 
 
 
 
 
14
  transformers==4.48.1
15
  gradio==5.12.0
16
  gradio[oauth]
17
+ Pillow
18
  numpy==1.26.4
19
  requests
20
  # git+https://github.com/huggingface/diffusers[torch]
21
  diffusers[torch]==0.32.2
22
+ accelerate
23
  peft
24
  opencv-python
25
  open3d
 
31
  # git+https://github.com/triton-lang/triton.git -not windows supported --disable in environment variable
32
  tiktoken
33
  pilmoji[requests]==2.0.4
34
+ emoji==2.2.0
35
+ pycairo
36
+ cairocffi
37
+ pangocffi
38
+ pangocairocffi