Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- # tk_Text_To_Compact.py
- import tkinter as tk
- from tkinter import colorchooser
- from PIL import Image, ImageDraw, ImageTk, ImageFont, ImageChops
- import os
- import tempfile
- import subprocess
- import platform
- import random
- WW = 600
- HH = 600
- root = tk.Tk()
- root.title("Text To Compact")
- root.geometry("+10+10")
- left_frame = tk.Frame(root)
- left_frame.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)
- right_frame = tk.Frame(root)
- right_frame.pack(side=tk.RIGHT, fill=tk.Y)
- canvas = tk.Canvas(left_frame, width=WW, height=HH)
- scrollbar = tk.Scrollbar(left_frame, orient="vertical", command=canvas.yview)
- canvas.configure(yscrollcommand=scrollbar.set)
- canvas.pack(side="left", fill="both", expand=True)
- scrollbar.pack(side="right", fill="y")
- font_listbox = tk.Listbox(right_frame, width=40, height=30)
- font_listbox.pack(side=tk.LEFT, fill=tk.Y)
- scrollbar = tk.Scrollbar(right_frame, orient=tk.VERTICAL)
- scrollbar.config(command=font_listbox.yview)
- scrollbar.pack(side=tk.RIGHT, fill=tk.Y)
- font_listbox.config(yscrollcommand=scrollbar.set)
- max_width = 580
- padding = 10
- avoid = '''
- holomdl2
- marlett
- segmdl2
- symbol
- webdings
- wingding
- '''
- def copy_canvas_to_clipboard():
- bbox = canvas.bbox("all")
- x0, y0, x1, y1 = bbox
- total_width = (x1 - x0) + padding * 2
- total_height = (y1 - y0) + padding * 2
- img = Image.new("RGBA", (total_width, total_height), (255, 255, 255, 255))
- paste_y = padding
- for canvas_img, x, y in canvas_items:
- if canvas_img.mode != "RGBA":
- canvas_img = canvas_img.convert("RGBA")
- img.paste(canvas_img, (x, paste_y), canvas_img)
- paste_y += canvas_img.height + padding
- top = tk.Toplevel()
- top.title("Canvas Copy")
- canvas_top = tk.Canvas(top, width=WW, height=HH)
- canvas_top.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)
- scrollbar = tk.Scrollbar(top, orient="vertical", command=canvas_top.yview)
- scrollbar.pack(side=tk.RIGHT, fill=tk.Y)
- canvas_top.configure(yscrollcommand=scrollbar.set)
- canvas_top.bind(
- "<Configure>",
- lambda e: canvas_top.configure(scrollregion=canvas_top.bbox("all"))
- )
- tk_img = ImageTk.PhotoImage(img)
- canvas_top.create_image(0, 0, anchor='nw', image=tk_img)
- canvas_top.image = tk_img
- canvas_top.configure(scrollregion=canvas_top.bbox("all"))
- root.update()
- with tempfile.NamedTemporaryFile(suffix=".png", delete=False) as tmp_file:
- img.save(tmp_file.name)
- tmp_file_path = tmp_file.name
- print(f"Image saved to {tmp_file_path}")
- script = f'''
- Add-Type -AssemblyName System.Windows.Forms
- $image = [System.Drawing.Image]::FromFile("{tmp_file_path}")
- [System.Windows.Forms.Clipboard]::SetImage($image)
- '''
- subprocess.run(["powershell", "-Command", script], check=True)
- os.remove(tmp_file_path)
- menu_bar = tk.Menu(root)
- root.config(menu=menu_bar)
- file_menu = tk.Menu(menu_bar, tearoff=0)
- menu_bar.add_cascade(label="Options", menu=file_menu)
- file_menu.add_command(label="Copy To Clipboard", command=copy_canvas_to_clipboard)
- def on_mouse_wheel(event):
- canvas.yview_scroll(int(-1 * (event.delta / 120)), "units")
- canvas.bind_all("<MouseWheel>", on_mouse_wheel)
- def on_font_select(event):
- global font_name
- selected_font = font_listbox.get(font_listbox.curselection())
- font_name = selected_font
- if platform.system() == "Windows":
- fonts_dir = os.path.join(os.environ['WINDIR'], 'Fonts')
- else:
- fonts_dir = "/usr/share/fonts"
- font_lib = {}
- for sys_root, _, files in os.walk(fonts_dir):
- for file in files:
- if file.endswith(('.ttf', '.otf')):
- font_path = os.path.join(sys_root, file)
- font_name = font_path.split('\\')[-1].split('.')[0]
- font_path = ImageFont.truetype(os.path.join(sys_root, file), size=600)
- if font_name not in avoid:
- font_lib[font_name] = font_path
- font_listbox.insert(tk.END, font_name)
- font_name = current_font = 'palai'
- if font_name not in font_lib:
- font_name = current_font = random.choice(list(font_lib))
- sentence = "This is just a demo"
- words = sentence.split()
- splits = []
- for i in range(0, len(words)):
- for j in range(i + 1, len(words) + 1):
- text = words[i:j]
- text = " ".join(text)
- if len(text) > 2:
- splits.append(text)
- def find_true_bbox(img, threshold=128):
- if img.mode != "RGBA":
- img = img.convert("RGBA")
- bg = Image.new("RGBA", img.size, img.getpixel((0, 0)))
- diff = ImageChops.difference(img, bg)
- diff = diff.convert("L")
- diff = diff.point(lambda p: 255 if p > threshold else 0)
- bbox = diff.getbbox()
- return bbox
- def on_canvas_click(canvas_id):
- color = colorchooser.askcolor(title="Choose A Color")[1]
- if color:
- update_line(canvas_id, color)
- def update_line(canvas_id, color):
- text, font, bbox, buffer_draw, buffer_width, buffer_height, tk_img = line_data[canvas_id]
- buffer_image = Image.new("RGBA", (6000, 1000), (255, 255, 255, 0))
- buffer_draw = ImageDraw.Draw(buffer_image)
- buffer_draw.text((50, 0), text, font=font, fill=color)
- buffer_image = buffer_image.crop(bbox)
- buffer_image = buffer_image.resize((buffer_width, buffer_height), Image.ANTIALIAS)
- tk_img = ImageTk.PhotoImage(buffer_image)
- canvas.itemconfig(canvas_id, image=tk_img)
- line_img[canvas_id] = tk_img
- idx = line_img[canvas_id, 'idx']
- img, padding, y_offset = canvas_items[idx]
- canvas_items[idx] = buffer_image, padding, y_offset
- line_data = {}
- def plot(img):
- global y_offset
- tk_img = ImageTk.PhotoImage(img)
- canvas_id = canvas.create_image(padding, y_offset, anchor="nw", image=tk_img)
- line_data[canvas_id] = (text, font_lib[font_name], bbox, ImageDraw.Draw(img), img.width, img.height, tk_img)
- canvas.tag_bind(canvas_id, "<Button-1>", lambda event, idx=canvas_id: on_canvas_click(idx))
- root.update()
- line_img[canvas_id, 'idx'] = len(canvas_items)
- canvas_items.append((img, padding, y_offset))
- canvas.img = tk_img
- y_offset += img.height + padding
- font_listbox.bind("<<ListboxSelect>>", on_font_select)
- font_size = 500
- while 1:
- if font_name:
- line_img = {}
- canvas_items = []
- canvas.configure(scrollregion=(0, 0, WW, 5000))
- canvas.yview_moveto(0.0)
- current_font = font_name
- canvas.delete("all")
- line_data = {}
- y_offset = padding
- print(f"Current font: {font_name}")
- for text in splits:
- if font_name == current_font:
- buffer_image = Image.new("RGBA", (6000, 1000), (255, 255, 255, 0))
- buffer_draw = ImageDraw.Draw(buffer_image)
- buffer_draw.text((50, 0), text, font=font_lib[font_name], fill="black")
- bbox = find_true_bbox(buffer_image, threshold=128)
- buffer_image = buffer_image.crop(bbox)
- buffer_width, buffer_height = buffer_image.size
- print(f"Text: {text}, BBox: {bbox}, Original size: {buffer_width}x{buffer_height}")
- buffer_height = int((max_width / buffer_width) * buffer_height)
- buffer_image = buffer_image.resize((max_width, buffer_height), Image.ANTIALIAS)
- plot(buffer_image)
- else:
- break
- if font_name == current_font:
- canvas.configure(scrollregion=(0, 0, WW, y_offset))
- root.update()
- font_name = ''
- print('*** done ***\n')
- root.update()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement