baqu2213's picture
Upload 3 files
1d5295c
raw
history blame
No virus
202 kB
import customtkinter
import tkinter as tk
from tkinter import font
from tkinter import Tk
from PIL import Image, ImageOps, ImageDraw, ImageFont,ImageTk
import os, sys
import ctypes
import pandas as pd
import numpy as np
import NAIA_search, NAIA_random_function_core, NAIA_Login, NAIA_generation
import json
import arti_list, tagbag, wlist, copyright_list_reformatted, remove_result_e, remove_result_qe, copyright_dict_0103
import character_dictionary as cd
import time
from datetime import datetime
import random
import threading, pyperclip
from ctypes import windll
from CTkListbox import *
from tkinter import filedialog
import io
from openpyxl import Workbook
from openpyxl.styles import Alignment
from openpyxl.drawing.image import Image as OpenpyxlImage
from collections import Counter
from artist_dictionary import artist_dict
import re
import requests
import base64
import queue
import webbrowser
class Data:
def __init__(self, wlist, tagbag, arti_list, copyright_list_reformatted, cd, remove_result_e, remove_result_qe):
self.whitelist = wlist.whitelist
self.bag_of_tags = tagbag.bag_of_tags
self.afilter_30000 = arti_list.afilter_30000
self.copyright_keys = copyright_list_reformatted.copyright_list
self.character_keys = list(cd.character_dictionary.keys())
nsfw_word = list(remove_result_e.keyword_counts.keys())
questionable_word = list(remove_result_qe.keyword_counts.keys())
self.qe_word = nsfw_word + questionable_word
class AccountSetting(customtkinter.CTkToplevel):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.title("NAI Account Setting")
self.attributes('-topmost', True)
def on_close(self):
self.withdraw()
def NAI_connect(self):
username = self.NAI_ID_entry.get().strip()
password = self.NAI_PW_entry.get().strip()
access_key = NAIA_Login.get_access_key(username, password)
try:
app.access_token = NAIA_Login.login(access_key)
app.NAI_ID = username[:4]
self.state_label.configure(text="(๋กœ๊ทธ์ธ ์„ฑ๊ณต, ๋‹ซ๊ธฐ ๋ฒ„ํŠผ์„ ๋ˆŒ๋Ÿฌ์ฃผ์„ธ์š”.)", font=my_font)
app.NAI_Account_Login.configure(state="disabled")
app.NAI_Token_Remove.configure(state="normal")
app.NAI_Account_State.configure(text="NAI Login : OK")
app.image_generation_button.configure(state="normal")
except Exception as e:
print(e)
self.state_label.configure(text="์•„์ด๋”” ํ˜น์€ ๋น„๋ฐ€๋ฒˆํ˜ธ ์˜ค๋ฅ˜์ž…๋‹ˆ๋‹ค.", font=my_font)
self.button_frame = customtkinter.CTkFrame(self)
self.button_frame.grid(row=0, padx=5, pady=5, sticky="nsew")
self.button_frame.columnconfigure(0, weight=1)
self.button_frame.columnconfigure(1, weight=4)
my_font = customtkinter.CTkFont('Pretendard', 13)
self.NAI_ID_label = customtkinter.CTkLabel(self.button_frame, text="NAI ID:", font=my_font)
self.NAI_ID_label.grid(row = 0, column = 0, padx=5, pady=5, sticky="nsew")
self.NAI_PW_label = customtkinter.CTkLabel(self.button_frame, text="NAI PW:", font=my_font)
self.NAI_PW_label.grid(row = 1, column = 0, padx=5, pady=5, sticky="nsew")
self.NAI_ID_entry = customtkinter.CTkEntry(self.button_frame)
self.NAI_ID_entry.grid(row = 0, column = 1, padx=5, pady=5, sticky="nsew")
self.NAI_PW_entry = customtkinter.CTkEntry(self.button_frame, show="*")
self.NAI_PW_entry.grid(row = 1, column = 1, padx=5, pady=5, sticky="nsew")
self.connect_button = customtkinter.CTkButton(self.button_frame, text="Connect", command=lambda:NAI_connect(self))
self.connect_button.grid(row = 2, column = 0, columnspan=2, padx=5, pady=5, sticky="n")
self.state_label = customtkinter.CTkLabel(self.button_frame, text="ํ•ด๋‹น ์ ‘์†๊ธฐ๋Šฅ์€ ์ •์ƒ์ ์ธ ์ ‘์† ํŒจํ„ด์ด ์•„๋‹Œ์  ์ฐธ๊ณ  ๋ถ€ํƒ๋“œ๋ฆฝ๋‹ˆ๋‹ค.", font=my_font)
self.state_label.grid(row = 3, column = 0, columnspan=2, padx=5, pady=5, sticky="nsew")
self.protocol("WM_DELETE_WINDOW", lambda: on_close(self))
class Advanced_setting(customtkinter.CTkToplevel):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.title("๊ธฐํƒ€ ์„ค์ •")
self.resizable(width=False, height=False)
self.geometry("270x250")
self.attributes('-topmost', True)
my_font = customtkinter.CTkFont('Pretendard', 13)
def on_close(self):
self.withdraw()
def select_folder(self):
folder_selected = filedialog.askdirectory()
try:
self.save_path.configure(state="normal")
self.save_path.delete(0,"end")
self.save_path.insert(0, folder_selected)
self.save_path.configure(state="disabled")
app.output_file_path_personal = True
app.output_file_path = folder_selected
except:
pass
def deselect_folder(self):
self.save_path.configure(state="normal")
app.output_file_path = f"output_NAI\\{app.start_time}\\txt2img"
self.save_path.delete(0,"end")
self.save_path.insert(0, app.output_file_path)
self.save_path.configure(state="disabled")
app.output_file_path_personal = True
self.advanced_setting_frame = customtkinter.CTkFrame(self, width=250)
self.advanced_setting_frame.grid(row=0, column=0, padx=10, pady=5, sticky="nsew")
self.change_save_path_button = customtkinter.CTkButton(self.advanced_setting_frame, text="์ด๋ฏธ์ง€ ์ €์žฅ ๊ฒฝ๋กœ ๋ณ€๊ฒฝ", command= lambda: select_folder(self), font=my_font, width=250)
self.change_save_path_button.grid(row=0, column=0, pady=5,sticky="nsew")
self.save_path = customtkinter.CTkEntry(self.advanced_setting_frame, font=my_font, width=250)
self.save_path.insert(0, app.output_file_path)
self.save_path.configure(state="disabled")
self.save_path.grid(row=1, column=0, pady=5,sticky="nsew")
self.change_save_path_button2 = customtkinter.CTkButton(self.advanced_setting_frame, text="๊ฒฝ๋กœ ์ดˆ๊ธฐํ™”", command= lambda: deselect_folder(self), font=my_font, width=250)
self.change_save_path_button2.grid(row=2, column=0, pady=5,sticky="nsew")
self.file_name_label = customtkinter.CTkLabel(self.advanced_setting_frame, text=" -- ํŒŒ์ผ๋ช….png ๊ทœ์น™ ์„ค์ • -- " , font=my_font, width=250)
self.file_name_label.grid(row=3, column=0, pady=5,sticky="n")
self.radio1 = customtkinter.CTkRadioButton(self.advanced_setting_frame, text="์ƒ์„ฑ์‹œ๊ฐ„.png : 20231230_123001.png", variable=app.name_var, value="time", font=my_font)
self.radio1.grid(row=4, column=0)
self.radio2 = customtkinter.CTkRadioButton(self.advanced_setting_frame, text="์ƒ์„ฑ์ˆœ์„œ.png : 00001.png,00002.png", variable=app.name_var, value="count", font=my_font)
self.radio2.grid(row=5, column=0)
self.file_name_label2 = customtkinter.CTkLabel(self.advanced_setting_frame, text="*์ƒ์„ฑ์ˆœ์„œ ์ ์šฉ์‹œ ๋‚ ์งœ_์‹œ๊ฐ„ ํด๋”์— ์ €์žฅ" , font=my_font, width=250)
self.file_name_label2.grid(row=6, column=0, pady=5,sticky="n")
self.protocol("WM_DELETE_WINDOW", lambda: on_close(self))
class Automation_setting(customtkinter.CTkToplevel):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.title("Automation ์ข…๋ฃŒ/์ง€์—ฐ ์„ค์ •")
self.var = customtkinter.StringVar()
self.attributes('-topmost', True)
my_font = customtkinter.CTkFont('Pretendard', 13)
def show_option(self):
if self.var.get() == 'timer':
self.timer_label.grid(row=4, column=0)
self.timer_entry.grid(row=4, column=1)
self.count_label.grid_forget()
self.count_entry.grid_forget()
elif self.var.get() == 'count':
self.count_label.grid(row=4, column=0)
self.count_entry.grid(row=4, column=1)
self.timer_label.grid_forget()
self.timer_entry.grid_forget()
else:
self.timer_label.grid_forget()
self.timer_entry.grid_forget()
self.count_label.grid_forget()
self.count_entry.grid_forget()
def on_close(self):
self.withdraw()
self.label_time = customtkinter.CTkLabel(self, text="์ด๋ฏธ์ง€ ์ƒ์„ฑ๋‹น ์ง€์—ฐ์‹œ๊ฐ„ ์ถ”๊ฐ€ (์ดˆ)", font = my_font)
self.label_time.grid(row=0, column=0, columnspan=3, sticky="n")
self.delay_entry = customtkinter.CTkEntry(self, font = my_font)
self.delay_entry.grid(row=1, column=0,columnspan=3, sticky="n")
self.label = customtkinter.CTkLabel(self, text="์ž๋™ํ™” ์ข…๋ฃŒ ์กฐ๊ฑด", font = my_font)
self.label.grid(row=2, column=0, columnspan=3, sticky="n")
self.radio1 = customtkinter.CTkRadioButton(self, text="๋ฌด์ œํ•œ", variable=self.var, value="unlimited", command=lambda: show_option(self), font = my_font)
self.radio1.grid(row=3, column=0)
self.radio2 = customtkinter.CTkRadioButton(self, text="ํƒ€์ด๋จธ", variable=self.var, value="timer", command=lambda: show_option(self), font = my_font)
self.radio2.grid(row=3, column=1)
self.radio3 = customtkinter.CTkRadioButton(self, text="์ƒ์„ฑ์นด์šดํŠธ", variable=self.var, value="count", command=lambda: show_option(self), font = my_font)
self.radio3.grid(row=3, column=2)
self.timer_label = customtkinter.CTkLabel(self, text="์ž๋™ํ™” ๋™์ž‘ ์‹œ๊ฐ„(๋ถ„) : ", font = my_font)
self.timer_entry = customtkinter.CTkEntry(self)
self.count_label = customtkinter.CTkLabel(self, text="์ž๋™ ์ƒ์„ฑ ํšŸ์ˆ˜ : ", font = my_font)
self.count_entry = customtkinter.CTkEntry(self)
self.apply_button = customtkinter.CTkButton(self, text="์ ์šฉ", font = my_font, command=lambda: on_apply(self))
self.stop_button = customtkinter.CTkButton(self, text="์ค‘๋‹จ", font = my_font, command=lambda: on_stop(self))
self.close_button = customtkinter.CTkButton(self, text="๋‹ซ๊ธฐ", font = my_font, command=lambda: on_close(self))
self.apply_button.grid(row=5, column=0, pady=5)
self.stop_button.grid(row=5, column=1, pady=5)
self.close_button.grid(row=5, column=2, pady=5)
def on_apply(self):
selected_option = self.var.get()
if self.delay_entry.get():
try:
app.delay_offset = round(float(self.delay_entry.get()), 1)
if app.delay_offset > 60:
app.delay_offset = 60
elif app.delay_offset < -8:
app.delay_offset = -8
app.automation_setting_button.configure(text=f"์ž๋™ํ™” ์„ค์ • ({str(round(app.delay_offset, 1))}์ดˆ)")
except ValueError as e:
print(e)
app.delay_offset = 0
else:
app.delay_offset = 0
app.automation_setting_button.configure(text=f"์ž๋™ํ™” ์„ค์ •")
if selected_option == "timer":
app.auto_time_left_flag = True
app.auto_count_left_flag = False
try:
# ์—”ํŠธ๋ฆฌ์—์„œ ์ž…๋ ฅ๋œ ์‹œ๊ฐ„์„ ๋ถ„ ๋‹จ์œ„์—์„œ ์ดˆ ๋‹จ์œ„๋กœ ๋ณ€ํ™˜
app.auto_time_left = int(self.timer_entry.get()) * 60
except ValueError:
# ์ž˜๋ชป๋œ ์ž…๋ ฅ ์ฒ˜๋ฆฌ
print("Invalid input for timer. Please enter a number.")
return
elif selected_option == "count":
app.auto_count_left_flag = True
app.auto_time_left_flag = False
try:
app.auto_count_left = int(self.count_entry.get())
except ValueError:
# ์ž˜๋ชป๋œ ์ž…๋ ฅ ์ฒ˜๋ฆฌ
print("Invalid input for count. Please enter a number.")
return
else:
self.auto_time_left_flag = False
self.auto_count_left_flag = False
on_stop(self) # ์ด์ „ ์Šค๋ ˆ๋“œ ์ข…๋ฃŒ
start_auto_thread() # ์ƒˆ ์Šค๋ ˆ๋“œ ์‹œ์ž‘
def auto_time_thread(stop_event):
def seconds_to_hms(seconds):
h = seconds // 3600
m = (seconds % 3600) // 60
s = seconds % 60
if h != 0:
if (s%2) == 0:
return f"{h:02d}:{m:02d}"
else:
return f"{h:02d} {m:02d}"
else:
if (s%2) == 0:
return f"{m:02d}:{s:02d}"
else:
return f"{m:02d} {s:02d}"
def update_label_for_time_finished():
app.automation_button.configure(text="์ž๋™ํ™” (์ข…๋ฃŒ๋จ)")
app.auto_time_left_flag = False
app.automation_button.deselect()
while not stop_event.is_set() and app.auto_time_left > 0:
time.sleep(1)
app.auto_time_left -= 1
remaining_time = seconds_to_hms(app.auto_time_left)
app.after(0, lambda: app.automation_button.configure(text=f"์ž๋™ํ™” ({remaining_time})"))
if app.auto_time_left <= 0:
app.after(0, update_label_for_time_finished)
if app.stop_event.is_set():
app.after(0, lambda: app.automation_button.configure(text="์ž๋™ํ™”"))
app.auto_time_left_flag = False
def auto_count_thread(stop_event):
def update_label_for_count_finished():
app.automation_button.configure(text="์ž๋™ํ™” (์ข…๋ฃŒ๋จ)")
app.auto_time_left_flag = False
app.automation_button.deselect()
while not stop_event.is_set():
time.sleep(1) # ์ฃผ๊ธฐ์ ์œผ๋กœ ํ™•์ธ
app.after(0, lambda: app.automation_button.configure(text=f"์ž๋™ํ™” ({app.auto_count_left})"))
if app.auto_count_left <= 0:
app.after(0, update_label_for_count_finished)
break # ๋ฃจํ”„ ํƒˆ์ถœ
if app.stop_event.is_set():
app.after(0, lambda: app.automation_button.configure(text="์ž๋™ํ™”"))
app.auto_count_left_flag = False
# ์Šค๋ ˆ๋“œ ์‹œ์ž‘ ๋ฐ ์ข…๋ฃŒ ํ•จ์ˆ˜
def start_auto_thread():
app.stop_event = threading.Event()
app.auto_thread = None
if app.auto_time_left_flag:
app.auto_thread = threading.Thread(target=auto_time_thread, args=(app.stop_event,), daemon=True)
elif app.auto_count_left_flag:
app.auto_thread = threading.Thread(target=auto_count_thread, args=(app.stop_event,), daemon=True)
if app.auto_thread is not None:
app.auto_thread.start()
def stop_auto_thread(self):
if app.stop_event is not None:
app.stop_event.set()
def on_stop(self):
stop_auto_thread(self)
self.protocol("WM_DELETE_WINDOW", lambda: on_close(self))
class Character_search(customtkinter.CTkToplevel):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.title("์บ๋ฆญํ„ฐ ๊ฒ€์ƒ‰ ๋ฐ ์‚ฌ์ „")
#self.resizable(width=False, height=False)
self.app = app
self.attributes('-topmost', True)
my_font = customtkinter.CTkFont('Pretendard', 13)
character_book_dict = {}
try:
if os.path.exists('Character_book.json'):
with open('Character_book.json', 'r', encoding='utf-8') as f:
try:
character_book_dict = json.load(f)
except:
character_book_dict = {}
except FileNotFoundError:
character_book_dict = {}
def lost_top_most(self):
self.attributes('-topmost', False)
def on_close(self):
self.withdraw()
frame_head = customtkinter.CTkFrame(self, width=750, height=40)
frame_head.grid(row =0, column =0, columnspan=5, padx=5, pady=5, sticky="nsew")
frame_left = customtkinter.CTkFrame(self, width=300, height=520)
frame_left.grid(row =1, column =0, padx=5, pady=5, sticky="nsew")
frame_right = customtkinter.CTkFrame(self, width=450, height=520)
frame_right.grid(row =1, column =2, padx=5, pady=5, sticky="nsew")
search_word = customtkinter.StringVar()
search_entry = customtkinter.CTkEntry(frame_head, font=my_font, textvariable=search_word)
character_prompt_frame = customtkinter.CTkFrame(frame_right)
character_prompt_frame.grid(row=0, column=0, padx=10, pady=5, sticky="nsew")
prompt_label = customtkinter.CTkLabel(character_prompt_frame, text="์บ๋ฆญํ„ฐ ํ”„๋กฌํ”„ํŠธ: ", font=my_font)
prompt_label.grid(row=0, column=0, padx=10, pady=5, sticky="w")
def generate_character(self):
prompt = character_prompt.get("0.0", "end-1c")
prompt_cos = cosplay_prompt.get("0.0", "end-1c")
concat_entry = generate_entry.get() + ", {{face focus, upper body}}"
keywords = [item.strip() for item in prompt.split(',')]
if len(keywords) >= 2:
keyword = keywords[1]
keywords[1] = '{{'+keyword+'}}'
keywords.insert(2, concat_entry)
else:
keyword = keywords[0]
keywords[0] = "{{" + keywords[0] + "}}"
request_prompt = ', '.join(keywords)
instant_image_generation_book(self, request_prompt, keyword, prompt, prompt_cos)
character_prompt_generation = customtkinter.CTkButton(character_prompt_frame, font=my_font, text="์ฆ‰์‹œ์ƒ์„ฑ", fg_color="grey", hover_color="grey10", command=lambda: generate_character(self))
character_prompt_generation.grid(row=0, column=1, padx=5, pady=5, sticky="w")
continuous_generation = customtkinter.IntVar()
continuous_generation_button = customtkinter.CTkCheckBox(character_prompt_frame, font=my_font, text="๋นˆ ๋„๊ฐ ์ž๋™์ฑ„์šฐ๊ธฐ", variable=continuous_generation)
continuous_generation_button.grid(row=0, column=2, padx=5, pady=5, sticky="w")
character_prompt = customtkinter.CTkTextbox(frame_right, font=my_font, width=450)
character_prompt.grid(row=1, column=0, padx=10, pady=5, sticky="w")
cosplay_prompt_frame = customtkinter.CTkFrame(frame_right)
cosplay_prompt_frame.grid(row=2, column=0, padx=10, pady=5, sticky="nsew")
prompt_label = customtkinter.CTkLabel(cosplay_prompt_frame, text="์บ๋ฆญํ„ฐ(Cosplay)):", font=my_font)
prompt_label.grid(row=0, column=0, padx=10, pady=5, sticky="w")
#cosplay_prompt_generation = customtkinter.CTkButton(cosplay_prompt_frame, font=my_font, text="์ฆ‰์‹œ์ƒ์„ฑ", fg_color="grey", hover_color="grey10", command=lambda: app.instant_image_generation_book())
#cosplay_prompt_generation.grid(row=0, column=1, padx=5, pady=5, sticky="w")
cosplay_prompt = customtkinter.CTkTextbox(frame_right, font=my_font, width=450)
cosplay_prompt.grid(row=3, column=0, padx=10, pady=5, sticky="w")
image_label = customtkinter.CTkLabel(frame_right, text="")
image_label.grid(row=0, rowspan=4, column=1, padx=10, pady=5, sticky="w")
white_image = Image.new('RGB', (384, 512), 'white')
white_photo = customtkinter.CTkImage(white_image, size=(384,512))
image_label.configure(image=white_photo)
generate_label = customtkinter.CTkLabel(self, text="Portrait ์ƒ์„ฑ์‹œ ์ ์šฉํ•  ์„ ํ–‰ ๊ณ ์ • ํ”„๋กฌํ”„ํŠธ : ", font=my_font)
generate_label.grid(row=2, column=0, padx=5, pady=5, sticky="w")
generate_entry = customtkinter.CTkEntry(self, font=my_font)
generate_entry.grid(row=2, column=1, columnspan=2, padx=5, pady=5, sticky="nsew")
if character_book_dict != None and 'user_fix_prompt' in character_book_dict and character_book_dict['user_fix_prompt'] != None:
generate_entry.delete(0, "end")
generate_entry.insert(0, character_book_dict['user_fix_prompt'])
def instant_image_generation_book(self, request_prompt, character_name, p1, p2):
if app.running_flag == False and app.automation_button.get() == 0:
character_prompt_generation.configure(state="disabled")
#cosplay_prompt_generation.configure(state="disabled")
app.running_flag == True
try:
scale_pre = float(scale_pre)
except:
scale_pre = 5.0
app.cfg_scale_var.set("5.0")
rescale_pre = app.prompt_guidance_rescale_entry.get()
try:
rescale_pre = float(rescale_pre)
except:
rescale_pre = 0
app.prompt_guidance_rescale_var.set("0")
gen_request = {
"width":896,
"height":1152,
"quality_toggle":app.auto_quality_toggle.get(),
"seed":random.randint(0,9999999999),
"sampler":app.sampler_button.get(),
"scale":scale_pre,
"sema":app.sema_button.get(),
"sema_dyn": app.dyn_button.get(),
"cfg_rescale": rescale_pre,
"prompt": request_prompt,
"negative":app.negative_prompt_input.get("0.0", "end-1c"),
"user_screen_size": app.get_max_size(),
"start_time": app.start_time,
"access_token": app.access_token,
"save_folder": app.output_file_path,
"png_rule": app.name_var.get(),
"type": "normal"
}
def run_generation():
if gen_request["png_rule"] == "count":
app.generation_count += 1
gen_request["count"] =app.generation_count
app.state_label.configure(text ="state : ๋„๊ฐ ์ด๋ฏธ์ง€ ์š”์ฒญ๋จ ", text_color = "#FFFF97")
result_image, result_prompt, result_seed, info, filename = NAIA_generation.generate(gen_request)
app.running_flag == False
character_prompt_generation.configure(state="normal")
#cosplay_prompt_generation.configure(state="normal")
app.state_label.configure(text ="state : ๋„๊ฐ ์ด๋ฏธ์ง€ ์š”์ฒญ ๋ฐ˜ํ™˜๋จ", text_color = "#DCE4EE")
if info:
temp = info.get('Comment', '')
temp = temp[temp.find("prompt")+10:temp.find("skip_cfg_below_sigma")-3].replace('"','')
else:
temp = result_prompt
app.image_label_report.configure(state="normal")
app.image_label_report.delete("0.0", "end")
app.image_label_report.configure(text_color="#DCE4EE")
app.image_label_report.insert("0.0", temp)
app.image_label_report.configure(state="disabled")
if result_image:
image_bytes = io.BytesIO()
book_image = Image.open(filename).resize((384,512))
book_image = book_image.convert('RGB')
book_image.save(image_bytes, format='JPEG', quality=90)
image_bytes = base64.b64encode(image_bytes.getvalue()).decode('utf-8')
character_book_dict[character_name] = [0, p1, p2, image_bytes]
character_book_dict['user_fix_prompt'] = generate_entry.get()
with open('Character_book.json', 'w', encoding='utf-8') as f:
json.dump(character_book_dict, f, ensure_ascii=False, indent=4)
image_stream = io.BytesIO(base64.b64decode(image_bytes))
reloaded_image = Image.open(image_stream)
image_label.configure(image=customtkinter.CTkImage(reloaded_image, size=(384,512)))
if app.state() != 'zoomed':
instant_result_image = customtkinter.CTkImage(result_image, size=(620,620))
else:
current_image = Image.open(filename)
original_width, original_height = current_image.size
max_size = app.winfo_screenheight()-100
if original_width > max_size or original_height > max_size:
new_image = Image.new("RGB", (max_size, max_size), "black")
new_image.paste(current_image, ((max_size - original_width) // 2, (max_size - original_height) // 2))
instant_result_image = customtkinter.CTkImage(new_image, size=(max_size, max_size))
else:
instant_result_image = customtkinter.CTkImage(current_image, size=(max_size, max_size))
app.image_label.configure(image=instant_result_image)
app.ext_set_image_to_queue(result_image, result_prompt, str(result_seed), filename)
if continuous_generation.get() == 1:
listbox.focus()
app.after(500, move_selection_down(self))
else:
if continuous_generation.get() == 1:
app.after(500, generate_character(self))
generation_thread = threading.Thread(target=run_generation, daemon=True)
generation_thread.start()
def move_selection_down(self):
selected_indices = listbox.curselection()
if selected_indices:
current_index = selected_indices[0]
next_index = current_index + 1
# ๋ฆฌ์ŠคํŠธ์˜ ๋์„ ๋„˜์–ด๊ฐ€์ง€ ์•Š๋„๋ก ํ™•์ธ
if next_index < listbox.size():
listbox.selection_clear(current_index)
listbox.selection_set(next_index)
listbox.see(next_index)
else:
continuous_generation_button.deselect()
keyword_with_count = listbox.get(next_index).strip()
keyword = keyword_with_count.split(' - ')[0].strip()
if keyword not in character_book_dict and continuous_generation.get() == 1:
on_search()
app.after(500, generate_character(self))
elif continuous_generation.get() == 1:
app.after(500, move_selection_down(self))
def on_key_release(event):
search_keyword = search_entry.get()
update_listbox(search_keyword)
def on_search():
# ๊ฒ€์ƒ‰ ๋ฒ„ํŠผ ์ด๋ฒคํŠธ ์ฒ˜๋ฆฌ ํ•จ์ˆ˜
selected_indices = listbox.curselection()
if not selected_indices: # If there is no selection
print("No selection made.")
return
# Assuming the first selected index (single selection mode)
selected_index = selected_indices[0]
# Get the keyword from the listbox, split by '-', and trim whitespace
keyword_with_count = listbox.get(selected_index).strip()
keyword = keyword_with_count.split(' - ')[0].strip()
# Call the analyze function with the selected keyword
print(f"Analyzing keyword: {keyword}")
character, cosplay = analyze_keywords_in_data('csdataset.parquet', keyword)
character_prompt.delete("0.0", "end")
character_prompt.insert("0.0", character)
cosplay_prompt.delete("0.0", "end")
cosplay_prompt.insert("0.0", cosplay)
def analyze_keywords_in_data(parquet_file, keyword):
# Parquet ํŒŒ์ผ ์ฝ๊ธฐ
df = pd.read_parquet(parquet_file)
bag_of_tags = ['penis', 'character name', 'upper body','holding','full body', 'artist name', 'male focus', 'open mouth', 'mature male', 'muscular', 'muscular male', 'closed mouth','closed eyes', 'white background', 'solo', 'breasts', 'simple background', 'smile', 'looking at viewer', 'flat chest', 'small breasts', 'medium breasts', 'large breasts', 'huge breasts','aqua eyes', 'black eyes', 'blue eyes', 'brown eyes', 'green eyes', 'grey eyes', 'orange eyes', 'purple eyes', 'pink eyes', 'red eyes', 'white eyes', 'yellow eyes', 'amber eyes', 'heterochromia', 'multicolored eyes', 'aqua pupils', 'blue pupils', 'brown pupils', 'green pupils', 'grey pupils', 'orange pupils', 'pink pupils', 'purple pupils', 'red pupils', 'white pupils', 'yellow pupils', 'pointy ears', 'long pointy ears', 'aqua hair', 'black hair', 'blonde hair', 'blue hair', 'light blue hair', 'dark blue hair', 'brown hair', 'light brown hair', 'green hair', 'dark green hair', 'light green hair', 'grey hair', 'orange hair', 'pink hair', 'purple hair', 'light purple hair', 'red hair', 'white hair', 'multicolored hair', 'colored inner hair', 'colored tips', 'roots (hair)', 'gradient hair', 'print hair', 'rainbow hair', 'split-color hair', 'spotted hair', 'streaked hair', 'two-tone hair', 'very short hair', 'short hair', 'medium hair', 'long hair', 'very long hair', 'absurdly long hair', 'big hair', 'bald', 'bald girl', 'bob cut', 'inverted bob', 'bowl cut', 'buzz cut', 'chonmage', 'crew cut', 'flattop', 'okappa', 'pixie cut', 'undercut', 'flipped hair', 'wolf cut', 'cornrows', 'dreadlocks', 'hime cut', 'mullet', 'bow-shaped hair', 'braid', 'braided bangs', 'front braid', 'side braid', 'french braid', 'crown braid', 'single braid', 'multiple braids', 'twin braids', 'low twin braids', 'tri braids', 'quad braids', 'flower-shaped hair', 'hair bun', 'braided bun', 'single hair bun', 'double bun', 'cone hair bun', 'doughnut hair bun', 'heart hair bun', 'triple bun', 'cone hair bun', 'hair rings', 'single hair ring', 'half updo', 'one side up', 'two side up', 'low-braided long hair', 'low-tied long hair', 'mizura', 'multi-tied hair', 'nihongami', 'ponytail', 'folded ponytail', 'front ponytail', 'high ponytail', 'short ponytail', 'side ponytail', 'split ponytail', 'star-shaped hair', 'topknot', 'twintails', 'low twintails', 'short twintails', 'uneven twintails', 'tri tails', 'quad tails', 'quin tails', 'twisted hair', 'afro', 'huge afro', 'beehive hairdo', 'crested hair', 'pompadour', 'quiff', 'shouten pegasus mix mori', 'curly hair', 'drill hair', 'twin drills', 'tri drills', 'hair flaps', 'messy hair', 'pointy hair', 'ringlets', 'spiked hair', 'straight hair', 'wavy hair', 'bangs', 'arched bangs', 'asymmetrical bangs', 'bangs pinned back', 'blunt bangs', 'crossed bangs', 'diagonal bangs', 'dyed bangs', 'fanged bangs', 'hair over eyes', 'hair over one eye', 'long bangs', 'parted bangs', 'curtained hair', 'ribbon bangs', 'short bangs', 'swept bangs', 'hair between eyes', 'hair intakes', 'single hair intake', 'sidelocks', 'asymmetrical sidelocks', 'drill sidelocks', 'low-tied sidelocks', 'sidelocks tied back', 'single sidelock', 'ahoge', 'heart ahoge', 'huge ahoge', 'antenna hair', 'heart antenna hair', 'comb over', 'hair pulled back', 'hair slicked back', 'mohawk', 'oseledets', 'lone nape hair', 'hair bikini', 'hair censor', 'hair in own mouth', 'hair over breasts', 'hair over one breast', 'hair over crotch', 'hair over shoulder', 'hair scarf', 'alternate hairstyle', 'hair down', 'hair up', 'asymmetrical hair', 'sidecut', 'blunt ends', 'dark skin', 'dark-skinned female', 'pale skin', 'sun tatoo', 'black skin', 'blue skin', 'green skin', 'grey skin', 'orange skin', 'pink skin', 'purple skin', 'red skin', 'white skin', 'yellow skin', 'colored skin', 'multiple tails', 'demon tail', 'dragon tail', 'ghost tail', 'pikachu tail', 'snake head tail', 'fiery tail', 'bear tail', 'rabbit tail', 'cat tail', 'cow tail', 'deer tail', 'dog tail', 'ermine tail', 'fox tail', 'horse tail', 'leopard tail', 'lion tail', 'monkey tail', 'mouse tail', 'pig tail', 'sheep tail', 'squirrel tail', 'tiger tail', 'wolf tail', 'crocodilian tail', 'fish tail', 'scorpion tail', 'snake tail', 'tadpole tail']
mini_bag_of_tags = ['penis', 'character name', 'upper body', 'full body', 'alternate costume','artist name', 'male focus', 'open mouth', 'mature male', 'muscular', 'muscular male', 'closed mouth','closed eyes','white background', 'solo', 'breasts', 'simple background', 'smile', 'looking at viewer']
# 'character' ์—ด์—์„œ keyword์— ํ•ด๋‹นํ•˜๋Š” ํ–‰๋งŒ ํ•„ํ„ฐ๋ง
filtered_df = df[df['character'] == keyword]
filtered_df = filtered_df[~filtered_df['character'].str.contains(',', na=False)]
if filtered_df.empty:
filtered_df = df[df['character'].str.contains(keyword, na=False, regex=False)]
filtered_df = filtered_df[~(filtered_df['rating'] == 'e')]
#print(len(filtered_df))
# keyword:count ํ˜•ํƒœ๋กœ ๋ฐ์ดํ„ฐ ์ง‘๊ณ„ํ•  ๋”•์…”๋„ˆ๋ฆฌ ์ƒ์„ฑ
keyword_count_dict = {}
# ๊ฐ ํ–‰์˜ 'general' ์—ด ์ฒ˜๋ฆฌ
for general in filtered_df['general']:
# ๋ฌธ์ž์—ด ๋ถ„ํ• 
tags = [tag.strip() for tag in general.split(',')]
# ๋”•์…”๋„ˆ๋ฆฌ์— ๊ฐ ํƒœ๊ทธ์˜ count ์ถ”๊ฐ€
for tag in tags:
keyword_count_dict[tag] = keyword_count_dict.get(tag, 0) + 1
# ํŠน์ • ํ‚ค์›Œ๋“œ ์ œ์™ธ
exclude_keywords = bag_of_tags
keyword_count_dict1 = keyword_count_dict.copy()
keyword_count_dict1 = {k: v for k, v in keyword_count_dict1.items() if k not in mini_bag_of_tags}
keyword_count_dict = {k: v for k, v in keyword_count_dict.items() if k not in exclude_keywords}
# ๊ฐ€์žฅ ๋†’์€ count ๊ฐ’ ์ฐพ๊ธฐ
highest_count = max(keyword_count_dict.values()) if keyword_count_dict else 0
highest_count1 = max(keyword_count_dict1.values()) if keyword_count_dict1 else 0
if(len(filtered_df)) < 10:
weight = 0.6
elif(len(filtered_df)) < 30:
weight = 0.5
elif(len(filtered_df)) < 80:
weight = 0.45
elif(len(filtered_df)) < 160:
weight = 0.35
elif(len(filtered_df)) < 280:
weight = 0.3
else:
weight = 0.2
result_list = []
result_list1 = []
# count๊ฐ€ highest_count*0.4 ์ด์ƒ์ธ ํ‚ค์›Œ๋“œ ์ถœ๋ ฅ
for k, v in keyword_count_dict.items():
if '|' in k: continue
if v >= highest_count * weight:
result_list.append(k)
for k, v in keyword_count_dict1.items():
if '|' in k: continue
if v >= highest_count1 * weight:
result_list1.append(k)
result_list1.insert(1, keyword)
result_list.insert(1, "alternative costume, ["+keyword+" (cosplay)]")
return ", ".join(result_list1),", ".join(result_list)
def update_listbox(search_keyword):
# Clear the listbox
if listbox.size() > 0:
listbox.delete(0, "end")
# List to hold all matching keywords and counts
all_matching_keywords = []
# Set to track added keywords to avoid duplicates
added_keywords = set()
# Check if the search keyword is not empty and has at least 3 characters
if search_keyword and len(search_keyword) >= 3:
# Search in copyright_dict first
for key, keywords in copyright_dict_0103.copyright_dict.items():
if search_keyword.lower() in key.lower():
for keyword in keywords:
count = cd.character_dictionary.get(keyword, 0)
if count > 50 and keyword not in added_keywords:
all_matching_keywords.append((keyword, count))
added_keywords.add(keyword)
# Then search in character_dictionary
matching_keywords = [
(k, v) for k, v in cd.character_dictionary.items()
if search_keyword.lower() in k.lower() and v > 50 and k not in added_keywords
]
all_matching_keywords.extend(matching_keywords)
else:
# Sort all keywords by count in descending order
all_matching_keywords = [
(k, v) for k, v in cd.character_dictionary.items() if v > 50 and k not in added_keywords
]
# Now sort all matching keywords by count in descending order and insert into listbox
all_matching_keywords.sort(key=lambda item: item[1], reverse=True)
for keyword, count in all_matching_keywords:
listbox.insert("end", f"{keyword} - {count}")
search_entry.grid(row =0, column =0, padx=5, pady=5, sticky="nsew")
search_entry.bind("<KeyRelease>", on_key_release)
search_label = customtkinter.CTkLabel(frame_head, text="โ—€ ๊ฒ€์ƒ‰ ๋Œ€์ƒ copyright/character ์ž…๋ ฅ (English) | ์„ฑ๋Šฅ ์ด์Šˆ๋กœ Danbooru 50์žฅ ์ด์ƒ๋งŒ ํ‘œ์‹œ", font=my_font)
search_label.grid(row =0, column =1, padx=5, pady=5, sticky="w")
def show_image(event):
selected_indices = listbox.curselection()
selected_index = selected_indices[0]
keyword_with_count = listbox.get(selected_index).strip()
keyword = keyword_with_count.split(' - ')[0].strip()
if keyword in character_book_dict:
try:
image_stream = io.BytesIO(base64.b64decode(character_book_dict[keyword][3]))
reloaded_image = Image.open(image_stream)
image_label.configure(image=customtkinter.CTkImage(reloaded_image, size=(384,512)))
character_prompt.delete("0.0", "end")
character_prompt.insert("0.0", character_book_dict[keyword][1])
cosplay_prompt.delete("0.0", "end")
cosplay_prompt.insert("0.0", character_book_dict[keyword][2])
except:
return
else:
if character_prompt.get("0.0","end") != None:
character_prompt.delete("0.0", "end")
if cosplay_prompt.get("0.0","end") != None:
cosplay_prompt.delete("0.0", "end")
image_label.configure(image=white_photo)
listbox = tk.Listbox(frame_left, width=32, height=30, font = font.Font(family='Pretendard', size=13), bg='#2B2B2B', fg='#F8F8F8', borderwidth=2, highlightbackground='lightgrey')
listbox.bind('<<ListboxSelect>>', show_image)
listbox.grid(row = 0, column=0, padx=5, pady=5, sticky="nsew")
search_button = customtkinter.CTkButton(self, font=my_font, text="์กฐํšŒ", fg_color="grey", hover_color="grey10", command=on_search)
search_button.grid(row = 1, column=1, padx=5, pady=150, sticky="w")
all_keywords = sorted(
((k, v) for k, v in cd.character_dictionary.items() if v > 50),
key=lambda item: item[1],
reverse=True
)
for keyword, count in all_keywords:
listbox.insert("end", f"{keyword} - {count}")
self.protocol("WM_DELETE_WINDOW", lambda: on_close(self))
collection_button = customtkinter.CTkButton(frame_head, text="Copyright ๋„๊ฐ", font=my_font, fg_color="grey", hover_color="grey10", command=lambda: open_collection(self))
collection_button.grid(row =0, column =2, padx=50, pady=5, sticky="e")
def open_collection(self):
self.attributes('-topmost', False)
collection_window = customtkinter.CTkToplevel()
collection_window.title("๋„๊ฐ")
collection_window.attributes('-topmost', True)
collection_window.resizable(width=False, height=False)
_height = app.winfo_screenheight()
print(_height)
if _height < 1152:
yview = 660
ylist = 46
else:
yview = 700
ylist = 50
collection_frame_head = customtkinter.CTkFrame(collection_window, width=1220, height=40)
collection_frame_head.grid(row =0, column =0, columnspan=5, padx=5, pady=5, sticky="nsew")
collection_label1 = customtkinter.CTkLabel(collection_frame_head, font=my_font, text="์ด๋ฆ„์„ ๋ˆŒ๋Ÿฌ ํŠน์ง•์„ ๋ณต์‚ฌํ•ฉ๋‹ˆ๋‹ค.")
collection_label1.grid(row = 0, column=0, padx=5, pady=5, sticky="nsew")
collection_frame_left = customtkinter.CTkFrame(collection_window, width=300, height=yview)
collection_frame_left.grid(row =1, column =0, padx=5, pady=5, sticky="nsew")
collection_frame_right = customtkinter.CTkScrollableFrame(collection_window, width=900, height=yview)
collection_frame_right.grid(row =1, column =2, padx=5, pady=5, sticky="nsew")
show_window = []
def copy_character_info(key):
text = character_book_dict[key][1].split(',')
text_list = [keyword.strip() for keyword in text]
charactersitics = []
charactersitics.append("{"+key+"}")
count = 0
for texts in text_list:
if count < 4 and texts in tagbag.bag_of_tags[5:] and 'tail' not in texts and 'pupil' not in texts and '1girl' not in texts and '1boy' not in texts and '1other' not in texts:
charactersitics.append(texts)
count += 1
texts = ', '.join(charactersitics)
pyperclip.copy(texts)
collection_label1.configure(text=f"์„ ํƒํ•˜์‹  {texts}๊ฐ€ ํด๋ฆฝ๋ณด๋“œ์— ๋ณต์‚ฌ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.", text_color="#FFFF97")
def spread_image(event, show_window):
collection_frame_right._parent_canvas.yview_moveto(0)
selected_indices = collection_listbox.curselection()
selected_index = selected_indices[0]
collection_listbox.configure(state="disabled")
if show_window:
for i in show_window:
i.destroy()
keyword_with_count = collection_listbox.get(selected_index).strip()
keyword = ' '.join(keyword_with_count.split('%')[1].split()).strip()
try:
key_in_book = split_dict[keyword]
# ๋‚˜๋จธ์ง€ ์ฝ”๋“œ...
except KeyError:
print(f"KeyError: '{keyword}' not found in the split dictionary.")
count = 0
for key in key_in_book:
_row = count//3
_column = count%3
if key in character_book_dict:
f = customtkinter.CTkFrame(collection_frame_right, width = 298, height=394)
f.grid(row=_row, column=_column, padx=5, pady=5, sticky="nsew")
name = key
if len(key) > 45:
name = key[:44]
b = customtkinter.CTkButton(f, font=my_font,text=name, state="disabled" if len(key) > 45 else "normal", fg_color="grey10", hover_color="grey10", text_color_disabled="white", command=lambda name=name: copy_character_info(name))
b.grid(row=0, column=0, padx=5, pady=5, sticky="nsew")
image_stream = io.BytesIO(base64.b64decode(character_book_dict[key][3]))
reloaded_image = Image.open(image_stream)
i = customtkinter.CTkLabel(f, text="", image=customtkinter.CTkImage(reloaded_image, size=(288,384)))
i.grid(row=1, column=0, padx=5, pady=5, sticky="nsew")
show_window.append(f)
count += 1
collection_listbox.configure(state="normal")
collection_listbox.selection_clear(selected_index)
collection_listbox = tk.Listbox(collection_frame_left, width=32, height=ylist, font = font.Font(family='Pretendard', size=13), bg='#2B2B2B', fg='#F8F8F8', borderwidth=2, highlightbackground='lightgrey')
collection_listbox.bind('<<ListboxSelect>>',lambda event: spread_image(event, show_window))
collection_listbox.grid(row = 0, column=0, padx=5, pady=5, sticky="nsew")
all_collections = sorted(
((k, v) for k, v in copyright_dict_0103.copyright_dict.items()),
key=lambda item: len(item[1]),
reverse=True
)
split_dict = {}
for keyword, value in all_collections:
key_in_book = copyright_dict_0103.copyright_dict[keyword]
cover = sum(key in character_book_dict for key in key_in_book)
coverage = f"{round((cover / len(key_in_book)) * 100, 1) if cover else 0}%"
# key_in_book์˜ ๊ธธ์ด๊ฐ€ 90์„ ์ดˆ๊ณผํ•˜๋Š” ๊ฒฝ์šฐ ์ฒ˜๋ฆฌ
if len(key_in_book) > 96:
for i in range(0, len(key_in_book), 96):
part_key = f"{keyword} ({i//96 + 1})"
split_dict[part_key] = key_in_book[i:i+96]
cover_part = sum(key in character_book_dict for key in split_dict[part_key])
coverage_part = f"{round((cover_part / len(split_dict[part_key])) * 100, 1) if cover_part else 0}%"
collection_listbox.insert("end", f"{coverage_part:<7s}{keyword} ({i//96 + 1})")
else:
split_dict[keyword] = key_in_book
collection_listbox.insert("end", f"{coverage:<7s}{keyword}")
class Preset_open(customtkinter.CTkToplevel):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.title("ํ”„๋กฌํ”„ํŠธ ๊ฒ€์ƒ‰/์„ค์ • ํ”„๋ฆฌ์…‹")
self.attributes('-topmost', True)
self.resizable(width=False, height=False)
my_font = customtkinter.CTkFont('Pretendard', 13)
presets ={}
items = 0
preset_frame_left = customtkinter.CTkFrame(self, width=250, height=520)
preset_frame_left.grid(row =1, rowspan=10, column =0, padx=5, pady=5, sticky="nsew")
preset_frame_right = customtkinter.CTkFrame(self, width=700, height=520)
preset_frame_right.grid(row =1, rowspan=10, column =1, columnspan = 2, padx=5, pady=5, sticky="nsew")
preset_insert_right_frame = customtkinter.CTkFrame(self)
preset_insert_right_frame.grid(row =0, column =0, columnspan=2, padx=5, pady=5, sticky="nsew")
preset_insert_button = customtkinter.CTkButton(preset_insert_right_frame, text="ํ”„๋ฆฌ์…‹ ์ถ”๊ฐ€", font=my_font, command=lambda: add_preset(self, presets))
preset_insert_button.grid(row =0, column =0, padx=5, pady=5, sticky="nsew")
preset_insert_name = customtkinter.CTkLabel(preset_insert_right_frame, text="ํ”„๋ฆฌ์…‹ ๋ช…์นญ : ", font=my_font)
preset_insert_name.grid(row =0, column =1, padx=5, pady=5, sticky="w")
preset_insert_name_entry = customtkinter.CTkEntry(preset_insert_right_frame,width=200, font=my_font)
preset_insert_name_entry.grid(row =0, column =2, padx=5, pady=5, sticky="w")
preset_insert_description = customtkinter.CTkLabel(preset_insert_right_frame, text=" ์„ค๋ช… : ", font=my_font)
preset_insert_description.grid(row =0, column =3, padx=5, pady=5, sticky="w")
preset_insert_description_entry = customtkinter.CTkEntry(preset_insert_right_frame, width=420, font=my_font)
preset_insert_description_entry.grid(row =0, column =4, padx=5, pady=5, sticky="w")
preset_frame_bottom = customtkinter.CTkFrame(self)
preset_frame_bottom.grid(row =11, column =0, columnspan=2, padx=5, pady=5, sticky="nsew")
preset_label = customtkinter.CTkLabel(preset_frame_bottom, text="์ƒ์„ฑ๊ธฐ ๋‚ด ์ขŒ์ธก ํŒจ๋„์˜ ๊ฐ’๋“ค์„ ํ”„๋ฆฌ์…‹์œผ๋กœ ์ €์žฅํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.", font=my_font)
preset_label.grid(row =0, column=0,sticky="n" )
def _yield(selected_option):
ypreset = self.presets[selected_option]
yield_preset_description.configure(text=ypreset['description'])
yield_preset_search.configure(text=ypreset['search'])
yield_preset_exclude.configure(text=ypreset['exclude'])
yield_preset_prompt.configure(state="normal")
yield_preset_prompt.delete("0.0", "end")
yield_preset_prompt.insert("0.0", ypreset['prompt'])
yield_preset_prompt.configure(state="disabled")
_text = ""
if ypreset['explicit'] == 1:
_text += "Explicit "
if ypreset['nsfw'] == 1:
_text += "NSFW "
if ypreset['sensitive'] == 1:
_text += "Sensitive "
if ypreset['general'] == 1:
_text += "General"
yield_activated_ratings.configure(text = _text)
yield_prefix.configure(state="normal")
yield_prefix.delete("0.0", "end")
yield_prefix.insert("0.0", ypreset['fix'])
yield_prefix.configure(state="disabled")
yield_postfix.configure(state="normal")
yield_postfix.delete("0.0", "end")
yield_postfix.insert("0.0", ypreset['fix_after'])
yield_postfix.configure(state="disabled")
yield_negative.configure(state="normal")
yield_negative.delete("0.0", "end")
yield_negative.insert("0.0", ypreset['negative'])
yield_negative.configure(state="disabled")
yield_autohide.configure(state="normal")
yield_autohide.delete("0.0", "end")
yield_autohide.insert("0.0", ypreset['auto_hide'])
yield_autohide.configure(state="disabled")
_text = ""
if ypreset['rm_artist'] == 1:
_text += "์ž‘๊ฐ€๋ช…์ œ๊ฑฐ "
if ypreset['rm_copyright'] == 1:
_text += "์ž‘ํ’ˆ๋ช…์ œ๊ฑฐ "
if ypreset['rm_character'] == 1:
_text += "์บ๋ฆญํ„ฐํŠน์ง•์ œ๊ฑฐ"
yield_rm.configure(text = _text)
preset_list = CTkListbox(preset_frame_left, height=570, font=my_font, command= _yield)
preset_list.grid(row = 0, column=0, padx=5, pady=5, sticky="nsew")
show_preset_description = customtkinter.CTkButton(preset_frame_right, text="Description", font=my_font, width=150, fg_color="grey10", text_color_disabled="white",state="disabled")
show_preset_description.grid(row = 0, column = 0, padx=5, pady=5, sticky="w")
yield_preset_description = customtkinter.CTkLabel(preset_frame_right, text="", font=my_font, width=550)
yield_preset_description.grid(row = 0, column = 1, padx=5, pady=5, sticky="w")
def insert_search():
if preset_list.get():
app.search_label_entry.delete(0, "end")
app.search_label_entry.insert(0, yield_preset_search.cget("text"))
show_preset_search = customtkinter.CTkButton(preset_frame_right, text="Search Keyword", font=my_font, width=150, fg_color="grey10", hover_color="grey", command=insert_search)
show_preset_search.grid(row = 1, column = 0, padx=5, pady=5, sticky="w")
yield_preset_search = customtkinter.CTkLabel(preset_frame_right, text="", font=my_font, width=550)
yield_preset_search.grid(row = 1, column = 1, padx=5, pady=5, sticky="w")
def insert_exclude():
if preset_list.get():
app.exclude_label_entry.delete(0, "end")
app.exclude_label_entry.insert(0, yield_preset_exclude.cget("text"))
show_preset_exclude = customtkinter.CTkButton(preset_frame_right, text="Exclude Keyword", font=my_font, width=150, fg_color="grey10", hover_color="grey", command=insert_exclude)
show_preset_exclude.grid(row = 2, column = 0, padx=5, pady=5, sticky="w")
yield_preset_exclude = customtkinter.CTkLabel(preset_frame_right, text="", font=my_font, width=550)
yield_preset_exclude.grid(row = 2, column = 1, padx=5, pady=5, sticky="w")
def insert_prompt():
if preset_list.get():
app.text_input.delete("0.0","end")
app.text_input.insert("0.0", yield_preset_prompt.get("0.0", "end"))
show_preset_prompt = customtkinter.CTkButton(preset_frame_right, text="Prompt", font=my_font, width=150, height=100, fg_color="grey10", hover_color="grey", command=insert_prompt)
show_preset_prompt.grid(row = 3, column = 0, padx=5, pady=5, sticky="w")
yield_preset_prompt = customtkinter.CTkTextbox(preset_frame_right, font=my_font, state="disabled",width=550, height=100, fg_color='#2B2B2B')
yield_preset_prompt.grid(row = 3, column = 1, padx=5, pady=5, sticky="w")
def insert_ratings():
if preset_list.get():
app.rating_select_explicit.deselect()
app.rating_select_nsfw.deselect()
app.rating_select_sensitive.deselect()
app.rating_select_general.deselect()
_text = yield_activated_ratings.cget("text")
if "Explicit" in _text:
app.rating_select_explicit.select()
if "NSFW" in _text:
app.rating_select_nsfw.select()
if "Sensitive" in _text:
app.rating_select_sensitive.select()
if "General" in _text:
app.rating_select_general.select()
show_activated_ratings = customtkinter.CTkButton(preset_frame_right, text="Ratings", font=my_font, width=150, fg_color="grey10", hover_color="grey", command=insert_ratings)
show_activated_ratings.grid(row = 4, column = 0, padx=5, pady=5, sticky="w")
yield_activated_ratings = customtkinter.CTkLabel(preset_frame_right, text="", font=my_font, width=550)
yield_activated_ratings.grid(row = 4, column = 1, padx=5, pady=5, sticky="w")
#์„ ํ–‰๊ณ ์ •
def insert_prefix():
if preset_list.get():
app.fixed_prompt_input.delete("0.0","end")
app.fixed_prompt_input.insert("0.0", yield_prefix.get("0.0", "end"))
show_prefix = customtkinter.CTkButton(preset_frame_right, text="Pre-fix", font=my_font, width=150, height=50, fg_color="grey10", hover_color="grey", command=insert_prefix)
show_prefix.grid(row = 5, column = 0, padx=5, pady=5, sticky="w")
yield_prefix = customtkinter.CTkTextbox(preset_frame_right, font=my_font, state="disabled",width=550, height=50, fg_color='#2B2B2B')
yield_prefix.grid(row = 5, column = 1, padx=5, pady=5, sticky="w")
def insert_postfix():
if preset_list.get():
app.fixed_prompt_after_input.delete("0.0","end")
app.fixed_prompt_after_input.insert("0.0", yield_postfix.get("0.0", "end"))
show_postfix = customtkinter.CTkButton(preset_frame_right, text="Post-fix", font=my_font, width=150, height=50, fg_color="grey10", hover_color="grey", command=insert_postfix)
show_postfix.grid(row = 6, column = 0, padx=5, pady=5, sticky="w")
yield_postfix = customtkinter.CTkTextbox(preset_frame_right, font=my_font, state="disabled",width=550, height=50, fg_color='#2B2B2B')
yield_postfix.grid(row = 6, column = 1, padx=5, pady=5, sticky="w")
def insert_negative():
if preset_list.get():
app.negative_prompt_input.delete("0.0","end")
app.negative_prompt_input.insert("0.0", yield_negative.get("0.0", "end"))
show_negative = customtkinter.CTkButton(preset_frame_right, text="Negative prompt", font=my_font, width=150, height=70, fg_color="grey10", hover_color="grey", command=insert_negative)
show_negative.grid(row = 7, column = 0, padx=5, pady=5, sticky="w")
yield_negative = customtkinter.CTkTextbox(preset_frame_right, font=my_font, state="disabled",width=550, height=70, fg_color='#2B2B2B')
yield_negative.grid(row = 7, column = 1, padx=5, pady=5, sticky="w")
def insert_autohide():
if preset_list.get():
app.auto_hide_keyword_input.delete("0.0","end")
app.auto_hide_keyword_input.insert("0.0", yield_autohide.get("0.0", "end"))
show_autohide = customtkinter.CTkButton(preset_frame_right, text="Hidden keyword", font=my_font, width=150, height=70, fg_color="grey10", hover_color="grey", command=insert_autohide)
show_autohide.grid(row = 8, column = 0, padx=5, pady=5, sticky="w")
yield_autohide = customtkinter.CTkTextbox(preset_frame_right, font=my_font, state="disabled",width=550, height=70, fg_color='#2B2B2B')
yield_autohide.grid(row = 8, column = 1, padx=5, pady=5, sticky="w")
def insert_rm():
if preset_list.get():
app.rm_artist_name_button.deselect()
app.rm_copyright_name_button.deselect()
app.rm_characteristic_button.deselect()
_text = yield_rm.cget("text")
if "์ž‘๊ฐ€๋ช…์ œ๊ฑฐ" in _text:
app.rm_artist_name_button.select()
if "์ž‘ํ’ˆ๋ช…์ œ๊ฑฐ" in _text:
app.rm_copyright_name_button.select()
if "์บ๋ฆญํ„ฐํŠน์ง•์ œ๊ฑฐ" in _text:
app.rm_characteristic_button.select()
show_rm = customtkinter.CTkButton(preset_frame_right, text="Options", font=my_font, width=150, fg_color="grey10", hover_color="grey", command=insert_rm)
show_rm.grid(row = 9, column = 0, padx=5, pady=5, sticky="w")
yield_rm = customtkinter.CTkLabel(preset_frame_right, text="", font=my_font, width=550)
yield_rm.grid(row = 9, column = 1, padx=5, pady=5, sticky="w")
def apply_all():
if preset_list.get():
insert_search()
insert_exclude()
insert_prompt()
insert_ratings()
insert_prefix()
insert_postfix()
insert_negative()
insert_autohide()
insert_rm()
apply_all = customtkinter.CTkButton(preset_frame_right, text="์ผ๊ด„์„ค์ •", font=my_font, width=150, command=apply_all)
apply_all.grid(row = 10, column = 0, padx=5, pady=5, sticky="w")
def remove_preset(self):
presets = self.presets
preset_name = preset_list.get()
if preset_name in presets:
del presets[preset_name]
save_preset(presets)
self.presets = load_preset()
update_list(self, self.presets)
remove_preset_button = customtkinter.CTkButton(preset_frame_right, text="์ด ํ”„๋ฆฌ์…‹์„ ์‚ญ์ œ", font=my_font, fg_color="grey10", hover_color="grey", command=lambda: remove_preset(self))
remove_preset_button.grid(row = 10, column =1, padx=5, pady=5, sticky="nsew")
def add_preset(self, presets):
preset_name = preset_insert_name_entry.get()
if len(preset_name.strip()) < 1:
preset_label.configure(text="ํ”„๋ฆฌ์…‹ ์ด๋ฆ„์„ ์ •ํ™•ํžˆ ์ž…๋ ฅํ•ด์ฃผ์„ธ์š”.", text_color="#FFFF97")
else:
preset = {
'preset_name':preset_name,
'description':preset_insert_description_entry.get(),
'search':app.search_label_entry.get(),
'exclude':app.exclude_label_entry.get(),
'prompt':app.text_input.get("0.0", "end-1c"),
'fix':app.fixed_prompt_input.get("0.0", "end-1c"),
'fix_after':app.fixed_prompt_after_input.get("0.0", "end-1c"),
'negative':app.negative_prompt_input.get("0.0", "end-1c"),
'auto_hide':app.auto_hide_keyword_input.get("0.0", "end-1c"),
'rm_artist':app.rm_artist_name_button.get(),
'rm_character':app.rm_characteristic_button.get(),
'rm_copyright':app.rm_copyright_name_button.get(),
'explicit':app.rating_select_explicit.get(),
'nsfw':app.rating_select_nsfw.get(),
'sensitive':app.rating_select_sensitive.get(),
'general':app.rating_select_general.get()
}
updated_preset = {preset_name: preset}
if self.presets:
updated_preset.update(self.presets)
else:
self.presets = updated_preset
save_preset(updated_preset)
self.presets = load_preset()
update_list(self, self.presets)
def update_list(self, presets):
if preset_list.size() != 0:
preset_list.delete(0, "END")
if presets:
for i, names in enumerate(presets.keys()):
preset_list.insert(i, names)
self.presets = presets
def save_preset(presets):
with open('NAIA_preset.json', 'w', encoding='utf-8') as f:
json.dump(presets, f, ensure_ascii=False, indent=4)
def load_preset():
try:
if os.path.exists('NAIA_preset.json'):
with open('NAIA_preset.json', 'r', encoding='utf-8') as f:
return json.load(f)
except FileNotFoundError:
return {}
def on_close(self):
self.withdraw()
presets = load_preset()
update_list(self, presets)
self.protocol("WM_DELETE_WINDOW", lambda: on_close(self))
class App(customtkinter.CTk):
access_token = None
NAI_ID = None
data = Data(wlist, tagbag, arti_list, copyright_list_reformatted, cd, remove_result_e, remove_result_qe)
def __init__(self):
super().__init__()
if getattr(sys, 'frozen', False):
basedir = sys._MEIPASS
else:
basedir = os.path.dirname(__file__)
ctypes.windll.gdi32.AddFontResourceW(os.path.abspath(os.path.join(basedir,"Pretendard-Bold.otf")))
ctypes.windll.gdi32.AddFontResourceW(os.path.abspath(os.path.join(basedir,"Pretendard-Regular.otf")))
my_font = customtkinter.CTkFont('Pretendard', 13)
large_font = customtkinter.CTkFont('Pretendard', 13)
v_large_font = customtkinter.CTkFont('Pretendard', 14, weight="normal")
#For Automation
self.auto_time_left = 0
self.auto_time_left_flag = False
self.auto_count_left = 0
self.auto_count_left_flag = False
self.delay_offset = 0
self.auto_thread = None
self.stop_event = None
self.start_time_prime = datetime.now()
self.start_time = self.start_time_prime.strftime('%Y%m%d_%H%M')
self.title("NAIA Alpha v1")
self.grid_rowconfigure(0, weight=1)
self.columnconfigure(2, weight=1)
windll.shcore.SetProcessDpiAwareness(1)
#๋””์ž์ธ: ์ƒ์šฉ ํ”„๋กœ๊ทธ๋žจ์˜ ์Šคํƒ€์ผ๊ณผ ์œ ์‚ฌํ•˜๋„๋ก UI๋ฅผ ์ƒˆ๋กญ๊ฒŒ ๊ฐœํŽธํ•œ๋‹ค.
self.left_frame = customtkinter.CTkScrollableFrame(self, width=510, height=960)
self.left_frame.grid(row=0, column=0, sticky="nsew")
self.right_frame = customtkinter.CTkScrollableFrame(self, width=768,height=960)
self.right_frame.grid(row=0, column=1, sticky="nsew")
self.hidden_frame = customtkinter.CTkFrame(self, width=250)
self.hidden_frame.grid(row=0, column=2, sticky="nsew")
self.image_label_report_sub = customtkinter.CTkTextbox(self.hidden_frame,width=250, height=500, font=large_font)
self.image_label_report_sub.grid(row=2, column=0, columnspan=2, pady=5, padx=5, sticky="nsew")
self.image_label_report_sub.configure(state="disabled")
self.state_label2 = customtkinter.CTkLabel(self.hidden_frame, text="state : idle", font=my_font)
self.state_label2.grid(row=8, column=0, columnspan=2, pady=5, padx=5, sticky="n")
self.hidden_frame.grid_forget()
def sync_text():
content = self.image_label_report.get("0.0", "end-1c").rstrip()
label = self.state_label.cget("text").rstrip()
label_sub = self.state_label2.cget("text").rstrip()
content_sub = self.image_label_report_sub.get("0.0", "end-1c").rstrip()
if content != content_sub:
self.image_label_report_sub.configure(state="normal")
self.image_label_report_sub.delete("0.0", "end")
self.image_label_report_sub.insert("0.0", content)
self.image_label_report_sub.configure(text_color=self.image_label_report.cget("text_color"),state="disabled")
if label != label_sub:
self.state_label2.configure(text=label, text_color=self.image_label_report.cget("text_color"))
self.after(500, sync_text)
#๊ฒ€์ƒ‰ ํ‚ค์›Œ๋“œ ์ฐฝ ๊ด€๋ฆฌ ํ”„๋ ˆ์ž„
self.search_frame = customtkinter.CTkFrame(self.left_frame)
self.search_frame.grid(row=0, column=0, sticky="nsew")
def open_AccountSetting(self):
if self.AccountSetting is None:
self.AccountSetting = AccountSetting(self)
else:
if self.AccountSetting.state() == 'withdrawn':
self.AccountSetting.deiconify()
else:
self.AccountSetting.NAI_ID_entry.focus()
def NAI_token_remove(self):
app.access_token = None
app.NAI_ID = None
if self.running_flag or self.automation_button.get()==1 or self.image_generation_button.cget("state") == "disabled":
self.image_label_report.configure(state="normal")
self.image_label_report.delete("0.0", "end")
self.image_label_report.insert("0.0", "<UserAttention> NAI ํ† ํฐ์˜ ์ œ๊ฑฐ๊ฐ€ ๊ฐ€๋Šฅํ•œ ์ƒํƒœ๊ฐ€ ์•„๋‹™๋‹ˆ๋‹ค. ๋ชจ๋“  ์ž‘์—…/์ž๋™ํ™” ์„ค์ •์„ ๋งˆ์น˜๊ณ  ์‹œ๋„ ํ•ด์ฃผ์„ธ์š”.")
self.image_label_report.configure(text_color="#FFFF97")
self.image_label_report.configure(state="disabled")
else:
app.NAI_Account_Login.configure(state="disabled")
app.NAI_Token_Remove.configure(state="disabled")
app.NAI_Account_State.configure(text="NAI Logout", text_color="red")
app.image_generation_button.configure(state="disabled")
self.image_label_report.configure(state="normal")
self.image_label_report.delete("0.0", "end")
self.image_label_report.insert("0.0", "<UserAttention> NAI ํ† ํฐ ์ œ๊ฑฐ ์™„๋ฃŒ(Logout). ํ”„๋กœ๊ทธ๋žจ์„ ์ •์ƒ์ ์œผ๋กœ ์ข…๋ฃŒ ํ›„ ์žฌ์‹คํ–‰ํ•ด์•ผ ๋ฐ˜์˜๋ฉ๋‹ˆ๋‹ค.")
self.image_label_report.configure(text_color="#FFFF97")
self.image_label_report.configure(state="disabled")
self.AccountSetting = None
#NAI ๊ณ„์ • ๊ด€๋ฆฌ ํ”„๋ ˆ์ž„
self.NAI_Account_Frame = customtkinter.CTkFrame(self.search_frame, width=440, height=50, bg_color="transparent")
self.NAI_Account_Frame.grid(row=0, column=0, padx=8, pady=5,sticky="nsew")
self.NAI_Account_Frame.columnconfigure(0, weight=6)
self.NAI_Account_Frame.columnconfigure(1, weight=4)
self.NAI_Account_Frame.columnconfigure(2, weight=4)
#NAI ๊ณ„์ • ๋กœ๊ทธ์ธ ์ƒํƒœ
self.NAI_Account_State = customtkinter.CTkLabel(self.NAI_Account_Frame, text="NAI Login : **** ", font=my_font)
#print(self.NAI_Account_State .cget("font"))
self.NAI_Account_State.grid(row=0, column=0, padx=20, sticky="w")
#NAI ๊ณ„์ • ๋กœ๊ทธ์ธ ๋ฒ„ํŠผ
self.NAI_Account_Login = customtkinter.CTkButton(self.NAI_Account_Frame, text="NAI ๊ณ„์ •์—ฐ๊ฒฐ", font=my_font, command=lambda: open_AccountSetting(self))
self.NAI_Account_Login.grid(row=0, column=1, padx=20, sticky="ew")
#NAI ํ† ํฐ ํ•ด์ œ ๋ฒ„ํŠผ
self.NAI_Token_Remove = customtkinter.CTkButton(self.NAI_Account_Frame, text="NAI ํ† ํฐ์ œ๊ฑฐ", state="disabled", fg_color="#848484", font=my_font, command=lambda: NAI_token_remove(self))
self.NAI_Token_Remove.grid(row=0, column=2,padx=20, sticky="ew")
#๊ฒ€์ƒ‰,์ œ์™ธ ํ‚ค์›Œ๋“œ ์ฐฝ
self.search_label = customtkinter.CTkLabel(self.search_frame, text="๊ฒ€์ƒ‰ ํ‚ค์›Œ๋“œ ์ž…๋ ฅ : keyword, *keyword, {keyword1|keyword2}", font=my_font)
self.search_label.grid(row=1, column=0, padx=8, sticky="w")
self.search_label_entry = customtkinter.CTkEntry(self.search_frame, width=490)
self.search_label_entry.grid(row=2, column=0, padx=8, sticky="w")
self.exclude_label = customtkinter.CTkLabel(self.search_frame, text="์ œ์™ธ ํ‚ค์›Œ๋“œ ์ž…๋ ฅ : keyword, ~keyword", font=my_font)
self.exclude_label.grid(row=3, column=0, padx=8, sticky="w")
self.exclude_label_entry = customtkinter.CTkEntry(self.search_frame, width=490)
self.exclude_label_entry.grid(row=4, column=0, padx=8, sticky="w")
#๊ฒ€์ƒ‰ ์ˆ˜์œ„ ๊ด€๋ฆฌ ์ฐฝ
self.select_rating_frame = customtkinter.CTkFrame(self.search_frame, width=490)
self.select_rating_frame.grid(row=6, column=0, padx=8, pady=10, sticky="nsew")
#๊ฒ€์ƒ‰ ์ˆ˜์œ„ ์ฒดํฌ๋ฐ•์Šค
self.rating_select_var_explicit = customtkinter.IntVar(value=1)
self.rating_select_var_nsfw = customtkinter.IntVar(value=1)
self.rating_select_var_sensitive = customtkinter.IntVar(value=1)
self.rating_select_var_general = customtkinter.IntVar(value=1)
self.rating_select_explicit = customtkinter.CTkCheckBox(self.select_rating_frame, width=85, text="Explicit", variable= self.rating_select_var_explicit, font=my_font)
self.rating_select_explicit.grid(row=0, column=0, sticky="ew")
self.rating_select_nsfw = customtkinter.CTkCheckBox(self.select_rating_frame, width=80,text="NSFW", variable= self.rating_select_var_nsfw, font=my_font)
self.rating_select_nsfw.grid(row=0, column=1, sticky="ew")
self.rating_select_sensitive = customtkinter.CTkCheckBox(self.select_rating_frame,width=90, text="Sensitive", variable= self.rating_select_var_sensitive, font=my_font)
self.rating_select_sensitive.grid(row=0, column=2, sticky="ew")
self.rating_select_general = customtkinter.CTkCheckBox(self.select_rating_frame,width=85, text="General", variable= self.rating_select_var_general, font=my_font)
self.rating_select_general.grid(row=0, column=3, sticky="e")
self.cached_rows = None
self.searching_flag = False
self.search_thread = None
def null_prompt_attention():
self.text_input.delete("0.0", "end")
self.text_input.insert("0.0", "ํ˜„์žฌ ์กฐ๊ฑด์— ๋งž๋Š” ํ”„๋กฌํ”„ํŠธ๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค.")
def prompt_search():
self.searching_flag = True
self.search_button.configure(text="๊ฒ€์ƒ‰ (์ž‘์—…์ค‘)", state="disabled")
search_thread = threading.Thread(target=perform_search, daemon=True)
self.search_thread = search_thread
search_thread.start()
def perform_search():
df = pd.read_parquet(os.path.join(basedir, "tags.parquet"), engine="pyarrow")
df = NAIA_search.search(df, self.search_label_entry.get(), self.exclude_label_entry.get(), self.rating_select_explicit.get(), self.rating_select_nsfw.get(), self.rating_select_sensitive.get(), self.rating_select_general.get())
if df is None:
null_prompt_attention() # ๋ฌธ์ž์—ด ๋น„์—ˆ๋‹ค๊ณ  ๊ฒฝ๊ณ 
else:
self.cached_rows = df
df.reset_index(drop=True, inplace=True)
update_labels(df)
self.searching_flag = False
self.search_button.configure(text="๊ฒ€์ƒ‰", state="normal")
def update_labels(df):
self.searched_prompt_label.configure(text="๊ฒ€์ƒ‰ ํ”„๋กฌํ”„ํŠธ ํ–‰ : " + str(len(self.cached_rows)))
self.cached_prompt_label.configure(text="๋‚จ์€ ํ”„๋กฌํ”„ํŠธ ํ–‰ : " + str(len(self.cached_rows)))
print(df.info(memory_usage="deep"))
#๊ฒ€์ƒ‰ ๋ฒ„ํŠผ
self.search_button = customtkinter.CTkButton(self.select_rating_frame, text="๊ฒ€์ƒ‰", font=my_font, command=prompt_search, width=130)
self.search_button.grid(row=0, column=4,padx=5, sticky="w")
#๊ฒ€์ƒ‰ ๊ฒฐ๊ณผ ๊ด€๋ฆฌ ์ฐฝ
self.searched_prompt_frame = customtkinter.CTkFrame(self.search_frame)
self.searched_prompt_frame.grid(row=7, column=0, padx=8, pady=5, sticky="nsew")
self.searched_prompt_frame.columnconfigure(0, weight= 1)
self.searched_prompt_frame.columnconfigure(1, weight= 1)
self.searched_prompt_frame.columnconfigure(2, weight= 1)
self.searched_prompt_label = customtkinter.CTkLabel(self.searched_prompt_frame, text="๊ฒ€์ƒ‰ ํ”„๋กฌํ”„ํŠธ ํ–‰ : 0", font=my_font)
self.searched_prompt_label.grid(row=0, column=0, sticky="ew")
self.cached_prompt_label = customtkinter.CTkLabel(self.searched_prompt_frame, text="๋‚จ์€ ํ”„๋กฌํ”„ํŠธ ํ–‰ : 0", font=my_font)
self.cached_prompt_label.grid(row=0, column=1, sticky="ew")
self.Preset_open = None
def open_Preset(self):
if self.Preset_open is None:
self.Preset_open = Preset_open(self)
else:
if self.Preset_open.state() == 'withdrawn':
self.Preset_open.deiconify()
else:
self.Preset_open.focus()
self.prompt_preset_button = customtkinter.CTkButton(self.searched_prompt_frame, width=120, text="ํ”„๋ฆฌ์…‹", fg_color="#848484", font=my_font, command= lambda: open_Preset(self))
self.prompt_preset_button.grid(row=0, column=2, padx=30, sticky="w")
def on_enter_pressed(event):
if self.control_pressed:
NAIA_generate(self)
return "break"
else:
pass
def on_tab_pressed(event):
if self.toggle_prompt_fix_button.get() == 0:
time.sleep(0.2)
random_function()
#ํ…์ŠคํŠธ ์ž…๋ ฅ
self.text_input_frame = customtkinter.CTkFrame(self.searched_prompt_frame)
self.text_input_frame.grid(row=1, column=0, columnspan=3, sticky="nsew")
self.text_input_label = customtkinter.CTkLabel(self.text_input_frame, text=" ----------------------------- ํ”„๋กฌํ”„ํŠธ ----------------------------- ", font=large_font)
self.text_input_label.grid(row = 0, sticky="n" )
self.text_input = customtkinter.CTkTextbox(self.text_input_frame, width=490, font=v_large_font)
self.text_input.grid(row=1, column=0, pady=5, sticky="nsew")
self.text_input.bind("<Return>", on_enter_pressed)
self.text_input.bind("<Tab>", on_tab_pressed)
def random_function():
if(self.random_function_pressed) == False:
self.random_function_pressed = True
self.random_function_button.configure(state="disabled")
if self.toggle_prompt_fix.get()==0 and type(self.cached_rows) == type(None):
self.text_input.delete("0.0", "end")
self.text_input.insert("0.0", "๋จผ์ € ํ‚ค์›Œ๋“œ ๊ฒ€์ƒ‰์„ ํ•ด ์ฃผ์„ธ์š”.")
self.random_function_button.configure(state="normal")
self.random_function_pressed = False
return
if self.toggle_prompt_fix.get()==1 and type(self.cached_rows) == type(None):
self.random_function_pressed = False
return
elif self.toggle_prompt_fix.get()==0 and self.cached_rows.empty:
if (self.automation_button.get() == 0):
self.text_input.delete("0.0", "end")
self.text_input.insert("0.0", "๋จผ์ € ํ‚ค์›Œ๋“œ ๊ฒ€์ƒ‰์„ ํ•ด ์ฃผ์„ธ์š”.")
self.random_function_button.configure(state="normal")
self.random_function_pressed = False
return
else:
self.text_input.delete("0.0", "end")
self.text_input.insert("0.0", "์žฌ๊ฒ€์ƒ‰์„ ์ˆ˜ํ–‰ํ•ฉ๋‹ˆ๋‹ค.")
prompt_search()
while(self.cached_rows.empty):
time.sleep(1)
self.random_function_button.configure(state="normal")
self.random_function_pressed = False
app.after(0, random_function)
return
if self.toggle_prompt_fix.get():
self.random_function_pressed = False
return
else:
if self.random_artist_button.get() == 1:
try:
if self.random_artist_prefix.get() == "artist:":
random_artist_name = "artist:"+ random.choice(self.random_artist)
elif self.random_artist_prefix.get() == "(artist)":
random_artist_name = random.choice(self.random_artist)+" (artist)"
else:
random_artist_name = random.choice(self.random_artist)
except:
random_artist_name = ""
magic_word = {
"random_artist":True,
"random_artist_name": random_artist_name
}
else:
magic_word = {
"random_artist":False
}
random_index = np.random.choice(self.cached_rows.index)
#print(random_index)
popped_row = self.cached_rows.loc[random_index]
self.cached_rows.drop(random_index, inplace=True)
self.cached_prompt_label.configure(text = "๋‚จ์€ ํ”„๋กฌํ”„ํŠธ ํ–‰ : "+str(len(self.cached_rows)))
prompt = NAIA_random_function_core.RFP(popped_row, self.fixed_prompt_input.get("0.0", "end"), self.fixed_prompt_after_input.get("0.0", "end"), self.auto_hide_keyword_input.get("0.0", "end")
,self.rm_artist_name_button.get(), self.rm_copyright_name_button.get(),self.rm_characteristic_button.get(), self.rm_not_nsfw_button.get(), self.data, magic_word)
self.text_input.delete("0.0", "end")
self.text_input.insert("0.0", prompt)
app.after(100, lambda: self.random_function_button.configure(state="normal"))
self.random_function_pressed = False
self.random_function_pressed = False
self.running_flag = False
self.error_count = 0
self.turbo_fail_count = 0
self.anlas_request = False
def NAIA_generate(self):
if self.seed_fix_button.get() == 0:
self.entry_seed_value.set(random.randint(0,9999999999))
if self.random_resolution_button.get() == 1:
resolutions = ["1024 x 1024", "960 x 1088", "896 x 1152", "832 x 1216", "1088 x 960", "1152 x 896", "1216 x 832"]
random_resolution = random.choice(resolutions)
self.resolution_button.set(random_resolution)
if self.cached_rows is None and self.toggle_prompt_fix_button.get() == 0 and self.automation_button.get() == 1:
self.state_label.configure(text ="state : ์ž๋™ํ™” ์ „ ํ”„๋กฌํ”„ํŠธ ๊ฒ€์ƒ‰์„ ์ˆ˜ํ–‰ํ•˜๋Š” ์ค‘ ์ž…๋‹ˆ๋‹ค", text_color = "#FFFF97")
prompt_search()
if self.turbo_button.get() == 1:
origin = self.text_input.get("0.0", "end-1c")
pretest = [keyword.strip() for keyword in origin.split(',')]
if (('sex' not in pretest and 'group sex' not in pretest) or ('1girl' not in pretest and 'girls' not in origin[:20]) or ('1boy' not in pretest and 'boys' not in origin[:20])):
self.image_label_report.configure(state="normal")
self.image_label_report.delete("0.0", "end")
self.image_label_report.insert("0.0", "<UserAttention> Explicit Turbo ๊ธฐ๋Šฅ์€ ํ”„๋กฌํ”„ํŠธ ๋‚ด์— 1girl/girls, 1boy/boys, sex/group sex๊ฐ€ ์กด์žฌํ•  ๋•Œ ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค.")
self.turbo_fail_count += 1
if self.turbo_fail_count >= 20:
self.turbo_button.deselect()
self.image_label_report.configure(text_color="#FFFF97")
self.image_label_report.configure(state="disabled")
if self.automation_button.get() == 1 and self.toggle_prompt_fix_button.get() == 0:
random_function()
time.sleep(0.5)
if self.searching_flag == True:
self.search_thread.join()
return self.event_generate(GENERATE_EVENT, when="tail")
elif self.automation_button.get() == 1 and self.toggle_prompt_fix_button.get() == 1:
self.automation_button.deselect()
return
else:
return
else:
self.turbo_fail_count = 0
if not self.running_flag:
self.image_generation_button.configure(state="disabled")
self.running_flag = True
NAI_width, NAI_height = self.resolution_button.get().split(' x ')
NAI_width = str((int(NAI_width) // 64) * 64)
NAI_height = str((int(NAI_height) // 64) * 64)
if int(NAI_height) * int(NAI_width) > 1048576:
self.image_label_report.configure(state="normal")
self.image_label_report.delete("0.0", "end")
self.image_label_report.insert("0.0", "<UserAttention> Anlas๊ฐ€ ์†Œ๋ชจ๋˜๋Š” ํ•ด์ƒ๋„ ์š”์ฒญ์ž…๋‹ˆ๋‹ค.")
self.image_label_report.configure(text_color="#FFFF97")
self.image_label_report.configure(state="disabled")
self.anlas_request = True
scale_pre = self.cfg_scale_entry.get()
try:
scale_pre = float(scale_pre)
except:
scale_pre = 5.0
self.cfg_scale_var.set("5.0")
rescale_pre = self.prompt_guidance_rescale_entry.get()
try:
rescale_pre = float(rescale_pre)
except:
rescale_pre = 0
self.prompt_guidance_rescale_var.set("0")
#### ์—ฌ๊ธฐ์„œ๋ถ€ํ„ฐ ์™€์ผ๋“œ์นด๋“œ ์ฒ˜๋ฆฌ ๊ตฌ๋ฌธ ####
before_wildcard = self.text_input.get("0.0", "end-1c")
before_wildcard = [item.strip() for item in before_wildcard.split(',')]
if '<' in self.text_input.get("0.0", "end-1c"):
#### ๋‹จ๊ณ„ 1 : ์ธ์Šคํ„ดํŠธ ์™€์ผ๋“œ์นด๋“œ ์ฒ˜๋ฆฌ ###
for i, keyword in enumerate(before_wildcard):
if keyword.startswith('<') and keyword.endswith('>'):
vbar_check = keyword[1:-1]
if '|' in vbar_check:
choices = vbar_check.split('|') # '|'๋ฅผ ๊ธฐ์ค€์œผ๋กœ split
choice_dic = {}
for choice in choices:
match = re.match(r'(\d*\.?\d+):(.+)', choice)
if match:
value, keyword = float(match.group(1)), match.group(2).strip()
else:
value, keyword = 1, choice.strip()
choice_dic[keyword] = value
keywords = list(choice_dic.keys())
weights = list(choice_dic.values())
selected_instant_wildcard = random.choices(keywords, weights=weights, k=1)[0]
before_wildcard[i] = selected_instant_wildcard
#### ๋‹จ๊ณ„ 2 : ๊ธ€๋กœ๋ฒŒ ์™€์ผ๋“œ์นด๋“œ ์ฒ˜๋ฆฌ ###
for i, keyword in enumerate(before_wildcard):
if "<" in keyword:
input_str = keyword.strip('<>').strip()
if("__" in input_str):
adjectives = re.findall(r'__(.*?)__', input_str)
last_keyword = re.split(r'__.*?__', input_str)[-1]
adjective_string = ""
for adjective in adjectives:
adjective_string += (self.get_wildcard(adjective) + " ")
before_wildcard[i] = adjective_string + self.get_wildcard(last_keyword)
else:
before_wildcard[i] = self.get_wildcard(input_str)
else:
after_wildcard = self.text_input.get("0.0", "end-1c")
after_wildcard = ', '.join(before_wildcard)
##############################
gen_request = {
"width":NAI_width,
"height":NAI_height,
"quality_toggle":self.auto_quality_toggle.get(),
"seed":self.seed_entry.get(),
"sampler":self.sampler_button.get(),
"scale":scale_pre,
"sema":self.sema_button.get(),
"sema_dyn": self.dyn_button.get(),
"cfg_rescale": rescale_pre,
"prompt": after_wildcard,
"negative":self.negative_prompt_input.get("0.0", "end-1c"),
"user_screen_size": self.get_max_size(),
"start_time": self.start_time,
"access_token": self.access_token,
"save_folder": self.output_file_path,
"png_rule": self.name_var.get(),
"type": "normal"
}
if self.turbo_button.get() == 1:
request_list = []
treq_0, treq_1, treq_2, treq_3 = NAIA_generation.make_turbo_prompt(gen_request)
request_list.append(gen_request)
request_list.append(treq_0)
request_list.append(treq_1)
request_list.append(treq_2)
request_list.append(treq_3)
def run_generation():
if gen_request["png_rule"] == "count":
self.generation_count += 1
gen_request["count"] =self.generation_count
if app.auto_count_left_flag == True:
app.auto_count_left -= 1
app.image_generation_button.configure(border_width = 2)
self.state_label.configure(text ="state : NAI ์ด๋ฏธ์ง€ ์ƒ์„ฑ ๋Œ€๊ธฐ์ค‘ ... ", text_color = "#FFFF97")
result_image, result_prompt, result_seed, info, filename = NAIA_generation.generate(gen_request)
self.state_label.configure(text ="state : idle", text_color = "#DCE4EE")
app.image_generation_button.configure(border_width = 0)
if self.anlas_request:
self.anlas_request = False
self.get_anlas()
if info:
self.error_count = 0
temp = info.get('Comment', '')
temp = temp[temp.find("prompt")+10:temp.find("skip_cfg_below_sigma")-3].replace('"','')
else:
self.error_count += 1
if self.error_count >= 5:
self.automation_button.deselect()
temp = result_prompt
self.running_flag = False
self.image_label_report.configure(state="normal")
self.image_label_report.delete("0.0", "end")
self.image_label_report.configure(text_color="#DCE4EE")
self.image_label_report.insert("0.0", temp)
self.image_label_report.configure(state="disabled")
if result_image:
if app.state() != 'zoomed':
instant_result_image = customtkinter.CTkImage(result_image, size=(620,620))
else:
current_image = Image.open(filename)
original_width, original_height = current_image.size
max_size = app.winfo_screenheight()-100
if original_width > max_size or original_height > max_size:
new_image = Image.new("RGB", (max_size, max_size), "black")
new_image.paste(current_image, ((max_size - original_width) // 2, (max_size - original_height) // 2))
instant_result_image = customtkinter.CTkImage(new_image, size=(max_size, max_size))
else:
instant_result_image = customtkinter.CTkImage(current_image, size=(max_size, max_size))
self.image_label.configure(image=instant_result_image)
set_image_to_queue(result_image, result_prompt, result_seed, filename)
#์ž๋™ํ™” ์ฒดํฌ
if self.automation_button.get() == 1:
instant_wait = random.uniform(4.5, 8.5) + self.delay_offset
if instant_wait < 0 : instant_wait = 0.5
if self.toggle_prompt_fix_button.get() == 0:
random_function()
while(instant_wait > 0):
self.image_generation_button.configure(text=f"NAI ์ด๋ฏธ์ง€ ์ƒ์„ฑ ({round(instant_wait)})")
if instant_wait >= 1:
time.sleep(1)
else:
time.sleep(instant_wait)
instant_wait -= 1
self.image_generation_button.configure(text="NAI ์ด๋ฏธ์ง€ ์ƒ์„ฑ")
if self.automation_button.get() == 1:
self.event_generate(GENERATE_EVENT, when="tail")
else:
self.image_generation_button.configure(state="normal")
else:
self.image_generation_button.configure(state="normal")
def run_generation_turbo(gen_request):
if gen_request["png_rule"] == "count":
self.generation_count += 1
gen_request["count"] =self.generation_count
if app.auto_count_left_flag == True:
app.auto_count_left -= 1
app.image_generation_button.configure(border_width = 2)
self.state_label.configure(text ="state : NAI ์ด๋ฏธ์ง€ ์ƒ์„ฑ ๋Œ€๊ธฐ์ค‘ (EXP.turbo) ... ", text_color = "#FFFF97")
result_image, result_prompt, result_seed, info, filename = NAIA_generation.generate(gen_request)
self.state_label.configure(text ="state : idle", text_color = "#DCE4EE")
app.image_generation_button.configure(border_width = 0)
if info:
self.error_count = 0
temp = info.get('Comment', '')
temp = temp[temp.find("prompt")+10:temp.find("skip_cfg_below_sigma")-3].replace('"','')
else:
self.error_count += 1
if self.error_count >= 5:
self.automation_button.deselect()
self.turbo_button.deselect()
temp = result_prompt
self.running_flag = False
self.image_label_report.configure(state="normal")
self.image_label_report.delete("0.0", "end")
self.image_label_report.configure(text_color="#DCE4EE")
self.image_label_report.insert("0.0", temp)
self.image_label_report.configure(state="disabled")
if result_image:
if app.state() != 'zoomed':
instant_result_image = customtkinter.CTkImage(result_image, size=(620,620))
else:
current_image = Image.open(filename)
original_width, original_height = current_image.size
max_size = app.winfo_screenheight()-100
if original_width > max_size or original_height > max_size:
new_image = Image.new("RGB", (max_size, max_size), "black")
new_image.paste(current_image, ((max_size - original_width) // 2, (max_size - original_height) // 2))
instant_result_image = customtkinter.CTkImage(new_image, size=(max_size, max_size))
else:
instant_result_image = customtkinter.CTkImage(current_image, size=(max_size, max_size))
self.image_label.configure(image=instant_result_image)
set_image_to_queue(result_image, result_prompt, result_seed, filename)
instant_wait = random.uniform(4.5, 8.5) + self.delay_offset
if instant_wait < 0 : instant_wait = 0.5
while(instant_wait > 0):
self.image_generation_button.configure(text=f"NAI ์ด๋ฏธ์ง€ ์ƒ์„ฑ ({round(instant_wait)})")
if instant_wait >= 1:
time.sleep(1)
else:
time.sleep(instant_wait)
instant_wait -= 1
self.image_generation_button.configure(text="NAI ์ด๋ฏธ์ง€ ์ƒ์„ฑ")
def turbo_process_request():
turbo_count = 0
while(request_list):
gen_request = request_list.pop(0) #length=5
generation_thread = threading.Thread(target=run_generation_turbo, args=(gen_request,), daemon=True)
generation_thread.start()
generation_thread.join()
turbo_count += 1
if app.turbo_button.get() == 0:
app.state_label.configure(text =f"state : ์‚ฌ์šฉ์ž์— ์˜ํ•œ ํ„ฐ๋ณด์š”์ฒญ ์ค‘๋‹จ ({turbo_count})", text_color = "#FFFF97")
break
if self.automation_button.get() == 1:
if self.toggle_prompt_fix_button.get() == 0:
random_function()
self.event_generate(GENERATE_EVENT, when="tail")
else:
self.image_generation_button.configure(state="normal")
if self.turbo_button.get() == 0:
generation_thread = threading.Thread(target=run_generation, daemon=True)
generation_thread.start()
else:
turbo_process_request_thread = threading.Thread(target=turbo_process_request, daemon=True)
turbo_process_request_thread.start()
def open_AutomationSetting(self):
if self.Automation_setting is None:
self.Automation_setting = Automation_setting(self)
else:
if self.Automation_setting.state() == 'withdrawn':
self.Automation_setting.deiconify() # ์ˆจ๊ฒจ์ง„ ์œˆ๋„์šฐ๋ฅผ ๋‹ค์‹œ ํ™”๋ฉด์— ํ‘œ์‹œ
else:
self.Automation_setting.focus()
def show_advanced_settings(self):
if self.Advanced_setting is None:
self.Advanced_setting = Advanced_setting(self)
else:
if self.Advanced_setting.state() == 'withdrawn':
self.Advanced_setting.deiconify()
else:
self.Advanced_setting.focus()
def open_Character_search(self):
if self.Character_search is None:
if not os.path.exists("csdataset.parquet"):
make_parquet(self)
self.Character_search = Character_search(self)
else:
if self.Character_search.state() == 'withdrawn':
self.Character_search.deiconify()
else:
self.Character_search.focus()
def make_parquet(self):
filtered_dfs = []
df = pd.read_parquet(os.path.join(basedir, "tags.parquet"),engine="pyarrow")
filtered_df = df[df['general'].str.contains(' solo,', na=False) & ~df['general'].str.contains('monochrome', na=False)]
filtered_dfs.append(filtered_df)
final_df = pd.concat(filtered_dfs, ignore_index=True)
final_df.to_parquet("csdataset.parquet")
self.Advanced_setting = None
self.Automation_setting = None
self.Character_search = None
#์ด๋ฏธ์ง€ ์ƒ์„ฑ ํ”„๋ ˆ์ž„
self.image_generation_frame = customtkinter.CTkFrame(self.text_input_frame)
self.image_generation_frame.grid(row=2, column=0, sticky="nsew")
self.image_generation_frame.columnconfigure(0, weight= 1)
self.image_generation_frame.columnconfigure(1, weight= 1)
self.image_generation_frame.columnconfigure(2, weight= 1)
self.random_function_button = customtkinter.CTkButton(self.image_generation_frame, text="๋žœ๋ค/๋‹ค์Œ ํ”„๋กฌํ”„ํŠธ", font=my_font, command=random_function)
self.random_function_button.grid(row=0, column=0, pady=5, sticky="nsew")
self.automation_setting_button = customtkinter.CTkButton(self.image_generation_frame, text="์ž๋™ํ™” ์„ค์ •", fg_color="#CDCDCD", text_color="black", hover_color="#848484", font=my_font, command=lambda: open_AutomationSetting(self))
self.automation_setting_button.grid(row=0, column=1, padx=15, sticky="ew")
self.image_generation_button = customtkinter.CTkButton(self.image_generation_frame, text="NAI ์ด๋ฏธ์ง€ ์ƒ์„ฑ", fg_color="#ED7D31", hover_color="#CC5D12", font=my_font, state="disabled", command=lambda: NAIA_generate(self), text_color_disabled="black")
self.image_generation_button.grid(row=0, column=2, pady=5, sticky="nsew")
def hold_prompt():
if self.toggle_prompt_fix_button.get() == 1:
if self.unlock_hold_prompt_var.get() == 0:
self.fixed_prompt_input.configure(state="disabled", text_color="#A2B8D2")
self.fixed_prompt_after_input.configure(state="disabled", text_color="#A2B8D2")
self.random_function_button.configure(state="disabled")
self.rm_not_nsfw_button.deselect()
self.rm_not_nsfw_button.configure(state="disabled")
self.random_artist_button.deselect()
self.random_artist_button.configure(state="disabled")
self.unlock_hold_prompt.configure(state="normal")
else:
self.fixed_prompt_input.configure(state="normal", text_color="#DCE4EE")
self.fixed_prompt_after_input.configure(state="normal", text_color="#DCE4EE")
self.random_function_button.configure(state="normal")
self.rm_not_nsfw_button.configure(state="normal")
self.random_artist_button.configure(state="normal")
def explicit_user_attention():
if self.turbo_button.get() == 1:
self.image_label_report.configure(state="normal")
self.image_label_report.delete("0.0","end")
self.image_label_report.insert("0.0", "<UserAttention> Explicit turbo ์ƒ์„ฑ ๋„์ค‘ ์ค‘๋‹จ ํฌ๋ง์‹œ ์ฒดํฌ๋ฐ•์Šค๋ฅผ ํ•ด์ œ ํ•˜์‹œ๊ธฐ ๋ฐ”๋ž๋‹ˆ๋‹ค.")
self.image_label_report.configure(text_color="#FFFF97")
self.image_label_report.configure(state="disabled")
else:
self.image_label_report.configure(text_color="#DCE4EE")
self.toggle_prompt_fix = customtkinter.IntVar()
self.toggle_prompt_fix_button = customtkinter.CTkCheckBox(self.image_generation_frame, text="ํ”„๋กฌํ”„ํŠธ ๊ณ ์ •", variable=self.toggle_prompt_fix, font=my_font, command=hold_prompt)
self.toggle_prompt_fix_button.grid(row=1, column=0, sticky="ew", padx=15, pady=5)
self.automation = customtkinter.IntVar()
self.automation_button = customtkinter.CTkCheckBox(self.image_generation_frame, text="์ž๋™ํ™”", variable=self.automation, font=my_font)
self.automation_button.grid(row=1, column=1, sticky="ew", padx=15)
self.turbo = customtkinter.IntVar()
self.turbo_button = customtkinter.CTkCheckBox(self.image_generation_frame, text="์—ฐ์† ์ด๋ฏธ์ง€ ์ƒ์„ฑ(Explicit)", variable=self.turbo, font=my_font, command=explicit_user_attention)
self.turbo_button.grid(row=1, column=2, sticky="ew")
self.fixed_prompt_label = customtkinter.CTkLabel(self.text_input_frame, text=" ----------------------------- ์„ ํ–‰ ๊ณ ์ • ํ”„๋กฌํ”„ํŠธ ----------------------------- ", font=large_font)
self.fixed_prompt_label.grid(row = 3, column=0, sticky="n" )
self.fixed_prompt_input = customtkinter.CTkTextbox(self.text_input_frame, width=490, height=100, font=v_large_font)
self.fixed_prompt_input.grid(row=4, column=0, pady=5, sticky="nsew")
#์ž‘๊ฐ€๋ช… ์ œ๊ฑฐ ๋ฐ ๊ธฐํƒ€ ๊ธฐ๋Šฅ
self.check_box_frame = customtkinter.CTkFrame(self.text_input_frame)
self.check_box_frame.grid(row=5, column=0, pady=5, columnspan=3, sticky="nsew")
self.rm_artist_name_var = customtkinter.IntVar()
self.rm_artist_name_button = customtkinter.CTkCheckBox(self.check_box_frame, text="์ž‘๊ฐ€๋ช… ์ œ๊ฑฐ", variable=self.rm_artist_name_var, font=my_font)
self.rm_artist_name_button.grid(row=0, column=0, pady=5, padx=10, sticky="nsew")
self.rm_copyright_name_var = customtkinter.IntVar()
self.rm_copyright_name_button = customtkinter.CTkCheckBox(self.check_box_frame, text="์ž‘ํ’ˆ๋ช… ์ œ๊ฑฐ", variable=self.rm_copyright_name_var, font=my_font)
self.rm_copyright_name_button.grid(row=0, column=1, pady=5, sticky="nsew")
self.rm_characteristic_var = customtkinter.IntVar()
self.rm_characteristic_button = customtkinter.CTkCheckBox(self.check_box_frame, text="์บ๋ฆญํ„ฐ ํŠน์ง• ์ œ๊ฑฐ", variable=self.rm_characteristic_var, font=my_font)
self.rm_characteristic_button.grid(row=0, column=2, padx=10, pady=5, sticky="nsew")
self.rm_not_nsfw_var = customtkinter.IntVar()
self.rm_not_nsfw_button = customtkinter.CTkCheckBox(self.check_box_frame, text="NSFW Only", variable=self.rm_not_nsfw_var, font=my_font)
self.rm_not_nsfw_button.grid(row=0, column=3, padx=15, pady=5, sticky="nsew")
self.fixed_prompt_after_label = customtkinter.CTkLabel(self.text_input_frame, text=" ----------------------------- ํ›„ํ–‰ ๊ณ ์ • ํ”„๋กฌํ”„ํŠธ ----------------------------- ", font=large_font)
self.fixed_prompt_after_label.grid(row = 6, column=0, sticky="n" )
self.fixed_prompt_after_input = customtkinter.CTkTextbox(self.text_input_frame, width=490, height=60, font=v_large_font)
self.fixed_prompt_after_input.grid(row=7, column=0, pady=5, sticky="nsew")
self.negative_prompt_label = customtkinter.CTkLabel(self.text_input_frame, text=" ----------------------------- ๋„ค๊ฑฐํ‹ฐ๋ธŒ ํ”„๋กฌํ”„ํŠธ ----------------------------- ", font=large_font)
self.negative_prompt_label.grid(row = 8, column=0, sticky="n" )
self.negative_prompt_input = customtkinter.CTkTextbox(self.text_input_frame, width=490, height=100, font=v_large_font)
self.negative_prompt_input.insert("0.0", "lowres, jpeg artifacts, worst quality, watermark, blurry, very displeasing")
self.negative_prompt_input.grid(row=9, column=0, pady=5, sticky="nsew")
self.auto_hide_label = customtkinter.CTkLabel(self.text_input_frame, text="----------------------------- ์ž๋™์ˆจ๊น€ ํ‚ค์›Œ๋“œ -----------------------------", font=my_font)
self.auto_hide_label.grid(row = 10, column=0, sticky="n" )
self.auto_hide_keyword_input = customtkinter.CTkTextbox(self.text_input_frame, width=490, height=100, font=v_large_font)
self.auto_hide_keyword_input.grid(row=11, column=0, pady=5, sticky="nsew")
self.auto_quality_toggle_var = customtkinter.IntVar()
self.auto_quality_toggle =customtkinter.CTkCheckBox(self.text_input_frame, text="Auto Quality Tag ํ™œ์„ฑํ™” (Undesired Content Preset์€ ์ œ์™ธ)", font=my_font, variable=self.auto_quality_toggle_var)
self.auto_quality_toggle.grid(row = 12, column = 0, pady=5, sticky="w")
self.auto_quality_toggle.select()
self.unlock_hold_prompt_var = customtkinter.IntVar()
def unlock_hold():
if self.unlock_hold_prompt_var.get() == 1:
self.fixed_prompt_input.configure(state="normal", text_color="#DCE4EE")
self.fixed_prompt_after_input.configure(state="normal", text_color="#DCE4EE")
elif self.unlock_hold_prompt_var.get() == 0 and self.toggle_prompt_fix_button.get() == 1:
self.fixed_prompt_input.configure(state="disabled", text_color="#A2B8D2")
self.fixed_prompt_after_input.configure(state="disabled", text_color="#A2B8D2")
self.unlock_hold_prompt = customtkinter.CTkCheckBox(self.text_input_frame, text="ํ”„๋กฌํ”„ํŠธ ๊ณ ์ •: ์„ ํ–‰/ํ›„ํ–‰/๋žœ๋ค ํ”„๋กฌํ”„ํŠธ ์ž ๊ธˆ ๊ฐ•์ œํ•ด์ œ ", font=my_font, variable=self.unlock_hold_prompt_var, state="disabled", command=unlock_hold)
self.unlock_hold_prompt.grid(row = 13, column = 0, pady=5, sticky="w")
self.unlock_hold_prompt.deselect()
self.unlock_hold_prompt_label = customtkinter.CTkLabel(self.text_input_frame, text="*์ž ๊ธˆ์„ ํ•ด์ œํ•˜๋”๋ผ๋„ ์„ ํ–‰/ํ›„ํ–‰ ๊ณ ์ • ํ”„๋กฌํ”„ํŠธ๊ฐ€ ํ”„๋กฌํ”„ํŠธ์ฐฝ์— ๋ฐ˜์˜๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.", font=large_font)
self.unlock_hold_prompt_label.grid(row = 14, column = 0, pady=5, sticky="w")
#์ด๋ฏธ์ง€ ํžˆ์Šคํ† ๋ฆฌ
self.image_history_frame = customtkinter.CTkFrame(self.right_frame)
self.image_history_frame.grid(row=0, column=0, columnspan=2, rowspan=15, padx=5, pady=5, sticky="n")
#์ด๋ฏธ์ง€ ๋ ˆ์ด๋ธ”
self.image_label = customtkinter.CTkLabel(self.image_history_frame, text="")
self.image_label.grid(row=1, column=0, rowspan=14, padx=10, pady=5, sticky="w")
self.image_label_report = customtkinter.CTkTextbox(self.right_frame, width=740, height=100, font=large_font)
#image_label_report.insert("0.0", "1girl, {{minato aqua, ahoge, blue hair, braid, colored inner hair}}, artist:healthyman, [[[[[[[[[[artist:mikozin]]]]]]]]]], [[[artist:lakilolom]]], [[[[artist:crumbles]]]], [[artist:tianliang_duohe_fangdongye]], breasts, dutch angle, gloves, groin, gun, handgun, looking at viewer, nipples, no panties, one eye closed, skirt, smile, solo, topless, weapon, commentary request, highres, nsfw, great quality, aesthetic, absurdres, retouched, smooth lines, excellent color, suitable texture (SEED:22222222222), This text is sample, not an output of the actual generated result.")
self.image_label_under_frame = customtkinter.CTkFrame(self.image_history_frame)
self.image_label_under_frame.grid(row=0, column=0, padx=10, pady=5, sticky="ew")
self.open_save_folder = customtkinter.CTkButton(self.image_label_under_frame, text="ํด๋” ์—ด๊ธฐ", font=my_font, fg_color="transparent", width=60,command=lambda: open_file_explorer(self))
self.open_save_folder.grid(row=0, column=0,padx=5, pady=5, sticky="nsew")
self.window_label = customtkinter.CTkLabel(self.image_label_under_frame, text="0 / 0", font=my_font, width=60)
self.window_label.grid(row=0, column=4,padx=5, pady=5, sticky="nsew")
self.my_anlas = customtkinter.IntVar(value=0)
self.anlas_label = customtkinter.CTkLabel(self.image_label_under_frame, text="Anlas : 0", font=my_font)
self.anlas_label.grid(row=0, column=5,padx=5, pady=5, sticky="nsew")
self.request_upper_size_button = customtkinter.CTkButton(self.image_label_under_frame, text="๊ณ ํ•ด์ƒ๋„ ์ด๋ฏธ์ง€ ์š”์ฒญ (Anlas ์†Œ๋ชจ)",fg_color="transparent", hover_color="grey10", font=my_font,state="disabled", width=180, command=lambda: instant_image_generation(self))
self.request_upper_size_button.grid(row=0, column=6,padx=5, pady=5, sticky="nsew")
self.request_upper_size_seed_hold_var = customtkinter.IntVar(value=1)
self.request_upper_size_seed_hold = customtkinter.CTkCheckBox(self.image_label_under_frame, text="์‹œ๋“œ๊ณ ์ • Step : ", font=my_font, variable=self.request_upper_size_seed_hold_var)
self.request_upper_size_seed_hold.grid(row=0, column=7,padx=5, pady=5, sticky="nsew")
self.request_upper_size_steps = customtkinter.StringVar(value="28")
self.request_upper_size_steps_entry = customtkinter.CTkEntry(self.image_label_under_frame, font=my_font, textvariable=self.request_upper_size_steps, width=60)
self.request_upper_size_steps_entry.grid(row=0, column=8,padx=5, pady=5, sticky="nsew")
self.image_label_report.grid(row=16, column=0, padx=10, pady=5, sticky="ew")
self.image_label_report.configure(state="disabled")
white_image = Image.new('RGB', (768, 768), 'white')
#white_image =Image.open("sample_image.jpg")
white_photo = customtkinter.CTkImage(white_image, size=(620,620))
self.image_label.configure(image=white_photo)
self.image_label.image = white_photo
self.image_queue = []
self.window = 0
#image history ๋ฒ„ํŠผ
self.image_history_sub_frame = customtkinter.CTkFrame(self.image_history_frame, width=100, height=550)
self.image_history_sub_frame.grid(row=1, rowspan=12, column=1, sticky="n")
self.output_file_path = f"output_NAI\\{self.start_time}\\txt2img"
def open_file_explorer(self):
if not os.path.exists(self.output_file_path):
os.makedirs(self.output_file_path)
os.startfile(self.output_file_path)
def up_button_pressed():
if self.image_history_button_down.cget("state") == "disabled":
self.image_history_button_down.configure(state="normal")
if self.control_pressed:
self.window = len(self.image_queue)
else:
self.window+=1
update()
show_text = str(self.window)+" / "+ str(len(self.image_queue))
self.window_label.configure(text=show_text)
if self.window >= len(self.image_queue):
self.image_history_button_up.configure(state="disabled")
self.control_pressed = False
image_history_0_yield()
def down_button_pressed():
if self.image_history_button_up.cget("state") == "disabled":
self.image_history_button_up.configure(state="normal")
if self.control_pressed:
if self.window >= 105:
self.window -= 100
else:
self.window = 5
else:
self.window-=1
update()
show_text = str(self.window)+" / "+ str(len(self.image_queue))
self.window_label.configure(text=show_text)
if self.window <= 5:
self.image_history_button_down.configure(state="disabled")
self.control_pressed = False
image_history_4_yield()
self.current_window = None
def set_image_to_queue(imagen, prompt, seed, filename):
self.image_queue.append([imagen, prompt, seed, filename])
self.history_export.configure(text=f"export ({len(self.image_queue)})")
self.request_upper_size_button.configure(state="normal")
self.current_window = self.window
if self.window == len(self.image_queue)-1:
self.window+=1
update()
show_text = str(self.window)+" / "+ str(len(self.image_queue))
self.window_label.configure(text=show_text)
def image_history_0_yield(event=None):
if len(self.image_queue) < 1:
return
if self.control_pressed:
if self.toggle_prompt_fix_button.get() == 0:
self.text_input.delete("0.0", "end")
self.text_input.insert("0.0", self.image_queue[self.window-1][1])
else:
self.image_label_report.configure(state="normal")
self.image_label_report.delete("0.0", "end")
self.image_label_report.insert("0.0", "<UserAttention> ํ”„๋กฌํ”„ํŠธ ๊ณ ์ • ์ƒํƒœ์—์„œ๋Š” ์‚ฌ์šฉ ํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.")
self.image_label_report.configure(text_color="#FFFF97")
self.image_label_report.configure(state="disabled")
else:
self.current_window = self.window-1
if app.state() != 'zoomed':
self.image_label.configure(image=customtkinter.CTkImage(self.image_queue[self.window-1][0], size=(620,620)))
else:
current_image = Image.open(self.image_queue[self.window-1][3])
original_width, original_height = current_image.size
max_size = app.winfo_screenheight()-100
if original_width > max_size or original_height > max_size:
new_image = Image.new("RGB", (max_size, max_size), "black")
new_image.paste(current_image, ((max_size - original_width) // 2, (max_size - original_height) // 2))
instant_result_image = customtkinter.CTkImage(new_image, size=(max_size, max_size))
else:
instant_result_image = customtkinter.CTkImage(current_image, size=(max_size, max_size))
self.image_label.configure(image=instant_result_image)
self.image_label_report.configure(state="normal")
self.image_label_report.delete("0.0", "end")
self.image_label_report.configure(text_color="#DCE4EE")
self.image_label_report.insert("0.0", self.image_queue[self.window-1][1] + " seed : " + self.image_queue[self.window-1][2])
self.image_label_report.configure(state="disabled")
def image_history_1_yield(event=None):
if len(self.image_queue) < 2:
return
if self.control_pressed:
if self.toggle_prompt_fix_button.get() == 0:
self.text_input.delete("0.0", "end")
self.text_input.insert("0.0", self.image_queue[self.window-2][1])
else:
self.image_label_report.configure(state="normal")
self.image_label_report.delete("0.0", "end")
self.image_label_report.insert("0.0", "<UserAttention> ํ”„๋กฌํ”„ํŠธ ๊ณ ์ • ์ƒํƒœ์—์„œ๋Š” ์‚ฌ์šฉ ํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.")
self.image_label_report.configure(text_color="#FFFF97")
self.image_label_report.configure(state="disabled")
else:
self.current_window = self.window-2
if app.state() != 'zoomed':
self.image_label.configure(image=customtkinter.CTkImage(self.image_queue[self.window-2][0], size=(620,620)))
else:
current_image = Image.open(self.image_queue[self.window-2][3])
original_width, original_height = current_image.size
max_size = app.winfo_screenheight()-100
if original_width > max_size or original_height > max_size:
new_image = Image.new("RGB", (max_size, max_size), "black")
new_image.paste(current_image, ((max_size - original_width) // 2, (max_size - original_height) // 2))
instant_result_image = customtkinter.CTkImage(new_image, size=(max_size, max_size))
else:
instant_result_image = customtkinter.CTkImage(current_image, size=(max_size, max_size))
self.image_label.configure(image=instant_result_image)
self.image_label_report.configure(state="normal")
self.image_label_report.delete("0.0", "end")
self.image_label_report.configure(text_color="#DCE4EE")
self.image_label_report.insert("0.0", self.image_queue[self.window-2][1] + " seed : " + self.image_queue[self.window-2][2])
self.image_label_report.configure(state="disabled")
def image_history_2_yield(event=None):
if len(self.image_queue) < 3:
return
if self.control_pressed:
if self.toggle_prompt_fix_button.get() == 0:
self.text_input.delete("0.0", "end")
self.text_input.insert("0.0", self.image_queue[self.window-3][1])
else:
self.image_label_report.configure(state="normal")
self.image_label_report.delete("0.0", "end")
self.image_label_report.insert("0.0", "<UserAttention> ํ”„๋กฌํ”„ํŠธ ๊ณ ์ • ์ƒํƒœ์—์„œ๋Š” ์‚ฌ์šฉ ํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.")
self.image_label_report.configure(text_color="#FFFF97")
self.image_label_report.configure(state="disabled")
else:
self.current_window = self.window-3
if app.state() != 'zoomed':
self.image_label.configure(image=customtkinter.CTkImage(self.image_queue[self.window-3][0], size=(620,620)))
else:
current_image = Image.open(self.image_queue[self.window-3][3])
original_width, original_height = current_image.size
max_size = app.winfo_screenheight()-100
if original_width > max_size or original_height > max_size:
new_image = Image.new("RGB", (max_size, max_size), "black")
new_image.paste(current_image, ((max_size - original_width) // 2, (max_size - original_height) // 2))
instant_result_image = customtkinter.CTkImage(new_image, size=(max_size, max_size))
else:
instant_result_image = customtkinter.CTkImage(current_image, size=(max_size, max_size))
self.image_label.configure(image=instant_result_image)
self.image_label_report.configure(state="normal")
self.image_label_report.delete("0.0", "end")
self.image_label_report.configure(text_color="#DCE4EE")
self.image_label_report.insert("0.0", self.image_queue[self.window-3][1] + " seed : " + self.image_queue[self.window-3][2])
self.image_label_report.configure(state="disabled")
def image_history_3_yield(event=None):
if len(self.image_queue) < 4:
return
if self.control_pressed:
if self.toggle_prompt_fix_button.get() == 0:
self.text_input.delete("0.0", "end")
self.text_input.insert("0.0", self.image_queue[self.window-4][1])
else:
self.image_label_report.configure(state="normal")
self.image_label_report.delete("0.0", "end")
self.image_label_report.insert("0.0", "<UserAttention> ํ”„๋กฌํ”„ํŠธ ๊ณ ์ • ์ƒํƒœ์—์„œ๋Š” ์‚ฌ์šฉ ํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.")
self.image_label_report.configure(text_color="#FFFF97")
self.image_label_report.configure(state="disabled")
else:
self.current_window = self.window-4
if app.state() != 'zoomed':
self.image_label.configure(image=customtkinter.CTkImage(self.image_queue[self.window-4][0], size=(620,620)))
else:
current_image = Image.open(self.image_queue[self.window-4][3])
original_width, original_height = current_image.size
max_size = app.winfo_screenheight()-100
if original_width > max_size or original_height > max_size:
new_image = Image.new("RGB", (max_size, max_size), "black")
new_image.paste(current_image, ((max_size - original_width) // 2, (max_size - original_height) // 2))
instant_result_image = customtkinter.CTkImage(new_image, size=(max_size, max_size))
else:
instant_result_image = customtkinter.CTkImage(current_image, size=(max_size, max_size))
self.image_label.configure(image=instant_result_image)
self.image_label_report.configure(state="normal")
self.image_label_report.delete("0.0", "end")
self.image_label_report.configure(text_color="#DCE4EE")
self.image_label_report.insert("0.0", self.image_queue[self.window-4][1] + " seed : " + self.image_queue[self.window-4][2])
self.image_label_report.configure(state="disabled")
def image_history_4_yield(event=None):
if len(self.image_queue) < 5:
return
if self.control_pressed:
if self.toggle_prompt_fix_button.get() == 0:
self.text_input.delete("0.0", "end")
self.text_input.insert("0.0", self.image_queue[self.window-5][1])
else:
self.image_label_report.configure(state="normal")
self.image_label_report.delete("0.0", "end")
self.image_label_report.insert("0.0", "<UserAttention> ํ”„๋กฌํ”„ํŠธ ๊ณ ์ • ์ƒํƒœ์—์„œ๋Š” ์‚ฌ์šฉ ํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.")
self.image_label_report.configure(text_color="#FFFF97")
self.image_label_report.configure(state="disabled")
else:
self.current_window = self.window-5
if app.state() != 'zoomed':
self.image_label.configure(image=customtkinter.CTkImage(self.image_queue[self.window-5][0], size=(620,620)))
else:
current_image = Image.open(self.image_queue[self.window-5][3])
original_width, original_height = current_image.size
max_size = app.winfo_screenheight()-100
if original_width > max_size or original_height > max_size:
new_image = Image.new("RGB", (max_size, max_size), "black")
new_image.paste(current_image, ((max_size - original_width) // 2, (max_size - original_height) // 2))
instant_result_image = customtkinter.CTkImage(new_image, size=(max_size, max_size))
else:
instant_result_image = customtkinter.CTkImage(current_image, size=(max_size, max_size))
self.image_label.configure(image=instant_result_image)
self.image_label_report.configure(state="normal")
self.image_label_report.delete("0.0", "end")
self.image_label_report.configure(text_color="#DCE4EE")
self.image_label_report.insert("0.0", self.image_queue[self.window-5][1] + " seed : " + self.image_queue[self.window-5][2])
self.image_label_report.configure(state="disabled")
def update():
if len(self.image_queue) <= 5:
if len(self.image_queue) >= 1:
self.image_history_0.configure(self.image_history_sub_frame, image=customtkinter.CTkImage(self.image_queue[self.window-1][0], size=(100,100)))
if len(self.image_queue) >= 2:
self.image_history_0.configure(self.image_history_sub_frame, image=customtkinter.CTkImage(self.image_queue[self.window-1][0], size=(100,100)))
self.image_history_1.configure(self.image_history_sub_frame, image=customtkinter.CTkImage(self.image_queue[self.window-2][0], size=(100,100)))
if len(self.image_queue) >= 3:
self.image_history_0.configure(self.image_history_sub_frame, image=customtkinter.CTkImage(self.image_queue[self.window-1][0], size=(100,100)))
self.image_history_1.configure(self.image_history_sub_frame, image=customtkinter.CTkImage(self.image_queue[self.window-2][0], size=(100,100)))
self.image_history_2.configure(self.image_history_sub_frame, image=customtkinter.CTkImage(self.image_queue[self.window-3][0], size=(100,100)))
if len(self.image_queue) >= 4:
self.image_history_0.configure(self.image_history_sub_frame, image=customtkinter.CTkImage(self.image_queue[self.window-1][0], size=(100,100)))
self.image_history_1.configure(self.image_history_sub_frame, image=customtkinter.CTkImage(self.image_queue[self.window-2][0], size=(100,100)))
self.image_history_2.configure(self.image_history_sub_frame, image=customtkinter.CTkImage(self.image_queue[self.window-3][0], size=(100,100)))
self.image_history_3.configure(self.image_history_sub_frame, image=customtkinter.CTkImage(self.image_queue[self.window-4][0], size=(100,100)))
if len(self.image_queue) == 5:
self.image_history_0.configure(self.image_history_sub_frame, image=customtkinter.CTkImage(self.image_queue[self.window-1][0], size=(100,100)))
self.image_history_1.configure(self.image_history_sub_frame, image=customtkinter.CTkImage(self.image_queue[self.window-2][0], size=(100,100)))
self.image_history_2.configure(self.image_history_sub_frame, image=customtkinter.CTkImage(self.image_queue[self.window-3][0], size=(100,100)))
self.image_history_3.configure(self.image_history_sub_frame, image=customtkinter.CTkImage(self.image_queue[self.window-4][0], size=(100,100)))
self.image_history_4.configure(self.image_history_sub_frame, image=customtkinter.CTkImage(self.image_queue[self.window-5][0], size=(100,100)))
else:
self.image_history_0.configure(self.image_history_sub_frame, image=customtkinter.CTkImage(self.image_queue[self.window-1][0], size=(100,100)))
self.image_history_1.configure(self.image_history_sub_frame, image=customtkinter.CTkImage(self.image_queue[self.window-2][0], size=(100,100)))
self.image_history_2.configure(self.image_history_sub_frame, image=customtkinter.CTkImage(self.image_queue[self.window-3][0], size=(100,100)))
self.image_history_3.configure(self.image_history_sub_frame, image=customtkinter.CTkImage(self.image_queue[self.window-4][0], size=(100,100)))
self.image_history_4.configure(self.image_history_sub_frame, image=customtkinter.CTkImage(self.image_queue[self.window-5][0], size=(100,100)))
if len(self.image_queue) == 6:
self.image_history_button_down.configure(state="normal")
black_image = Image.new('RGB', (100, 100), '#2B2B2B')
self.image_history_0 = customtkinter.CTkButton(self.image_history_sub_frame, width=100, height=100, corner_radius=8,text="", fg_color="transparent", image=customtkinter.CTkImage(black_image, size=(100,100)), command=image_history_0_yield)
self.image_history_0.grid(row=0, column=1, padx=5, pady=1, sticky="n")
self.image_history_1 = customtkinter.CTkButton(self.image_history_sub_frame, width=100, height=100, corner_radius=8,text="", fg_color="transparent", image=customtkinter.CTkImage(black_image, size=(100,100)), command=image_history_1_yield)
self.image_history_1.grid(row=1, column=1, padx=5, pady=1, sticky="n")
self.image_history_2 = customtkinter.CTkButton(self.image_history_sub_frame, width=100, height=100, corner_radius=8,text="", fg_color="transparent",image=customtkinter.CTkImage(black_image, size=(100,100)), command=image_history_2_yield)
self.image_history_2.grid(row=2, column=1, padx=5, pady=1, sticky="n")
self.image_history_3 = customtkinter.CTkButton(self.image_history_sub_frame, width=100, height=100, corner_radius=8,text="", fg_color="transparent", image=customtkinter.CTkImage(black_image, size=(100,100)), command=image_history_3_yield)
self.image_history_3.grid(row=3,column=1, padx=5, pady=1, sticky="n")
self.image_history_4 = customtkinter.CTkButton(self.image_history_sub_frame, width=100, height=100, corner_radius=8,text="", fg_color="transparent", image=customtkinter.CTkImage(black_image, size=(100,100)), command=image_history_4_yield)
self.image_history_4.grid(row=4, column=1, padx=5, pady=1, sticky="n")
self.image_history_button_up = customtkinter.CTkButton(self.image_history_frame, text="โ–ฒ", width=100, font=my_font, state="disabled", command=up_button_pressed)
self.image_history_button_up.grid(row=0, column=1, pady=10, padx=5, sticky="n")
self.image_history_button_down = customtkinter.CTkButton(self.image_history_frame, text="โ–ผ", width=100, font=my_font, state="disabled", command=down_button_pressed)
self.image_history_button_down.grid(row=13, column=1, pady=5, padx=5, sticky="n")
def save_to_excel():
#contributor : highnoon1
#function : ํžˆ์Šคํ† ๋ฆฌ ์—‘์…€๋กœ ์ €์žฅ (๋ฌด์ œํ•œ ๋ณด๊ธฐ๋Š” ์„ฑ๋Šฅ ์ด์Šˆ๋กœ ์ œ์™ธ)
workbook = Workbook()
sheet = workbook.active
alignment = Alignment(wrapText=True)
sheet['A1'].alignment = alignment
sheet['A1'] = 'Prompt'
sheet['B1'] = 'Seed'
sheet['C1'] = 'Image'
image_objects = [] # BytesIO ๊ฐ์ฒด๋ฅผ ์ถ”์ ํ•˜๊ธฐ ์œ„ํ•œ ๋ฆฌ์ŠคํŠธ
# history ๋ฐ์ดํ„ฐ๋ฅผ ๋ฐ˜๋ณตํ•˜๋ฉฐ Excel์— ์ €์žฅ
for index, (pil_image, prompt, seed, _filename) in enumerate(self.image_queue):
row_num = index + 1 # ํ–‰ ๋ฒˆํ˜ธ (Excel ํ–‰์€ 1๋ถ€ํ„ฐ ์‹œ์ž‘)
# ํ”„๋กฌํ”„ํŠธ์™€ ์‹œ๋“œ ์‚ฝ์ž…
prompt_cell = sheet.cell(row=row_num, column=1, value=prompt)
sheet.cell(row=row_num, column=2, value=seed)
prompt_cell.alignment = Alignment(wrap_text=True)
# PIL ์ด๋ฏธ์ง€๋ฅผ BytesIO ๊ฐ์ฒด์— PNG ํ˜•์‹์œผ๋กœ ์ €์žฅ
pil_image = self.resize_image_to_fit(pil_image,192)
output = io.BytesIO()
pil_image.save(output, format='PNG')
output.seek(0)
image_objects.append(output) # ๋ฆฌ์ŠคํŠธ์— ์ถ”๊ฐ€
# Openpyxl ์ด๋ฏธ์ง€ ์ƒ์„ฑ ๋ฐ ์‹œํŠธ์— ์ถ”๊ฐ€
img = OpenpyxlImage(output)
img.anchor = f'C{row_num}' # ์ด๋ฏธ์ง€๋ฅผ C์—ด์— ๊ณ ์ •
sheet.add_image(img)
# ์ด๋ฏธ์ง€ ํฌ๊ธฐ์— ๋”ฐ๋ผ ํ–‰ ๋†’์ด ๋ฐ ์—ด ๋„ˆ๋น„ ์กฐ์ •
scale_factor = 0.75
sheet.row_dimensions[row_num].height = pil_image.height * scale_factor
sheet.column_dimensions['C'].width = pil_image.width * scale_factor / 7
# A์—ด๊ณผ B์—ด ํฌ๊ธฐ ์กฐ์ •
sheet.column_dimensions['A'].width = 50
sheet.column_dimensions['B'].width = 15
# ์›Œํฌ๋ถ ์ €์žฅ
workbook.save(f"history_with_images_{self.start_time}.xlsx")
# ๋ชจ๋“  BytesIO ๊ฐ์ฒด ๋‹ซ๊ธฐ
for img_obj in image_objects:
img_obj.close()
if os.path.exists(f"history_with_images_{self.start_time}.xlsx"):
os.startfile(f"history_with_images_{self.start_time}.xlsx")
print("์—‘์…€ ํŒŒ์ผ์— ์ €์žฅ๋จ")
self.history_export = customtkinter.CTkButton(self.image_history_frame, text="export (0)", width=100, font=my_font, command=save_to_excel)
self.history_export.grid(row=14, column=1, pady=10, padx=5, sticky="n")
#๋žœ๋ค์ž‘๊ฐ€ ๋ฐ ์™€์ผ๋“œ์นด๋“œ ์„ค์ •
self.extended_right_frame = customtkinter.CTkFrame(self.right_frame)
self.extended_right_frame.grid(row=17, column=0, columnspan=2, padx=5, sticky="w")
self.random_artist_var = customtkinter.IntVar()
self.random_artist_button = customtkinter.CTkCheckBox(self.extended_right_frame, text="๋žœ๋ค์ž‘๊ฐ€ ์ถ”๊ฐ€", variable=self.random_artist_var, font=my_font, state="disabled")
self.random_artist_button.grid(row=0, column=0,pady=5, padx=10, sticky="nsew")
self.random_artist_manage_button = customtkinter.CTkButton(self.extended_right_frame, text="๋žœ๋ค์ž‘๊ฐ€ ๊ด€๋ฆฌ", font=my_font, command=self.random_artist_window)
self.random_artist_manage_button.grid(row=0, column=1,pady=5, padx=5, sticky="nsew")
self.recommended_prompt_button = customtkinter.CTkButton(self.extended_right_frame, text="์ถ”์ฒœ ํ”„๋กฌํ”„ํŠธ", font=my_font, command= self.open_prompt_window)
self.recommended_prompt_button.grid(row=0, column=3,pady=5, padx=5, sticky="nsew")
self.wildcard_manager_button = customtkinter.CTkButton(self.extended_right_frame, text="์™€์ผ๋“œ์นด๋“œ ๊ด€๋ฆฌ", font=my_font, command=self.open_wildcard_window)
self.wildcard_manager_button.grid(row=0, column=2,pady=5, padx=5, sticky="nsew")
self.character_search_button = customtkinter.CTkButton(self.extended_right_frame, text="์บ๋ฆญํ„ฐ ๊ฒ€์ƒ‰", fg_color="#7030A0", hover_color="#481F67", font=my_font, command= lambda: open_Character_search(self))
self.character_search_button.grid(row=0, column=4,pady=5, padx=5, sticky="nsew")
self.seed_fix_var = customtkinter.IntVar()
self.seed_fix_button = customtkinter.CTkCheckBox(self.extended_right_frame, text="์‹œ๋“œ๊ณ ์ • ", variable=self.seed_fix_var, font=my_font)
self.seed_fix_button.grid(row=1, column=0,pady=5, padx=10, sticky="nsew")
self.entry_seed_value = customtkinter.IntVar()
self.seed_entry = customtkinter.CTkEntry(self.extended_right_frame, textvariable=self.entry_seed_value)
self.seed_entry.grid(row=1, column=1,pady=5, padx=5, sticky="nsew")
self.seed_entry.insert(0, random.randint(0,9999999999))
self.cfg_scale_label = customtkinter.CTkLabel(self.extended_right_frame, text="CFG Scale : ", font=my_font)
self.cfg_scale_label.grid(row=1, column=2,pady=5, padx=5, sticky="w")
self.cfg_scale_var = customtkinter.StringVar(value="5.0")
self.cfg_scale_entry = customtkinter.CTkEntry(self.extended_right_frame, width=65, textvariable=self.cfg_scale_var)
self.cfg_scale_entry.grid(row=1, column=2,pady=5, padx=5, sticky="e")
self.prompt_guidance_rescale_var = customtkinter.StringVar(value="0")
self.prompt_guidance_rescale_label = customtkinter.CTkLabel(self.extended_right_frame, text="Prompt Guidance Rescale :", font=my_font)
self.prompt_guidance_rescale_label.grid(row=1, column=3, pady=5, padx=5, sticky="w")
self.prompt_guidance_rescale_entry = customtkinter.CTkEntry(self.extended_right_frame, width=65)
self.prompt_guidance_rescale_entry.grid(row=1, column=4,pady=5, padx=10, sticky="w")
self.extra_setting_button = customtkinter.CTkButton(self.extended_right_frame, width=55, text="๊ธฐํƒ€์„ค์ •", font=my_font, fg_color="grey", hover_color="grey5", command=lambda: show_advanced_settings(self))
self.extra_setting_button.grid(row=1, column=4,pady=5, padx=5, sticky="e")
self.random_resolution_var = customtkinter.IntVar()
self.random_resolution_button = customtkinter.CTkCheckBox(self.extended_right_frame, text="๋žœ๋ค ํ•ด์ƒ๋„ ", variable=self.random_resolution_var, font=my_font)
self.random_resolution_button.grid(row=2, column=0,pady=5, padx=10, sticky="nsew")
self.resolution_var = customtkinter.StringVar(value="1024 x 1024")
self.resolution_button = customtkinter.CTkComboBox(self.extended_right_frame, width=160,values=["1024 x 1024", "960 x 1088", "896 x 1152", "832 x 1216", "1088 x 960", "1152 x 896", "1216 x 832"], variable=self.resolution_var, font=my_font)
self.resolution_button.grid(row=2, column=1, padx=5, sticky="w")
self.sampler_label = customtkinter.CTkLabel(self.extended_right_frame, text="Sampler :", font=my_font)
self.sampler_label.grid(row=2, column=2,pady=5, padx=15, sticky="w")
self.sampler_var = customtkinter.StringVar(value="k_euler_ancestral")
self.sampler_button = customtkinter.CTkComboBox(self.extended_right_frame, width=210,values=["k_euler", "k_euler_ancestral", "k_dpmpp_2s_ancestral", "k_dpmpp_sde"], variable=self.sampler_var, font=my_font)
self.sampler_button.grid(row=2, column=2, columnspan=2, pady=5, padx=15, sticky="e")
self.show_fullscreen_btn = customtkinter.CTkButton(self.extended_right_frame, text="์ „์ฒดํ™”๋ฉด(ESC๋‹ซ๊ธฐ)", font=my_font, command=self.show_fullscreen_image)
self.show_fullscreen_btn.grid(row=2, column=4,pady=5, padx=5, sticky="nsew")
self.sema_button_var = customtkinter.IntVar()
def sema_pressed():
if self.sema_button_var.get() == 0:
self.dyn_button.deselect()
self.sema_button = customtkinter.CTkCheckBox(self.extended_right_frame, text="SEMA", variable=self.sema_button_var,font=my_font, command=sema_pressed)
self.sema_button.grid(row=3, column=0, pady=5, padx=10, sticky="w")
self.dyn_button_var = customtkinter.IntVar()
def sema_dyn_pressed():
if self.dyn_button_var.get() == 1:
self.sema_button.select()
self.dyn_button = customtkinter.CTkCheckBox(self.extended_right_frame, text="SEMA+DYN", variable=self.dyn_button_var, font=my_font, command=sema_dyn_pressed)
self.dyn_button.grid(row=3, column=1, pady=5, padx=10, sticky="w")
self.state_label = customtkinter.CTkLabel(self.extended_right_frame, text="state : idle", font=my_font)
self.state_label.grid(row=3, column=2, columnspan=2, pady=5, padx=10, sticky="n")
self.instant_row_button = customtkinter.CTkButton(self.extended_right_frame, text="์ธ์Šคํ„ดํŠธ ์ด๋ฒคํŠธ (๋ฏธ๊ตฌํ˜„)", font=my_font, fg_color="grey10",state="disabled")
self.instant_row_button.grid(row=3, column=4,pady=5, padx=5, sticky="nsew")
GENERATE_EVENT = "<<GenerateEvent>>"
sync_text()
self.bind(GENERATE_EVENT, lambda x=None: NAIA_generate(self))
self.output_file_path_personal = False
self.png_name_rule = "time"
self.name_var = customtkinter.StringVar(value=self.png_name_rule)
self.window_resize_last_access = None
self.last_window_size_conf = None
self.generation_count = 0
self.random_artist_list = None
self.random_artist = []
self.random_artist_prefix = customtkinter.StringVar(value="none")
def on_window_resize(event):
if datetime.now() == app.last_window_size_conf:
return
time_difference = datetime.now() - app.start_time_prime
if (time_difference.total_seconds() < 3):
return
if app.last_window_size is None:
app.last_window_size = (app.winfo_width(), app.winfo_height())
# ์œˆ๋„์šฐ๊ฐ€ ์ตœ๋Œ€ํ™”๋˜์—ˆ๋Š”์ง€ ํ™•์ธ
current_size = (app.winfo_width(), app.winfo_height())
if current_size != app.last_window_size:
app.last_window_size = current_size
if app.state() == 'zoomed':
self.right_frame.configure(width=1200)
self.image_label.grid_forget()
self.image_label_under_frame.grid_forget()
self.image_history_sub_frame.grid_forget()
self.image_history_button_down.grid_forget()
self.image_history_sub_frame.grid(row=0, pady=45, rowspan=12, column=1, sticky="n")
self.image_history_button_down.grid(row=9, column=1, pady=5, padx=5, sticky="n")
self.image_label.grid(row=0, column=0,rowspan=14, padx=10, pady=5, sticky="w")
self.hidden_frame.grid(row=0, column=2,rowspan=14, sticky="nsew")
self.history_export.grid(row=10, column=1, pady=1, padx=5, sticky="n")
self.random_artist_button = customtkinter.CTkCheckBox(self.hidden_frame, text="๋žœ๋ค์ž‘๊ฐ€ ์ถ”๊ฐ€", variable=self.random_artist_var, font=my_font, state="disabled")
self.random_artist_button.grid(row=0, column=0,pady=5, padx=5, sticky="nsew")
self.seed_fix_button = customtkinter.CTkCheckBox(self.hidden_frame, text="์‹œ๋“œ๊ณ ์ • ", variable=self.seed_fix_var, font=my_font)
self.seed_fix_button.grid(row=1, column=0,pady=5, padx=5, sticky="nsew")
self.seed_entry = customtkinter.CTkEntry(self.hidden_frame, textvariable=self.entry_seed_value)
self.seed_entry.grid(row=1, column=1,pady=5, padx=5, sticky="nsew")
self.random_artist_manage_button = customtkinter.CTkButton(self.hidden_frame, text="๋žœ๋ค์ž‘๊ฐ€ ๊ด€๋ฆฌ", font=my_font, command=self.random_artist_window)
self.random_artist_manage_button.grid(row=0, column=1,pady=5, padx=5, sticky="nsew")
self.random_resolution_button2 = customtkinter.CTkCheckBox(self.hidden_frame, text="๋žœ๋ค ํ•ด์ƒ๋„", variable=self.random_resolution_var, font=my_font)
self.random_resolution_button2.grid(row=3, column=0,pady=5, padx=5, sticky="nsew")
self.resolution_button2 = customtkinter.CTkComboBox(self.hidden_frame, width=160,values=["1024 x 1024", "960 x 1088", "896 x 1152", "832 x 1216", "1088 x 960", "1152 x 896", "1216 x 832"], variable=self.resolution_var, font=my_font)
self.resolution_button2.grid(row=3, column=1, padx=5, sticky="w")
self.sampler_label2 = customtkinter.CTkLabel(self.hidden_frame, text="Sampler :", font=my_font)
self.sampler_label2.grid(row=4, column=0,pady=5, padx=5, sticky="w")
self.sampler_button2 = customtkinter.CTkComboBox(self.hidden_frame, width=160,values=["k_euler", "k_euler_ancestral", "k_dpmpp_2s_ancestral", "k_dpmpp_sde"], variable=self.sampler_var, font=my_font)
self.sampler_button2.grid(row=4, column=1, columnspan=2, pady=5, padx=5, sticky="e")
self.cfg_scale_label2 = customtkinter.CTkLabel(self.hidden_frame, text="CFG Scale : ", font=my_font)
self.cfg_scale_label2.grid(row=5, column=0,pady=5, padx=5, sticky="w")
self.cfg_scale_entry2 = customtkinter.CTkEntry(self.hidden_frame, width=65, textvariable=self.cfg_scale_var)
self.cfg_scale_entry2.grid(row=5, column=1,pady=5, padx=5, sticky="w")
self.prompt_guidance_rescale_label2 = customtkinter.CTkLabel(self.hidden_frame, text="P.Guide Rescale :", font=my_font)
self.prompt_guidance_rescale_label2.grid(row=6, column=0, pady=5, padx=5, sticky="w")
self.prompt_guidance_rescale_entry2 = customtkinter.CTkEntry(self.hidden_frame, width=65, textvariable=self.prompt_guidance_rescale_var)
self.prompt_guidance_rescale_entry2.grid(row=6, column=1,pady=5, padx=5, sticky="w")
self.sema_button2 = customtkinter.CTkCheckBox(self.hidden_frame, text="SEMA", variable=self.sema_button_var,font=my_font)
self.sema_button2.grid(row=7, column=0, pady=5, padx=5, sticky="w")
self.dyn_button2 = customtkinter.CTkCheckBox(self.hidden_frame, text="SEMA+DYN", variable=self.dyn_button_var, font=my_font)
self.dyn_button2.grid(row=7, column=1, pady=5, padx=5, sticky="w")
self.open_save_folder2 = customtkinter.CTkButton(self.hidden_frame, text="ํด๋” ์—ด๊ธฐ", font=my_font, fg_color="transparent", command=lambda: open_file_explorer(self), width=80)
self.open_save_folder2.grid(row=5, column=1,padx=5, pady=5, sticky="e")
self.extra_setting_button2 = customtkinter.CTkButton(self.hidden_frame, width=80, text="๊ธฐํƒ€์„ค์ •", font=my_font, fg_color="grey", hover_color="grey5", command=lambda: show_advanced_settings(self))
self.extra_setting_button2.grid(row=6, column=1,pady=5, padx=5, sticky="e")
self.recommended_prompt_button2 = customtkinter.CTkButton(self.hidden_frame, text="์ถ”์ฒœ ํ”„๋กฌํ”„ํŠธ", font=my_font, command= self.open_prompt_window)
self.recommended_prompt_button2.grid(row=9, column=0, columnspan=2, pady=5, padx=5, sticky="nsew")
self.wildcard_manager_button2 = customtkinter.CTkButton(self.hidden_frame, text="์™€์ผ๋“œ์นด๋“œ ๊ด€๋ฆฌ", font=my_font, command=self.open_wildcard_window)
self.wildcard_manager_button2.grid(row=10, column=0,columnspan=2, pady=5, padx=5, sticky="nsew")
self.character_search_button2 = customtkinter.CTkButton(self.hidden_frame, text="์บ๋ฆญํ„ฐ ๊ฒ€์ƒ‰", fg_color="#7030A0", hover_color="#481F67", font=my_font, command= lambda: open_Character_search(self))
self.character_search_button2.grid(row=11, column=0,columnspan=2, pady=5, padx=5, sticky="nsew")
self.window_label.grid_forget()
self.window_label = customtkinter.CTkLabel(self.hidden_frame, text=str(self.window)+" / "+ str(len(self.image_queue)), font=my_font)
self.window_label.grid(row=12, column=0,padx=5, pady=5, sticky="w")
if self.image_queue:
current_image = Image.open(self.image_queue[self.window-1][3])
original_width, original_height = current_image.size
max_size = app.winfo_screenheight()-100
if original_width > max_size or original_height > max_size:
new_image = Image.new("RGB", (max_size, max_size), "black")
new_image.paste(current_image, ((max_size - original_width) // 2, (max_size - original_height) // 2))
instant_result_image = customtkinter.CTkImage(new_image, size=(max_size, max_size))
else:
instant_result_image = customtkinter.CTkImage(current_image, size=(max_size, max_size))
self.image_label.configure(image=instant_result_image)
else:
self.image_label.configure(image=customtkinter.CTkImage(white_image, size=(app.winfo_screenheight()-100, app.winfo_screenheight()-100)))
else:
self.right_frame.configure(width=768)
self.image_label_report.grid_forget()
self.image_label.grid_forget()
self.image_label_under_frame.grid_forget()
self.image_history_sub_frame.grid_forget()
self.image_history_button_up.grid_forget()
self.image_history_button_down.grid_forget()
self.image_label.grid(row=1, column=0, rowspan=14, padx=10, pady=5, sticky="w")
self.image_label_under_frame.grid(row=0, column=0, padx=10, pady=5, sticky="ew")
self.image_history_sub_frame.grid(row=1, rowspan=12, column=1, sticky="n")
self.image_label_report.grid(row=16, column=0, padx=10, pady=5, sticky="ew")
self.image_history_button_up.grid(row=0, column=1, pady=10, padx=5, sticky="n")
self.image_history_button_down.grid(row=13, column=1, pady=5, padx=5, sticky="n")
self.history_export.grid(row=14, column=1, pady=10, padx=5, sticky="n")
self.hidden_frame.grid_forget()
self.window_label.grid_forget()
self.window_label = customtkinter.CTkLabel(self.image_label_under_frame, text=str(self.window)+" / "+ str(len(self.image_queue)), font=my_font)
self.window_label.grid(row=0, column=4,padx=5, pady=5, sticky="w")
if self.image_queue:
self.image_label.configure(image=customtkinter.CTkImage(self.image_queue[self.window-1][0], size=(620, 620)))
else:
self.image_label.configure(image=customtkinter.CTkImage(white_image, size=(620, 620)))
app.last_window_size_conf = datetime.now()
self.bind("<Configure>", on_window_resize)
def on_ctrl_press(event):
self.control_pressed = True
def on_ctrl_release(event):
self.control_pressed = False
self.control_pressed = False
self.bind_all("<Control_L>", on_ctrl_press)
self.bind_all("<KeyRelease-Control_L>", on_ctrl_release)
self.last_window_size = None
self.random_artist_select = "global"
self.random_artist_list_length = 0
self.protocol("WM_DELETE_WINDOW", lambda: (self.Automation_setting.destroy()))
self.wildcard_dict = None
self.wildacrds_dir = ""
def on_arrow_key(event):
key_pressed = event.keysym
#self.focus_set()
if key_pressed == "Up" and self.image_history_button_up.cget("state") == "normal":
up_button_pressed()
elif key_pressed == "Down" and self.image_history_button_down.cget("state") == "normal":
down_button_pressed()
def instant_image_generation(self):
def find_max_resolution(width, height, max_pixels=2166784, multiple_of=64):
ratio = width / height
max_width = int((max_pixels * ratio)**0.5)
max_height = int((max_pixels / ratio)**0.5)
max_width = (max_width // multiple_of) * multiple_of
max_height = (max_height // multiple_of) * multiple_of
while max_width * max_height > max_pixels:
max_width -= multiple_of
max_height = int(max_width / ratio)
max_height = (max_height // multiple_of) * multiple_of
return (max_width, max_height)
self.request_upper_size_button.configure(state="disabled")
request_prompt = self.image_queue[self.current_window][1]
request_seed = self.image_queue[self.current_window][2]
filename = self.image_queue[self.current_window][3]
width, height = Image.open(filename).size
request_width, request_height = find_max_resolution(width, height)
scale_pre = self.cfg_scale_entry.get()
steps = self.request_upper_size_steps.get()
try:
scale_pre = float(scale_pre)
except:
scale_pre = 5.0
self.cfg_scale_var.set("5.0")
rescale_pre = self.prompt_guidance_rescale_entry.get()
try:
rescale_pre = float(rescale_pre)
except:
rescale_pre = 0
self.prompt_guidance_rescale_var.set("0")
try:
steps = int(steps)
except:
steps = 28
self.cfg_scale_var.set("28")
gen_request = {
"width":request_width,
"height":request_height,
"quality_toggle":self.auto_quality_toggle.get(),
"seed":request_seed if self.request_upper_size_seed_hold_var.get() == 1 else random.randint(0,9999999999),
"sampler":self.sampler_button.get(),
"scale":scale_pre,
"sema":self.sema_button.get(),
"sema_dyn": self.dyn_button.get(),
"cfg_rescale": rescale_pre,
"prompt": request_prompt,
"negative":self.negative_prompt_input.get("0.0", "end-1c"),
"user_screen_size": self.get_max_size(),
"start_time": self.start_time,
"access_token": self.access_token,
"save_folder": self.output_file_path,
"png_rule": self.name_var.get(),
"type": "upper",
"steps": steps if steps <= 50 else 50
}
def run_generation():
if gen_request["png_rule"] == "count":
self.generation_count += 1
gen_request["count"] =self.generation_count
self.state_label.configure(text ="state : ๊ณ ํ•ด์ƒ๋„ ์ด๋ฏธ์ง€ ์š”์ฒญ๋จ ", text_color = "#FFFF97")
result_image, result_prompt, result_seed, info, filename = NAIA_generation.generate(gen_request)
self.state_label.configure(text ="state : ๊ณ ํ•ด์ƒ๋„ ์ด๋ฏธ์ง€ ์š”์ฒญ ๋ฐ˜ํ™˜๋จ", text_color = "#DCE4EE")
self.get_anlas()
self.request_upper_size_button.configure(state="normal")
if info:
temp = info.get('Comment', '')
temp = temp[temp.find("prompt")+10:temp.find("skip_cfg_below_sigma")-3].replace('"','')
else:
temp = result_prompt
self.image_label_report.configure(state="normal")
self.image_label_report.delete("0.0", "end")
self.image_label_report.configure(text_color="#DCE4EE")
self.image_label_report.insert("0.0", temp)
self.image_label_report.configure(state="disabled")
if result_image:
if app.state() != 'zoomed':
instant_result_image = customtkinter.CTkImage(result_image, size=(620,620))
else:
current_image = Image.open(filename)
original_width, original_height = current_image.size
max_size = app.winfo_screenheight()-100
if original_width > max_size or original_height > max_size:
new_image = Image.new("RGB", (max_size, max_size), "black")
new_image.paste(current_image, ((max_size - original_width) // 2, (max_size - original_height) // 2))
instant_result_image = customtkinter.CTkImage(new_image, size=(max_size, max_size))
else:
instant_result_image = customtkinter.CTkImage(current_image, size=(max_size, max_size))
self.image_label.configure(image=instant_result_image)
set_image_to_queue(result_image, result_prompt, str(result_seed), filename)
generation_thread = threading.Thread(target=run_generation, daemon=True)
generation_thread.start()
self.bind("<Up>", on_arrow_key)
self.bind("<Down>", on_arrow_key)
#์„ธ์ƒ์— ์‹œ๋ฐœ ์ด ์œ„๊นŒ์ง€ ์ „๋ถ€ __init__์— ๋“ค์–ด๊ฐ€์žˆ์Œ
def ext_set_image_to_queue(self, imagen, prompt, seed, filename):
self.image_queue.append([imagen, prompt, seed, filename])
self.history_export.configure(text=f"export ({len(self.image_queue)})")
self.request_upper_size_button.configure(state="normal")
self.current_window = self.window
if self.window == len(self.image_queue)-1:
self.window+=1
self.update()
show_text = str(self.window)+" / "+ str(len(self.image_queue))
self.window_label.configure(text=show_text)
def update(self):
if len(self.image_queue) <= 5:
if len(self.image_queue) >= 1:
self.image_history_0.configure(self.image_history_sub_frame, image=customtkinter.CTkImage(self.image_queue[self.window-1][0], size=(100,100)))
if len(self.image_queue) >= 2:
self.image_history_0.configure(self.image_history_sub_frame, image=customtkinter.CTkImage(self.image_queue[self.window-1][0], size=(100,100)))
self.image_history_1.configure(self.image_history_sub_frame, image=customtkinter.CTkImage(self.image_queue[self.window-2][0], size=(100,100)))
if len(self.image_queue) >= 3:
self.image_history_0.configure(self.image_history_sub_frame, image=customtkinter.CTkImage(self.image_queue[self.window-1][0], size=(100,100)))
self.image_history_1.configure(self.image_history_sub_frame, image=customtkinter.CTkImage(self.image_queue[self.window-2][0], size=(100,100)))
self.image_history_2.configure(self.image_history_sub_frame, image=customtkinter.CTkImage(self.image_queue[self.window-3][0], size=(100,100)))
if len(self.image_queue) >= 4:
self.image_history_0.configure(self.image_history_sub_frame, image=customtkinter.CTkImage(self.image_queue[self.window-1][0], size=(100,100)))
self.image_history_1.configure(self.image_history_sub_frame, image=customtkinter.CTkImage(self.image_queue[self.window-2][0], size=(100,100)))
self.image_history_2.configure(self.image_history_sub_frame, image=customtkinter.CTkImage(self.image_queue[self.window-3][0], size=(100,100)))
self.image_history_3.configure(self.image_history_sub_frame, image=customtkinter.CTkImage(self.image_queue[self.window-4][0], size=(100,100)))
if len(self.image_queue) == 5:
self.image_history_0.configure(self.image_history_sub_frame, image=customtkinter.CTkImage(self.image_queue[self.window-1][0], size=(100,100)))
self.image_history_1.configure(self.image_history_sub_frame, image=customtkinter.CTkImage(self.image_queue[self.window-2][0], size=(100,100)))
self.image_history_2.configure(self.image_history_sub_frame, image=customtkinter.CTkImage(self.image_queue[self.window-3][0], size=(100,100)))
self.image_history_3.configure(self.image_history_sub_frame, image=customtkinter.CTkImage(self.image_queue[self.window-4][0], size=(100,100)))
self.image_history_4.configure(self.image_history_sub_frame, image=customtkinter.CTkImage(self.image_queue[self.window-5][0], size=(100,100)))
else:
self.image_history_0.configure(self.image_history_sub_frame, image=customtkinter.CTkImage(self.image_queue[self.window-1][0], size=(100,100)))
self.image_history_1.configure(self.image_history_sub_frame, image=customtkinter.CTkImage(self.image_queue[self.window-2][0], size=(100,100)))
self.image_history_2.configure(self.image_history_sub_frame, image=customtkinter.CTkImage(self.image_queue[self.window-3][0], size=(100,100)))
self.image_history_3.configure(self.image_history_sub_frame, image=customtkinter.CTkImage(self.image_queue[self.window-4][0], size=(100,100)))
self.image_history_4.configure(self.image_history_sub_frame, image=customtkinter.CTkImage(self.image_queue[self.window-5][0], size=(100,100)))
if len(self.image_queue) == 6:
self.image_history_button_down.configure(state="normal")
def save_settings(self):
settings = {
"NAI_ID": self.NAI_ID if self.NAI_ID else " ",
"access_token": self.access_token if self.access_token else " ",
"searach_keyword": self.search_label_entry.get() if len(self.search_label_entry.get()) > 3 else " ",
"exclude_keyword": self.exclude_label_entry.get() if len(self.exclude_label_entry.get()) > 3 else " ",
"explicit": self.rating_select_explicit.get(),
"nsfw": self.rating_select_nsfw.get(),
"sensitive": self.rating_select_sensitive.get(),
"general": self.rating_select_general.get(),
"rm_artist": self.rm_artist_name_button.get(),
"rm_copyright": self.rm_copyright_name_button.get(),
"rm_character": self.rm_characteristic_button.get(),
"prompt": self.text_input.get("0.0", "end-1c") if len(self.text_input.get("0.0", "end")) > 4 else " ",
"negative": self.negative_prompt_input.get("0.0", "end-1c") if len(self.negative_prompt_input.get("0.0", "end")) > 4 else " ",
"fix": self.fixed_prompt_input.get("0.0", "end-1c") if len(self.fixed_prompt_input.get("0.0", "end")) > 4 else " ",
"after": self.fixed_prompt_after_input.get("0.0", "end-1c") if len(self.fixed_prompt_after_input.get("0.0", "end")) > 4 else " ",
"auto_hide": self.auto_hide_keyword_input.get("0.0", "end-1c") if len(self.auto_hide_keyword_input.get("0.0", "end")) > 4 else " ",
"cfg_scale": str(self.cfg_scale_entry.get()),
"guidance": str(self.prompt_guidance_rescale_entry.get()),
"sampler": self.sampler_var.get(),
"random": self.random_resolution_button.get(),
"sema": self.sema_button.get(),
"dyn": self.dyn_button.get(),
"personal_folder":self.output_file_path_personal,
"save_folder":self.output_file_path if self.output_file_path_personal else " ",
"png_rule":self.name_var.get(),
"quality_toggle":self.auto_quality_toggle.get()
}
with open('app_settings.json', 'w', encoding='utf-8') as f:
json.dump(settings, f, ensure_ascii=False, indent=4)
if type(self.cached_rows) != type(None) and not self.cached_rows.empty:
self.cached_rows.to_parquet('txt2img_temp_prompt.parquet')
#print("finished")
def load_settings(self):
if os.path.exists('app_settings.json'):
with open('app_settings.json', 'r', encoding='utf-8') as f:
try:
settings = json.load(f)
try:
self.NAI_ID = settings["NAI_ID"] if len(settings["NAI_ID"]) > 2 else None
except: pass
try:
self.access_token = settings["access_token"] if len(settings["access_token"]) > 2 else None
if self.access_token:
self.NAI_Account_Login.configure(state="disabled")
self.NAI_Token_Remove.configure(state="normal")
self.NAI_Account_State.configure(text="NAI Login : OK")
self.image_generation_button.configure(state="normal")
except: pass
try:
self.search_label_entry.insert(0, settings["searach_keyword"])
except: pass
try:
self.exclude_label_entry.insert(0, settings["exclude_keyword"])
except: pass
try:
self.rating_select_var_explicit.set(settings["explicit"])
if settings["explicit"] == 1: self.rating_select_explicit.select()
else: self.rating_select_explicit.deselect()
except: pass
try:
self.rating_select_var_nsfw.set(settings[ "nsfw"])
if settings["nsfw"] == 1: self.rating_select_nsfw.select()
else: self.rating_select_nsfw.deselect()
except: pass
try:
self.rating_select_var_sensitive.set(settings["sensitive"])
if settings["sensitive"] == 1: self.rating_select_sensitive.select()
else: self.rating_select_sensitive.deselect()
except: pass
try:
self.rating_select_var_general.set(settings["general"])
if settings["general"] == 1: self.rating_select_general.select()
else: self.rating_select_general.deselect()
except: pass
try:
self.rm_artist_name_var = settings["rm_artist"]
if settings["rm_artist"] == 1: self.rm_artist_name_button.select()
else: self.rm_artist_name_button.deselect()
except: pass
try:
self.rm_copyright_name_var = settings["rm_copyright"]
if settings["rm_copyright"] == 1: self.rm_copyright_name_button.select()
else: self.rm_copyright_name_button.deselect()
except: pass
try:
self.rm_characteristic_var = settings["rm_character"]
if settings["rm_character"] == 1: self.rm_characteristic_button.select()
else: self.rm_characteristic_button.deselect()
except: pass
try:
self.text_input.insert("0.0", settings["prompt"])
except: pass
try:
self.negative_prompt_input.delete("0.0", "end")
self.negative_prompt_input.insert("0.0", settings["negative"])
except: pass
try:
self.fixed_prompt_input.insert("0.0", settings["fix"])
except: pass
try:
self.fixed_prompt_after_input.insert("0.0", settings["after"])
except: pass
try:
self.auto_hide_keyword_input.insert("0.0", settings[ "auto_hide"])
except: pass
try:
self.cfg_scale_entry.delete(0, "end")
self.cfg_scale_entry.insert(0, str(settings["cfg_scale"]))
self.cfg_scale_var.set(settings["cfg_scale"])
except: pass
try:
self.prompt_guidance_rescale_entry.delete(0, "end")
self.prompt_guidance_rescale_entry.insert(0, str(settings["guidance"]))
self.prompt_guidance_rescale_var.set(settings["guidance"])
except: pass
try:
self.sampler_var.set(settings["sampler"])
self.sampler_button.set(settings["sampler"])
except: pass
try:
self.random_resolution_var.set(settings["random"])
if settings["random"] == 1: self.random_resolution_button.select()
else: self.random_resolution_button.deselect()
except: pass
try:
self.sema_button_var.set(settings["sema"])
if settings["sema"] == 1: self.sema_button.select()
else: self.sema_button.deselect()
except: pass
try:
self.dyn_button_var.set(settings["dyn"])
if settings["dyn"] == 1: self.dyn_button.select()
else: self.dyn_button.deselect()
except: pass
try:
if settings["personal_folder"] == True:
self.output_file_path_personal =True
self.output_file_path = settings["save_folder"]
else: self.output_file_path_personal =False
except: pass
try:
self.name_var.set(settings["png_rule"])
except: pass
try:
self.auto_quality_toggle_var=settings["quality_toggle"]
if settings["quality_toggle"] == 1: self.auto_quality_toggle.select()
else: self.auto_quality_toggle.deselect()
except: pass
except json.JSONDecodeError as e:
self.image_label_report.configure(state="normal", text_color = "#FFFF97")
self.image_label_report.insert("0.0", "์„ธ์ด๋ธŒ ํŒŒ์ผ์„ ๋ถˆ๋Ÿฌ์˜ค๋Š”๋ฐ ์‹คํŒจํ•˜์˜€์Šต๋‹ˆ๋‹ค : " + str(e))
self.image_label_report.configure(state="disabled")
if os.path.exists('txt2img_temp_prompt.parquet'):
try:
self.cached_rows = pd.read_parquet('txt2img_temp_prompt.parquet')
self.cached_prompt_label.configure(text = "๋‚จ์€ ํ”„๋กฌํ”„ํŠธ ํ–‰ : "+str(len(self.cached_rows)))
except: pass
def exit_program(self):
self.save_settings()
app.destroy()
def get_max_size(self):
width = self.winfo_screenheight()
return 768 if width < 1440 else 768
def update_fullscreen_image(self,new_window, new_image_label):
last_updated_image = None
while True:
time.sleep(1)
if not new_window.winfo_exists():
break
if self.image_queue:
current_image = Image.open(self.image_queue[self.window-1][3])
if current_image and current_image != last_updated_image:
#resized_image = self.resize_image_to_fit(current_image, new_window.winfo_screenheight())
original_width, original_height = current_image.size
ratio = new_window.winfo_screenheight() / float(original_height)
new_width = int(original_width * ratio)
tk_image = customtkinter.CTkImage(current_image, size=(new_width,new_window.winfo_screenheight()))
new_window.after(0, lambda img=tk_image: new_image_label.configure(image=img))
new_image_label.image = tk_image
last_updated_image = current_image
def show_fullscreen_image(self):
new_window = customtkinter.CTkToplevel()
new_window.attributes('-fullscreen', True)
new_window.state('zoomed')
new_window.configure(bg='black')
new_image_label = customtkinter.CTkLabel(new_window, text=" ")
new_image_label.pack(expand=True, fill='both')
new_window.bind("<Escape>", lambda e: new_window.destroy())
update_thread = threading.Thread(target=self.update_fullscreen_image, args=(new_window, new_image_label), daemon=True)
update_thread.daemon = True
update_thread.start()
def resize_image_to_fit(self, image, target_height):
original_width, original_height = image.size
ratio = target_height / float(original_height)
new_width = int(original_width * ratio)
resized_image = image.resize((new_width, target_height), Image.Resampling.LANCZOS)
return resized_image
def open_prompt_window(self):
prompt_window = customtkinter.CTkToplevel()
prompt_window.title("์ถ”์ฒœ ํ”„๋กฌํ”„ํŠธ")
prompt_window.attributes('-topmost', True)
prompt_window.resizable(width=False, height=False)
text_label1 = customtkinter.CTkLabel(prompt_window, text="๊ฒ€์ƒ‰ ๊ฒฐ๊ณผ ๋‚ด ๊ณ ๋นˆ๋„ ํ‚ค์›Œ๋“œ", font=customtkinter.CTkFont('Pretendard', 13), width=500)
text_label1.grid(row=0, column=0, padx=5, pady=5, sticky="nsew")
text_output1 = customtkinter.CTkTextbox(prompt_window, height=250, width=350, font=customtkinter.CTkFont('Pretendard', 15))
text_output1.grid(row=1, column=0, padx=5, pady=5, sticky="nsew")
text_label2 = customtkinter.CTkLabel(prompt_window, text="๊ฒ€์ƒ‰ ๊ฒฐ๊ณผ ๋‚ด ์ž‘๊ฐ€๋ช… ์ˆœ์œ„", font=customtkinter.CTkFont('Pretendard', 13), width=500)
text_label2.grid(row=2, column=0, padx=5, pady=5, sticky="nsew")
text_output2 = customtkinter.CTkTextbox(prompt_window, height=250, width=350, font=customtkinter.CTkFont('Pretendard', 15))
text_output2.grid(row=3, column=0, padx=5, pady=5, sticky="nsew")
text_label3 = customtkinter.CTkLabel(prompt_window, text="๋งŽ์ด ์‚ฌ์šฉ๋œ ์บ๋ฆญํ„ฐ ์ˆœ์œ„", font=customtkinter.CTkFont('Pretendard', 13), width=500)
text_label3.grid(row=4, column=0, padx=5, pady=5, sticky="nsew")
text_output3 = customtkinter.CTkTextbox(prompt_window, height=250, width=350, font=customtkinter.CTkFont('Pretendard', 15))
text_output3.grid(row=5, column=0, padx=5, pady=5, sticky="nsew")
if type(self.cached_rows) != type(None) and not self.cached_rows.empty:
counts1 = Counter()
ndf = self.cached_rows[self.cached_rows['general'].notnull()]
for row in ndf['general']:
if row != None:
substrings = [substring.strip() for substring in row.split(',') if substring.strip()]
counts1.update(substrings)
top_200_keywords = counts1.most_common(200)
formatted_keywords = [f"{keyword}: {count}" for keyword, count in top_200_keywords]
formatted_text = "\n".join(formatted_keywords)
text_output1.insert("0.0", formatted_text)
del[ndf]
counts2 = Counter()
ndf = self.cached_rows[self.cached_rows['artist'].notnull()]
for row in ndf['artist']:
if row != None:
substrings = [substring.strip() for substring in row.split(',') if substring.strip()]
counts2.update(substrings)
top_200_keywords = [(keyword, count) for keyword, count in counts2.most_common(200) if keyword in artist_dict]
formatted_keywords = [f"{keyword}: {count}" for keyword, count in top_200_keywords]
formatted_text = "\n".join(formatted_keywords)
text_output2.insert("0.0", formatted_text)
del[ndf]
counts3 = Counter()
ndf = self.cached_rows[self.cached_rows['character'].notnull()]
for row in ndf['character']:
if row != None:
substrings = [substring.strip() for substring in row.split(',') if substring.strip()]
counts3.update(substrings)
top_200_keywords = counts3.most_common(200)
formatted_keywords = [f"{keyword}: {count}" for keyword, count in top_200_keywords]
formatted_text = "\n".join(formatted_keywords)
text_output3.insert("0.0", formatted_text)
del[ndf]
def random_artist_window(self):
rartist_window = customtkinter.CTkToplevel()
rartist_window.title("๋žœ๋ค ์ž‘๊ฐ€๋ช… ์„ค์ •")
rartist_window.attributes('-topmost', True)
rartist_window.resizable(width=False, height=False)
rartist_window_left = customtkinter.CTkFrame(rartist_window, width=250)
rartist_window_left.grid(row=0, column=0, padx=5, pady=5, sticky="nsew")
#rartist_window_right = customtkinter.CTkFrame(rartist_window, width=250)
#rartist_window_right.grid(row=0, column=1, padx=5, pady=5, sticky="nsew")
text_label1 = customtkinter.CTkLabel(rartist_window_left, text="๋žœ๋ค ์ž‘๊ฐ€ ์‚ฝ์ž… ๋ฐฉ๋ฒ• ์„ ํƒ", font=customtkinter.CTkFont('Pretendard', 13), width=250)
text_label1.grid(row=0, column=0, padx=5, pady=5, sticky="nsew")
self.random_artist_select = customtkinter.StringVar()
ramdom_artist_global = customtkinter.CTkRadioButton(rartist_window_left, text="์ „์ฒด ์ž‘๊ฐ€๋ช… ๋ฆฌ์ŠคํŠธ์—์„œ", variable=self.random_artist_select, value="global", font=customtkinter.CTkFont('Pretendard', 13))
ramdom_artist_global.grid(row=1, column=0, padx=5, pady=5, sticky="w")
ramdom_artist_local = customtkinter.CTkRadioButton(rartist_window_left, text="๊ฒ€์ƒ‰ ํ”„๋กฌํ”„ํŠธ ์•ˆ์—์„œ", variable=self.random_artist_select, value="local", font=customtkinter.CTkFont('Pretendard', 13))
ramdom_artist_local.grid(row=2, column=0, padx=5, pady=5, sticky="w")
text_label2 = customtkinter.CTkLabel(rartist_window_left, text="๋‹จ๋ถ€๋ฃจ ๋‚ด ์ตœ์†Œ ์ด๋ฏธ์ง€ ์ˆ˜ ์„ค์ •(์ตœ์†Œ: 80)", font=customtkinter.CTkFont('Pretendard', 13), width=250)
text_label2.grid(row=3, column=0, padx=5, pady=5, sticky="nsew")
self.danbooru_minimum = customtkinter.IntVar(value=80)
danbooru_entry = customtkinter.CTkEntry(rartist_window_left, textvariable=self.danbooru_minimum, font=customtkinter.CTkFont('Pretendard', 13), width=50)
danbooru_entry.grid(row=4, column=0, padx=5, pady=5, sticky="n")
danbooru_set = customtkinter.CTkButton(rartist_window_left, text="์ƒˆ๋กœ ํƒ‘์žฌ",font=customtkinter.CTkFont('Pretendard', 13), width=50, command=self.get_artist)
danbooru_set.grid(row=5, column=0, padx=5, pady=5, sticky="n")
self.random_artist_list_length = customtkinter.CTkLabel(rartist_window_left, text="total length : 0", font=customtkinter.CTkFont('Pretendard', 13), width=250)
self.random_artist_list_length.grid(row=6, column=0, padx=5, pady=5, sticky="nsew")
text_label3 = customtkinter.CTkLabel(rartist_window_left, text="์ž‘๊ฐ€๋ช… ์‚ฝ์ž… ๋ฐฉ์‹", font=customtkinter.CTkFont('Pretendard', 13), width=250)
text_label3.grid(row=7, column=0, padx=5, pady=5, sticky="nsew")
random_artist_radio1 = customtkinter.CTkRadioButton(rartist_window_left, text="์•ž์— artist: ๋ถ™์ด๊ธฐ", variable=self.random_artist_prefix, value="artist:", font=customtkinter.CTkFont('Pretendard', 13))
random_artist_radio1.grid(row=8, column=0, padx=5, pady=5, sticky="w")
random_artist_radio2 = customtkinter.CTkRadioButton(rartist_window_left, text="๋’ค์— (artist) ๋ถ™์ด๊ธฐ", variable=self.random_artist_prefix, value="(artist)", font=customtkinter.CTkFont('Pretendard', 13))
random_artist_radio2.grid(row=9, column=0, padx=5, pady=5, sticky="w")
random_artist_radio3 = customtkinter.CTkRadioButton(rartist_window_left, text="๊ธฐ๋ณธ ์Šคํƒ€์ผ๋กœ", variable=self.random_artist_prefix, value="none", font=customtkinter.CTkFont('Pretendard', 13))
random_artist_radio3.grid(row=10, column=0, padx=5, pady=5, sticky="w")
self.random_artist_list = customtkinter.CTkTextbox(rartist_window_left, height=350, width=250, font=customtkinter.CTkFont('Pretendard', 15))
self.random_artist_list.grid(row=11, column=0, padx=5, pady=5, sticky="nsew")
text_label4 = customtkinter.CTkLabel(rartist_window_left, text="๊ณ ์ • ํ”„๋กฌํ”„ํŠธ์—์„œ๋Š” <random_artist>๋กœ ํ˜ธ์ถœ", font=customtkinter.CTkFont('Pretendard', 13), width=250)
text_label4.grid(row=12, column=0, padx=5, pady=5, sticky="nsew")
#TODO : ์ •๊ทœ์‹ ๊ธฐ๋ฐ˜์˜ ๋žœ๋ค์ž‘๊ฐ€ ์ธ์›/๋ธŒ๋ž˜ํ‚ท ๊ด€๋ฆฌ ๊ธฐ๋Šฅ ์ถ”๊ฐ€
#text_label4 = customtkinter.CTkLabel(rartist_window_right, text="๋žœ๋ค์ž‘๊ฐ€ ์ˆ˜ ๊ฐ€์ค‘์น˜", font=customtkinter.CTkFont('Pretendard', 13), width=250)
#text_label4.grid(row=0, column=0, padx=5, pady=5, sticky="nsew")
#text_label5 = customtkinter.CTkLabel(rartist_window_right, text="๊ฐ€์ค‘์น˜:int, ์ž‘๊ฐ€์ˆ˜(int), ", font=customtkinter.CTkFont('Pretendard', 13), width=250)
#text_label5.grid(row=1, column=0, padx=5, pady=5, sticky="nsew")
def reactivate_wildcards(self):
self.activate_wildcards()
pretty_string = ""
for key, value in self.wildcard_dict.items():
pretty_string += f"{key}: {value}\n"
self.wildcard_text.configure(state="normal")
self.wildcard_text.delete('0.0', "end")
self.wildcard_text.insert('0.0', pretty_string)
self.wildcard_text.configure(state="disabled")
def open_wildcard_folder(self):
if not os.path.exists(self.wildcards_dir):
os.makedirs(self.wildcards_dir)
os.startfile(self.wildcards_dir)
def open_wildcard_window(self):
wildcard_window = customtkinter.CTkToplevel()
wildcard_window.title("์™€์ผ๋“œ์นด๋“œ ๊ด€๋ฆฌ")
wildcard_window.attributes('-topmost', True)
wildcard_window.resizable(width=False, height=False)
wildcard_window_left = customtkinter.CTkFrame(wildcard_window)
wildcard_window_left.grid(row=0, column=0, sticky="nsew")
wildcard_window_right = customtkinter.CTkFrame(wildcard_window)
wildcard_window_right.grid(row=0, column=1, sticky="nsew")
text_label_frame = customtkinter.CTkFrame(wildcard_window_right, fg_color="#2B2B2B")
text_label_frame.grid(row=0, column=0, padx=5, pady=5, sticky="nsew")
text_label3 = customtkinter.CTkLabel(text_label_frame, text="์™€์ผ๋“œ์นด๋“œ ๊ด€๋ฆฌ", font=customtkinter.CTkFont('Pretendard', 13), width=300)
text_label3.grid(row=0, column=0, padx=5, pady=5, sticky="nsew")
text_hyperlink = customtkinter.CTkLabel(text_label_frame, text="๊ฐ€์ด๋“œ ์—ด๊ธฐ (arca.live)", font=customtkinter.CTkFont('Pretendard', 13), width=180, text_color="lightblue", cursor="hand2")
text_hyperlink.grid(row=0, column=1, padx=5, pady=5, sticky="nsew")
text_hyperlink.bind("<Button-1>", lambda e: webbrowser.open_new("https://arca.live/b/aiart/95877361"))
def wildcard_folder_callback(choice):
if choice != '':
if choice != '(+) ํด๋” ์ถ”๊ฐ€':
value = list(self.wildcard_dict[wildcard_folder_select_var.get()])+['(+) ์ƒˆ ์™€์ผ๋“œ์นด๋“œ']
wildcard_folder_select_var.set(choice)
wildcard_file_select.configure(values=value)
wildcard_file_select.set('')
else:
value = list(self.wildcard_dict.keys())
dialog = customtkinter.CTkInputDialog(text="์ƒˆ ์™€์ผ๋“œ์นด๋“œ ํด๋”๋ช…์„ ์ž…๋ ฅํ•˜์„ธ์š” (๊ฐ™์€ ์ด๋ฆ„ ๋ถˆ๊ฐ€):", title="ํด๋” ์ƒ์„ฑ")
input_value = dialog.get_input()
if input_value and input_value not in value:
os.makedirs(self.wildcards_dir+'/'+input_value)
self.reactivate_wildcards()
wildcard_folder_select.configure(values=list(self.wildcard_dict.keys())+['(+) ํด๋” ์ถ”๊ฐ€'])
wildcard_folder_select.set(input_value)
wildcard_file_select.set('')
else:
wildcard_folder_select.set('')
def wildcard_select_callback(choice):
if choice != '':
if choice == '(+) ์ƒˆ ์™€์ผ๋“œ์นด๋“œ':
value = list(self.wildcard_dict[wildcard_folder_select_var.get()])
dialog = customtkinter.CTkInputDialog(text="์ƒˆ ์™€์ผ๋“œ์นด๋“œ์˜ ์ด๋ฆ„์„ ์ž…๋ ฅํ•˜์„ธ์š” (๊ฐ™์€ ์ด๋ฆ„ ๋ถˆ๊ฐ€):", title="์™€์ผ๋“œ์นด๋“œ ์ƒ์„ฑ")
input_value = dialog.get_input()
if input_value and input_value not in value:
filepath = self.wildcards_dir+'/'+input_value if wildcard_folder_select_var.get() == "none" else self.wildcards_dir+'/'+wildcard_folder_select_var.get()+'/'+input_value
with open(filepath+'.txt', 'w') as file:
pass
self.reactivate_wildcards()
value2 = list(self.wildcard_dict[wildcard_folder_select_var.get()])+['(+) ์ƒˆ ์™€์ผ๋“œ์นด๋“œ']
wildcard_file_select.configure(values=value2)
wildcard_file_select.set('')
else:
self.wildcard_file_select_var = choice if wildcard_folder_select_var.get() == "none" else wildcard_folder_select_var.get()+'/'+choice
filepath = self.wildcards_dir+'/'+choice if wildcard_folder_select_var.get() == "none" else self.wildcards_dir+'/'+wildcard_folder_select_var.get()+'/'+choice
if os.path.exists(filepath):
with open(filepath, 'r', encoding='utf-8') as file:
lines = file.readlines()
updated_lines = []
for line in lines:
line = line.strip()
updated_lines.append(line)
wildcard_select_text.configure(state="normal")
wildcard_select_text.delete("0.0","end")
wildcard_select_text.insert("0.0", '\n'.join(updated_lines))
wildcard_select_text.configure(state="disabled")
self.current_wildcard_path = filepath
def fix_wildcard():
if fix_button.cget("text") == "์ˆ˜์ •":
save_button.configure(state="normal")
wildcard_select_text.configure(state="normal")
fix_button.configure(text="์ทจ์†Œ")
wildcard_folder_select.configure(state="disabled")
wildcard_file_select.configure(state="disabled")
coy_button.configure(state="disabled")
elif fix_button.cget("text") == "์ทจ์†Œ":
save_button.configure(state="disabled")
wildcard_select_text.configure(state="disabled")
fix_button.configure(text="์ˆ˜์ •")
wildcard_folder_select.configure(state="normal")
wildcard_file_select.configure(state="normal")
coy_button.configure(state="normal")
def save_wildcard():
text = wildcard_select_text.get("1.0", "end-1c")
with open(self.current_wildcard_path, "w", encoding="utf-8") as file:
file.write(text)
wildcard_select_text.configure(state="disabled")
fix_button.configure(text="์ˆ˜์ •")
wildcard_folder_select.configure(state="normal")
wildcard_file_select.configure(state="normal")
coy_button.configure(state="normal")
save_button.configure(state="disabled")
def copy_wildcard():
text = self.wildcard_file_select_var
text = text.replace(".txt","")
pyperclip.copy('<'+text+'>')
wildcard_window_select_frame = customtkinter.CTkFrame(wildcard_window_right)
wildcard_window_select_frame.grid(row=1, column=0, sticky="n")
text_label4 = customtkinter.CTkLabel(wildcard_window_select_frame, text="ํด๋” ์„ ํƒ:", font=customtkinter.CTkFont('Pretendard', 13))
text_label4.grid(row=0, column=0, padx=15, pady=5, sticky="nsew")
text_label5 = customtkinter.CTkLabel(wildcard_window_select_frame, text="ํŒŒ์ผ ์„ ํƒ:", font=customtkinter.CTkFont('Pretendard', 13))
text_label5.grid(row=0, column=2, padx=15, pady=5, sticky="nsew")
wildcard_folder_select_var = customtkinter.StringVar(value="none")
wildcard_folder_select = customtkinter.CTkComboBox(wildcard_window_select_frame,values=list(self.wildcard_dict.keys())+['(+) ํด๋” ์ถ”๊ฐ€'],command=wildcard_folder_callback, variable=wildcard_folder_select_var, font=customtkinter.CTkFont('Pretendard', 13))
wildcard_folder_select.grid(row=0, column=1, padx=15, pady=5, sticky="nsew")
self.wildcard_file_select_var = ""
self.current_wildcard_path = ""
wildcard_file_select = customtkinter.CTkComboBox(wildcard_window_select_frame,values=list(self.wildcard_dict[wildcard_folder_select_var.get()])+['(+) ์ƒˆ ์™€์ผ๋“œ์นด๋“œ'],command=wildcard_select_callback, font=customtkinter.CTkFont('Pretendard', 13))
wildcard_file_select.grid(row=0, column=3, padx=15, pady=5, sticky="nsew")
wildcard_file_select.set("")
text_label6 = customtkinter.CTkLabel(wildcard_window_select_frame, text="ํด๋” ๋ฐ ํŒŒ์ผ์˜ ์‚ญ์ œ๊ธฐ๋Šฅ์€ ์ œ๊ณต๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ์™€์ผ๋“œ์นด๋“œ ํด๋”์—์„œ ์ง์ ‘ ์‚ญ์ œํ•˜์„ธ์š”.", font=customtkinter.CTkFont('Pretendard', 13))
text_label6.grid(row=1, column=0, columnspan=4, padx=5, pady=5, sticky="n")
fix_button = customtkinter.CTkButton(wildcard_window_select_frame, text="์ˆ˜์ •", font=customtkinter.CTkFont('Pretendard', 13), width=100, hover_color="grey10", command=fix_wildcard)
fix_button.grid(row=2, column=0, padx=15, pady=5, sticky="n")
save_button = customtkinter.CTkButton(wildcard_window_select_frame, text="์ €์žฅ", font=customtkinter.CTkFont('Pretendard', 13), width=100, fg_color="grey", hover_color="grey10", command=save_wildcard, state="disabled")
save_button.grid(row=2, column=1, padx=15, pady=5, sticky="n")
coy_button = customtkinter.CTkButton(wildcard_window_select_frame, text="<์™€์ผ๋“œ์นด๋“œ>๋ฅผ ํด๋ฆฝ๋ณด๋“œ์— ๋ณต์‚ฌ", font=customtkinter.CTkFont('Pretendard', 13), fg_color="#7030A0", hover_color="#481F67", command=copy_wildcard)
coy_button.grid(row=2, column=2, columnspan=2, padx=5, pady=5, sticky="n")
text_label7 = customtkinter.CTkLabel(wildcard_window_right, text="<UserAttention> Enter ์ž…๋ ฅ์‹œ ๋‹ค๋ฅธ ํ–‰์œผ๋กœ ์ทจ๊ธ‰๋ฉ๋‹ˆ๋‹ค. ์ˆ˜์ • ํ›„ ๊ผญ ์ €์žฅ ๋ฒ„ํŠผ์„ ๋ˆ„๋ฅด์„ธ์š”.", font=customtkinter.CTkFont('Pretendard', 13), text_color="#FFFF97")
text_label7.grid(row=3, column=0, columnspan=4, padx=5, pady=5, sticky="n")
wildcard_select_text = customtkinter.CTkTextbox(wildcard_window_right, font=customtkinter.CTkFont('Pretendard', 14), width=490, height=280, state="disabled")
wildcard_select_text.grid(row=2, column=0, columnspan=4, padx=5, pady=5, sticky="nsew")
#wildcard_window_left = customtkinter.CTkFrame(wildcard_window, width=500)
#wildcard_window_left.grid(row=0, column=0, padx=5, pady=5, sticky="nsew")
text_label1 = customtkinter.CTkLabel(wildcard_window_left, text="์™€์ผ๋“œ์นด๋“œ ์ •๋ณด", font=customtkinter.CTkFont('Pretendard', 13), width=500)
text_label1.grid(row=0, column=0, padx=5, pady=5, sticky="nsew")
self.wildcard_text = customtkinter.CTkTextbox(wildcard_window_left, font=customtkinter.CTkFont('Pretendard', 13), width=500)
self.wildcard_text.grid(row=1, column=0, padx=5, pady=5, sticky="nsew")
text_label2 = customtkinter.CTkLabel(wildcard_window_left, text="txtํŒŒ์ผ ๋‚ด ๊ฐ€์ค‘์น˜ ๋ฌธ๋ฒ•(100: keyword)์€ ๊ณ„์† ์œ ํšจํ•ฉ๋‹ˆ๋‹ค. default=100", font=customtkinter.CTkFont('Pretendard', 13), width=500)
text_label2.grid(row=2, column=0, padx=5, pady=5, sticky="nsew")
self.wildcard_button_frame = customtkinter.CTkFrame(wildcard_window_left)
self.wildcard_button_frame.grid(row=3, column=0, padx=5, pady=5, sticky="n")
self.reactive_button = customtkinter.CTkButton(self.wildcard_button_frame, font=customtkinter.CTkFont('Pretendard', 13), text="์™€์ผ๋“œ์นด๋“œ ์—…๋ฐ์ดํŠธ", command= self.reactivate_wildcards)
self.reactive_button.grid(row=0, column=0, padx=5, pady=5, sticky="n")
self.open_wildcard_button = customtkinter.CTkButton(self.wildcard_button_frame, font=customtkinter.CTkFont('Pretendard', 13), text="์™€์ผ๋“œ์นด๋“œ ํด๋” ์—ด๊ธฐ", command= self.open_wildcard_folder)
self.open_wildcard_button.grid(row=0, column=1, padx=15, pady=5, sticky="n")
self.wildcard_text_sample = customtkinter.CTkTextbox(wildcard_window_left, font=customtkinter.CTkFont('Pretendard', 13), width=500, height=100, text_color="#FFFF97")
self.wildcard_text_sample.grid(row=4, column=0, padx=5, pady=5, sticky="nsew")
self.wildcard_text_sample.insert("0.0", "Example : 1girl, <koharu (blue archive)|noa (blue archive)|unicorn (azur lane)|<characters>>, <random_artist>, <happy|surprised|depressed>, <<__colors__clothes>|<{{clothes}}>>, looking at viewer")
self.wildcard_text_sample.configure(state="disabled")
text_label3 = customtkinter.CTkLabel(wildcard_window_left, text="<keyword1|keyword2> ํ˜•ํƒœ ํ‘œ๊ธฐ๋Š” '|'๋กœ ๊ตฌ๋ถ„๋˜๋Š” ์ธ์Šคํ„ดํŠธ ์™€์ผ๋“œ์นด๋“œ์ž…๋‹ˆ๋‹ค.", font=customtkinter.CTkFont('Pretendard', 13), width=500)
text_label3.grid(row=5, column=0, padx=5, pady=5, sticky="nsew")
self.reactivate_wildcards()
def get_artist(self):
self.random_artist_list.delete("0.0", "end")
danbooru_minimum = self.danbooru_minimum.get()
if self.random_artist_select.get() == "local":
counts = Counter()
ndf = self.cached_rows[self.cached_rows['artist'].notnull()]
for row in ndf['artist']:
if row != None:
substrings = [substring.strip() for substring in row.split(',') if substring.strip()]
counts.update(substrings)
top_500_keywords = [(keyword, count) for keyword, count in counts.most_common(500) if keyword in artist_dict]
filtered_keywords = [(keyword, count) for keyword, count in top_500_keywords if artist_dict.get(keyword, 0) > danbooru_minimum]
formatted_keywords = [f"{keyword}: {count}" for keyword, count in filtered_keywords]
keywords_only = [item.split(": ")[0] for item in formatted_keywords]
self.random_artist_list_length.configure(text='total length : ' + str(len(filtered_keywords)))
self.random_artist = keywords_only
try:
with open("wildcards/random_artist.txt", 'w') as file:
for keyword in keywords_only:
if self.random_artist_prefix.get() == "artist:":
file.write("artist:"+ keyword + '\n')
elif self.random_artist_prefix.get() == "(artist)":
file.write(keyword + ' (artist)\n')
else:
file.write(keyword + '\n')
except: pass
formatted_text = "\n".join(formatted_keywords)
self.random_artist_list.insert("0.0", formatted_text)
else:
filtered_keywords = [keyword for keyword, count in artist_dict.items() if count > danbooru_minimum]
formatted_keywords = [f"{keyword}: {count}" for keyword, count in artist_dict.items() if count > danbooru_minimum]
self.random_artist_list_length.configure(text='total length : ' + str(len(filtered_keywords)))
formatted_text = "\n".join(formatted_keywords)
self.random_artist_list.insert("0.0", formatted_text)
self.random_artist = filtered_keywords
try:
with open("wildcards/random_artist.txt", 'w') as file:
for keyword in filtered_keywords:
if self.random_artist_prefix.get() == "artist:":
file.write("artist:"+ keyword + '\n')
elif self.random_artist_prefix.get() == "(artist)":
file.write(keyword + ' (artist)\n')
else:
file.write(keyword + '\n')
except: pass
self.random_artist_button.configure(state="normal")
def activate_wildcards(self):
wildcards_dir = os.path.join(os.getcwd(), 'wildcards')
# wildcards ํด๋”๊ฐ€ ์žˆ๋Š”์ง€ ํ™•์ธํ•˜๊ณ , ์—†์œผ๋ฉด ์ƒ์„ฑ
if not os.path.exists(wildcards_dir):
os.makedirs(wildcards_dir)
# wildcard_dict ๋”•์…”๋„ˆ๋ฆฌ ์ดˆ๊ธฐํ™”
wildcard_dict = {'none': []}
# wildcards ํด๋” ๋‚ด์˜ ํŒŒ์ผ ๋ฐ ํด๋”๋ช… ํš๋“
for item in os.listdir(wildcards_dir):
item_path = os.path.join(wildcards_dir, item)
# ํŒŒ์ผ์ธ ๊ฒฝ์šฐ
if os.path.isfile(item_path) and item.endswith('.txt'):
wildcard_dict['none'].append(item)
# ํด๋”์ธ ๊ฒฝ์šฐ
elif os.path.isdir(item_path):
wildcard_dict[item] = []
# ํ•ด๋‹น ํด๋” ๋‚ด์˜ ํŒŒ์ผ๋“ค์„ ํƒ์ƒ‰
for subitem in os.listdir(item_path):
subitem_path = os.path.join(item_path, subitem)
if os.path.isfile(subitem_path) and subitem.endswith('.txt'):
wildcard_dict[item].append(subitem)
self.wildcard_dict = wildcard_dict
self.wildcards_dir = wildcards_dir
def get_wildcard(self, input_str):
def read_file_with_fallback(file_path, encodings=['utf-8', 'cp949']):
for encoding in encodings:
try:
with open(file_path, 'r', encoding=encoding, errors='ignore') as file:
return file.readlines()
except UnicodeDecodeError:
continue
return None
bracket_count = input_str.count('[')
brace_count = input_str.count('{')
modified_input_str = input_str.replace('[', '').replace(']', '').replace('{', '').replace('}', '')
file_path = ""
if '/' in modified_input_str:
folder, filename = modified_input_str.split('/', 1)
file_path = os.path.join(self.wildcards_dir, folder, filename + '.txt')
valid_file = folder in self.wildcard_dict and filename + ".txt" in self.wildcard_dict[folder] and os.path.exists(file_path)
else:
file_path = os.path.join(self.wildcards_dir, modified_input_str + ".txt")
valid_file = modified_input_str + ".txt" in self.wildcard_dict['none'] and os.path.exists(file_path)
if valid_file:
lines = read_file_with_fallback(file_path)
if lines:
choice_dic = {}
for line in lines:
match = re.match(r'(\d*\.?\d+):(.+)', line)
if match:
value, keyword = float(match.group(1)), match.group(2).strip()
else:
value, keyword = 100, line.strip()
choice_dic[keyword] = value
keywords = list(choice_dic.keys())
weights = list(choice_dic.values())
result = random.choices(keywords, weights=weights, k=1)[0].strip()
else:
result = modified_input_str
if brace_count > 0:
return '{' * brace_count + result + '}' * brace_count
elif bracket_count > 0:
return '[' * bracket_count + result + ']' * bracket_count
else:
return result
#Code from https://github.com/DCP-arca/NAI-Auto-Generator/blob/main/nai_generator.py
#Author : DCP-arca
def get_anlas(self):
try:
response = requests.get("https://api.novelai.net/user/subscription", headers={
"Authorization": f"Bearer {self.access_token}"})
data_dict = json.loads(response.content)
trainingStepsLeft = data_dict['trainingStepsLeft']
anlas = int(trainingStepsLeft['fixedTrainingStepsLeft']) + \
int(trainingStepsLeft['purchasedTrainingSteps'])
app.my_anlas.set(anlas)
self.anlas_label.configure(text="Anlas : "+str(app.my_anlas.get()), text_color="#FFFF97")
except Exception as e:
print(e)
return None
if __name__ == "__main__":
customtkinter.set_appearance_mode("dark")
app = App()
app.load_settings()
app.protocol("WM_DELETE_WINDOW", app.exit_program)
app.activate_wildcards()
app.get_anlas()
app.after(1000, lambda: setattr(app, 'last_window_size', (app.winfo_width(), app.winfo_height())))
app.mainloop()