File size: 25,137 Bytes
31931d9
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
6ef117e
31931d9
 
 
 
 
 
 
 
6ef117e
31931d9
 
 
 
6ef117e
 
31931d9
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
6ef117e
 
31931d9
 
 
6ef117e
31931d9
 
 
 
 
 
 
 
 
 
 
 
 
 
 
6ef117e
31931d9
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
# utils/hex_grid.py
import os
import math
from PIL import Image
import cairocffi as cairo
import pangocffi
import pangocairocffi
from PIL import Image, ImageDraw, ImageChops, ImageFont #, ImageColor
#from pilmoji import Pilmoji  # Import Pilmoji for handling emojis
from utils.excluded_colors import (
    excluded_color_list,
)
from utils.image_utils import multiply_and_blend_images
from utils.color_utils import update_color_opacity, parse_hex_color, draw_text_with_emojis, hex_to_rgb
import random  # For random text options
import utils.constants as constants  # Import constants
import ast

def calculate_font_size(hex_size, padding=0.6, size_ceil=20, min_font_size=8):
    """
    Calculate the font size based on the hexagon size.

    Parameters:
        hex_size (int): The size of the hexagon side.
        padding (float): The fraction of the hex size to use for font size.

    Returns:
        int or None: The calculated font size or None if hex is too small.
    """
    font_size = int(hex_size * padding)
    if font_size < min_font_size:
        return None  # Hex is too small for text
    return min(font_size, size_ceil)

def generate_hexagon_grid(hex_size, border_size, input_image=None, image_width=0, image_height=0, start_x=0, start_y=0, end_x=0, end_y=0, rotation=0, background_color="#ede9ac44", border_color="#12165380", fill_hex=True, excluded_color_list=excluded_color_list, filter_color=False, x_spacing=0, y_spacing=0):
    if input_image:
        image_width, image_height = input_image.size
    # Use half hex_size, thus do not double border size
    # Calculate the dimensions of the grid before rotation
    if rotation != 0:
        # Calculate rotated dimensions
        # modified to rotate input image and process to reduce calculation errors at edge conditions
        rotated_input_image = input_image.rotate(rotation, expand=True)
        rotated_image_width, rotated_image_height = rotated_input_image.size
        #rotated_image_height = abs(math.ceil((image_height ) * math.sin(math.radians(90 - rotation)) + (image_width ) * math.cos(math.radians(90 - rotation))))
        #rotated_image_width = abs(math.ceil((image_width ) * math.sin(math.radians(90 - rotation)) + (image_height ) * math.cos(math.radians(90 - rotation))))
        # Adjust hexagon size, spacing adjustments and border for rotation
        hex_size = abs(math.ceil((hex_size // 2) * math.sin(math.radians(90 - abs(rotation))) + (hex_size // 2) * math.cos(math.radians(90 - abs(rotation)))))
        hex_border_size = math.ceil(border_size * math.sin(math.radians(90 - abs(rotation))) + border_size * math.cos(math.radians(90 - abs(rotation))))
        x_spacing = math.ceil(x_spacing * math.sin(math.radians(90 - abs(rotation))) + x_spacing * math.cos(math.radians(90 - abs(rotation))))
        y_spacing = math.ceil(y_spacing * math.sin(math.radians(90 - abs(rotation))) + y_spacing * math.cos(math.radians(90 - abs(rotation))))
        # Calculate additional width and height due to rotation
        additional_width = rotated_image_width - image_width
        additional_height = rotated_image_height - image_height
        #rotated_input_image.show()
    else:
        rotated_input_image = input_image
        rotated_image_width = image_width 
        rotated_image_height = image_height
        hex_size = hex_size // 2
        hex_border_size = border_size
        additional_width = 0
        additional_height = 0
    # Create a new image with white background (adjusted for rotation)
    image = Image.new("RGBA", (rotated_image_width, rotated_image_height), background_color)
    draw = ImageDraw.Draw(image, mode="RGBA")
    hex_width = hex_size * 2
    hex_height = hex_size * 2
    hex_horizontal_spacing = (hex_width ) + (hex_border_size if hex_border_size < 0 else 0) + x_spacing #* 0.8660254
    hex_vertical_spacing = hex_height + (hex_border_size if hex_border_size < 0 else 0) + y_spacing
    col = 0
    row = 0
    def draw_hexagon(x, y, color="#FFFFFFFF", rotation=0, outline_color="#12165380", outline_width=0, sides=6):
        side_length = (hex_size * 2) / math.sqrt(3)
        points = [(x + side_length * math.cos(math.radians(angle + rotation)), y + side_length * math.sin(math.radians(angle + rotation))) for angle in range(0, 360, (360 // sides))]
        draw.polygon(points, fill=color, outline=outline_color, width=max(-5, outline_width))
    # Function to range a floating number
    def frange(start, stop, step):
        i = start
        while i < stop:
            yield i
            i += step
    # Draw hexagons 
    for y in frange(start_y, max(image_height + additional_height, image_height, rotated_image_height) + (end_y - start_y), hex_vertical_spacing):
        row += 1
        col = 0 
        for x in frange(start_x, max(image_width + additional_width, image_width, rotated_image_width) + (end_x - start_x), hex_horizontal_spacing):
            col += 1
            x_offset = hex_width // 2
            y_offset = (hex_height // 2) #* 1.15470054342517
            # Adjust y_offset for columns 1 and 3 to overlap
            if col % 2 == 1:
                y_offset -= (hex_height // 2) #* 0.8660254
            if rotated_input_image:
                # Sample the colors of the pixels in the hexagon, if fill_hex is True
                if fill_hex:
                    sample_size = max(2, math.ceil(math.sqrt(hex_size)))
                    sample_x = int(x + x_offset)
                    sample_y = int(y + y_offset)
                    sample_colors = []
                    for i in range(-sample_size // 2, sample_size // 2 + 1):
                        for j in range(-sample_size // 2, sample_size // 2 + 1):
                            print(f"    Progress : {str(min(rotated_image_width - 1,max(1,sample_x + i)))}  {str(min(rotated_image_height - 1,max(1,sample_y + j)))}", end="\r")
                            sample_colors.append(rotated_input_image.getpixel((min(rotated_image_width - 1,max(1,sample_x + i)), min(rotated_image_height - 1,max(1,sample_y + j)))))
                    if filter_color:
                        # Filter out the excluded colors
                        filtered_colors = [color for color in sample_colors if color not in excluded_color_list]
                        # Ensure there are colors left after filtering
                        if filtered_colors:
                            # Calculate the average color of the filtered colors
                            avg_color = tuple(int(sum(channel) / len(filtered_colors)) for channel in zip(*filtered_colors))
                        else:
                            avg_color = excluded_color_list[0] if excluded_color_list else (0,0,0,0)
                    else:
                        avg_color = tuple(int(sum(channel) / len(sample_colors)) for channel in zip(*sample_colors))
                    if avg_color in excluded_color_list:
                        print(f"color excluded: {avg_color}")
                        avg_color = (0,0,0,0)
                    else:
                        print(f"color found: {avg_color}")
                        #draw_hexagon(x + x_offset, y + y_offset, color="#{:02x}{:02x}{:02x}{:02x}".format(*avg_color if fill_hex else (0,0,0,0)), outline_color=border_color, outline_width=hex_border_size)
                        draw_hexagon(x + x_offset, y + y_offset, color="#{:02x}{:02x}{:02x}{:02x}".format(*avg_color), outline_color=border_color, outline_width=hex_border_size)
                else:
                    draw_hexagon(x + x_offset, y + y_offset, color="#000000", outline_color=border_color, outline_width=hex_border_size)
            else:
                color = "#%02x%02x%02x%02x" % (128, math.ceil(y) % 255, math.ceil(x) % 255, 255) if fill_hex else (0,0,0,0)
                draw_hexagon(x + x_offset, y + y_offset, color=color, outline_color=border_color, outline_width=hex_border_size)
    if rotation != 0:
        #image.show()
        # Rotate the final image
        rotated_image = image.rotate(-rotation, expand=True)
        #rotated_image.show()
        bbox = rotated_image.split()[3].getbbox(False)
        if bbox:
            final_image = rotated_image.crop(bbox).resize((image_width,image_height))
        else:
            final_image = rotated_image.resize((image_width,image_height))
    else:
        final_image = image
    return final_image

def generate_hexagon_grid_with_text(hex_size, border_size, input_image=None, image_width=0, image_height=0, start_x=0, start_y=0, end_x=0, end_y=0, rotation=0, background_color="#ede9ac44", border_color="#12165380", fill_hex=True, excluded_color_list=excluded_color_list, filter_color=False, x_spacing=0, y_spacing=0, 
        add_hex_text_option=None, custom_text_list=None, custom_text_color_list=None):

    if input_image:
        image_width, image_height = input_image.size
    # Use half hex_size, thus do not double border size
    # Calculate the dimensions of the grid before rotation
    if rotation != 0:
        # Calculate rotated dimensions
        # modified to rotate input image and process to reduce calculation errors at edge conditions
        rotated_input_image = input_image.rotate(rotation, expand=True)
        rotated_image_width, rotated_image_height = rotated_input_image.size
        #rotated_image_height = abs(math.ceil((image_height ) * math.sin(math.radians(90 - rotation)) + (image_width ) * math.cos(math.radians(90 - rotation))))
        #rotated_image_width = abs(math.ceil((image_width ) * math.sin(math.radians(90 - rotation)) + (image_height ) * math.cos(math.radians(90 - rotation))))
        # Adjust hexagon size, spacing adjustments and border for rotation
        hex_size = abs(math.ceil((hex_size // 2) * math.sin(math.radians(90 - abs(rotation))) + (hex_size // 2) * math.cos(math.radians(90 - abs(rotation)))))
        hex_border_size = math.ceil(border_size * math.sin(math.radians(90 - abs(rotation))) + border_size * math.cos(math.radians(90 - abs(rotation))))
        x_spacing = math.ceil(x_spacing * math.sin(math.radians(90 - abs(rotation))) + x_spacing * math.cos(math.radians(90 - abs(rotation))))
        y_spacing = math.ceil(y_spacing * math.sin(math.radians(90 - abs(rotation))) + y_spacing * math.cos(math.radians(90 - abs(rotation))))
        # Calculate additional width and height due to rotation
        additional_width = rotated_image_width - image_width
        additional_height = rotated_image_height - image_height
        #rotated_input_image.show()
    else:
        rotated_input_image = input_image
        rotated_image_width = image_width 
        rotated_image_height = image_height
        hex_size = hex_size // 2
        hex_border_size = border_size
        additional_width = 0
        additional_height = 0
    # Create a new image with white background (adjusted for rotation)
    image = Image.new("RGBA", (rotated_image_width, rotated_image_height), background_color)
    font_image = Image.new("RGBA", (rotated_image_width, rotated_image_height), (0,0,0,0))
    draw = ImageDraw.Draw(image, mode="RGBA")
    hex_width = hex_size * 2
    hex_height = hex_size * 2
    hex_horizontal_spacing = (hex_width ) + (hex_border_size if hex_border_size < 0 else 0) + x_spacing #* 0.8660254
    hex_vertical_spacing = hex_height + (hex_border_size if hex_border_size < 0 else 0) + y_spacing
    col = 0
    row = 0
    ## Function to draw optional text
    if add_hex_text_option != "None":
        # Load the emoji font
        font_name = "Segoe UI Emoji"
        if os.name == 'nt':  # Windows
            font_path = "./fonts/seguiemj.ttf"
        else:  # Other OS (Linux, macOS, etc.)
            font_path = "./fonts/seguiemj.ttf"
        if not os.path.exists(font_path):
            raise FileNotFoundError("Emoji font not found in './fonts' directory.")
        # Prepare the text and color lists
        text_list = []
        color_list = []
        if add_hex_text_option == "Playing Cards Sequential":
            text_list = constants.cards
            color_list = constants.card_colors
        elif add_hex_text_option == "Playing Cards Alternate Red and Black":
            text_list = constants.cards_alternating
            color_list = constants.card_colors_alternating
        elif add_hex_text_option == "Custom List":
            if custom_text_list:
                #text_list = [text.strip() for text in custom_text_list.split(",")]
                text_list = ast.literal_eval(custom_text_list) if custom_text_list else None
            if custom_text_color_list:
                #color_list = [color.strip() for color in custom_text_color_list.split(",")]
                color_list = ast.literal_eval(custom_text_color_list) if custom_text_color_list else None
        else:
            # Coordinates will be generated dynamically
            pass
    hex_index = -1  # Initialize hex index
    def draw_hexagon(x, y, color="#FFFFFFFF", rotation=0, outline_color="#12165380", outline_width=0, sides=6):
        side_length = (hex_size * 2) / math.sqrt(3)
        points = [(x + side_length * math.cos(math.radians(angle + rotation)), y + side_length * math.sin(math.radians(angle + rotation))) for angle in range(0, 360, (360 // sides))]
        draw.polygon(points, fill=color, outline=outline_color, width=max(-5, outline_width))
    # Function to range a floating number
    def frange(start, stop, step):
        i = start
        while i < stop:
            yield i
            i += step
    # Draw hexagons 
    for y in frange(start_y, max(image_height + additional_height, image_height, rotated_image_height) + (end_y - start_y), hex_vertical_spacing):
        row += 1
        col = 0 
        for x in frange(start_x, max(image_width + additional_width, image_width, rotated_image_width) + (end_x - start_x), hex_horizontal_spacing):
            col += 1
            hex_index += 1  # Increment hex index
            x_offset = hex_width // 2
            y_offset = (hex_height // 2) #* 1.15470054342517
            # Adjust y_offset for columns 1 and 3 to overlap
            if col % 2 == 1:
                y_offset -= (hex_height // 2) #* 0.8660254
            if rotated_input_image:
                # Sample the colors of the pixels in the hexagon, if fill_hex is True
                if fill_hex:
                    sample_size = max(2, math.ceil(math.sqrt(hex_size)))
                    sample_x = int(x + x_offset)
                    sample_y = int(y + y_offset)
                    sample_colors = []
                    for i in range(-sample_size // 2, sample_size // 2 + 1):
                        for j in range(-sample_size // 2, sample_size // 2 + 1):
                            print(f"    Progress : {str(min(rotated_image_width - 1,max(1,sample_x + i)))}  {str(min(rotated_image_height - 1,max(1,sample_y + j)))}", end="\r")
                            sample_colors.append(rotated_input_image.getpixel((min(rotated_image_width - 1,max(1,sample_x + i)), min(rotated_image_height - 1,max(1,sample_y + j)))))
                    if filter_color:
                        # Filter out the excluded colors
                        filtered_colors = [color for color in sample_colors if color not in excluded_color_list]
                        # Ensure there are colors left after filtering
                        if filtered_colors:
                            # Calculate the average color of the filtered colors
                            avg_color = tuple(int(sum(channel) / len(filtered_colors)) for channel in zip(*filtered_colors))
                        else:
                            avg_color = excluded_color_list[0] if excluded_color_list else (0,0,0,0)
                    else:
                        avg_color = tuple(int(sum(channel) / len(sample_colors)) for channel in zip(*sample_colors))
                    if avg_color in excluded_color_list:
                        print(f"color excluded: {avg_color}")
                        avg_color = (0,0,0,0)
                    else:
                        print(f"color found: {avg_color}")
                        #draw_hexagon(x + x_offset, y + y_offset, color="#{:02x}{:02x}{:02x}{:02x}".format(*avg_color if fill_hex else (0,0,0,0)), outline_color=border_color, outline_width=hex_border_size)
                        draw_hexagon(x + x_offset, y + y_offset, color="#{:02x}{:02x}{:02x}{:02x}".format(*avg_color), outline_color=border_color, outline_width=hex_border_size)
                else:
                    draw_hexagon(x + x_offset, y + y_offset, color="#00000000", outline_color=border_color, outline_width=hex_border_size)
            else:
                color = "#%02x%02x%02x%02x" % (128, math.ceil(y) % 255, math.ceil(x) % 255, 255) if fill_hex else (0,0,0,0)
                draw_hexagon(x + x_offset, y + y_offset, color=color, outline_color=border_color, outline_width=hex_border_size)
            # Draw text in hexagon
            if add_hex_text_option != None:
                font_size = calculate_font_size(hex_size, 0.333, 20, 7)
                # Skip drawing text if font size is too small
                if font_size:
                    font = ImageFont.truetype(font_path, font_size)
                    # Determine the text to draw
                    if add_hex_text_option == "Row-Column Coordinates":
                        text = f"{col},{row}"
                    elif add_hex_text_option == "Sequential Numbers":
                        text = f"{hex_index}"
                    elif text_list:
                        text = text_list[hex_index % len(text_list)]
                    else:
                        text = None
                    # Determine the text color
                    if color_list:
                        # Extract the opacity from the border color and add to the color_list
                        if isinstance(border_color, str):
                            opacity = int(border_color[-2:], 16)
                        elif isinstance(border_color, tuple) and len(border_color) == 4:
                            opacity = border_color[3]
                        else:
                            opacity = 255  # Default to full opacity if format is unexpected
                        text_color = update_color_opacity(hex_to_rgb(color_list[hex_index % len(color_list)]), opacity)
                    else:
                        # Use border color and opacity
                        text_color = border_color 
                        #text_color = "#{:02x}{:02x}{:02x}{:02x}".format(*text_color)
                    # Skip if text is empty
                    if text != None:
                        print(f"Drawing Text: {text} color: {text_color} size: {font_size}")
                        # Calculate text size using Pango
                        # Create a temporary surface to calculate text size
                        # temp_surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, 1, 1)
                        # temp_context = cairo.Context(temp_surface)
                        # temp_layout = pangocairocffi.create_layout(temp_context)
                        # temp_layout._set_text(text)
                        # temp_desc = pangocffi.FontDescription()
                        # temp_desc._set_family(font_name)
                        # temp_desc._set_size(pangocffi.units_from_double(font_size))
                        # temp_layout._set_font_description(temp_desc)
                        # pangocairocffi.show_layout(temp_context, temp_layout)
                        # ink_rect, logical_rect = temp_layout.get_extents()
                        # text_width = logical_rect.width
                        # text_height = logical_rect.height                
                        # Calculate position to center text in hexagon
                        # text_x = x + x_offset - (text_width / 2)
                        # text_y = y + y_offset - (text_height / 2)
                        # Calculate position to center text in hexagon
                        text_x = x + x_offset - (hex_size / 1.75)
                        text_y = y + y_offset - (hex_size / 1.25)
                        # Draw the text directly onto the image
                        font_image = draw_text_with_emojis(
                            image=font_image,
                            text=text,
                            font_color=update_color_opacity(text_color,255),
                            offset_x=text_x,
                            offset_y=text_y,
                            font_name=font_name,
                            font_size=font_size
                        )                        
                        # # Use Pilmoji to draw text with emojis
                        # with Pilmoji(image) as pilmoji:
                        #     # Calculate text size
                        #     w, h = pilmoji.getsize(text, font=font)
                        #     # Calculate position to center text in hexagon
                        #     text_x = x + x_offset - w / 2
                        #     text_y = y + y_offset - h / 2
                        #     # Draw text
                        #     pilmoji.text(
                        #         (text_x, text_y),
                        #         text,
                        #         font=font,
                        #         fill=text_color
                        #     )
    image.paste(font_image, (0, 0), font_image)
    if rotation != 0:
        # Rotate the final image
        rotated_image = image.rotate(-rotation, expand=True, fillcolor=background_color)
        bbox = rotated_image.split()[3].getbbox(alpha_only=False)

        if bbox:
            # Calculate the size of the rotated image
            rotated_width, rotated_height = rotated_image.size

            # Calculate the size of the cropped area
            box_width = bbox[2] - bbox[0]
            box_height = bbox[3] - bbox[1]

            box_width_adjust = (box_width - image_width) / 2
            bbox_height_adjust = (box_height - image_height) / 2

            print(f"\nbbox: {bbox}: size: {(image_width, image_height)} estimated size: {(box_width, box_height)}")

            # Calculate adjusted box coordinates
            left = bbox[0] + box_width_adjust
            upper = bbox[1] + bbox_height_adjust
            right = bbox[2] - box_width_adjust
            lower = bbox[3] - bbox_height_adjust

            # Ensure coordinates are within image bounds
            left = max(0, min(left, rotated_width))
            upper = max(0, min(upper, rotated_height))
            right = max(0, min(right, rotated_width))
            lower = max(0, min(lower, rotated_height))

            # Ensure the box has positive width and height
            if right > left and lower > upper:
                # Crop the image using the adjusted box
                cropped_image = rotated_image.crop((left, upper, right, lower))
                # Resize the cropped image to the desired size
                final_image = cropped_image.resize((image_width, image_height))
            else:
                # If the box is invalid, resize the entire rotated image
                final_image = rotated_image.resize((image_width, image_height))
        else:
            final_image = rotated_image.resize((image_width, image_height))
    else:
        final_image = image
    return final_image

def generate_hexagon_grid_interface(hex_size, border_size, image, start_x, start_y, end_x, end_y, rotation, background_color, border_color, fill_hex, excluded_color_list, filter_color, x_spacing, y_spacing, add_hex_text_option=None, custom_text_list=None, custom_text_color_list=None):
    print(f"Generating Hexagon Grid with Parameters: Hex Size: {hex_size}, Border Size: {border_size}, Start X: {start_x}, Start Y: {start_y}, End X: {end_x}, End Y: {end_y}, Rotation: {rotation}, Background Color: {background_color}, Border Color: {border_color}, Fill Hex: {fill_hex}, Excluded Color List: {excluded_color_list}, Filter Color: {filter_color}, X Spacing: {x_spacing}, Y Spacing: {y_spacing}, add Text Option {add_hex_text_option}\n")
    hexagon_grid_image = generate_hexagon_grid_with_text(
        hex_size=abs(hex_size),
        border_size=border_size,
        input_image=image,
        start_x=start_x,
        start_y=start_y,
        end_x=end_x,
        end_y=end_y,
        rotation=rotation,
        background_color=background_color,
        border_color=border_color,
        fill_hex = fill_hex,
        excluded_color_list = excluded_color_list,
        filter_color = filter_color, 
        x_spacing = x_spacing if abs(hex_size) > abs(x_spacing) else (hex_size if x_spacing >= 0 else -hex_size), 
        y_spacing = y_spacing if abs(hex_size) > abs(y_spacing) else (hex_size if y_spacing >= 0 else -hex_size),
        add_hex_text_option = add_hex_text_option,
        custom_text_list = custom_text_list,
        custom_text_color_list= custom_text_color_list
    )
    overlay_image = multiply_and_blend_images(image, hexagon_grid_image, 50)
    return hexagon_grid_image, overlay_image