baqu2213's picture
Upload 3 files
5d2f4e4
raw
history blame
No virus
192 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
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(',')]
keyword = keywords[1]
keywords[1] = '{{'+keyword+'}}'
keywords.insert(2, concat_entry)
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)
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)
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=700)
collection_frame_left.grid(row =1, column =0, padx=5, pady=5, sticky="nsew")
collection_frame_right = customtkinter.CTkScrollableFrame(collection_window, width=900, height=700)
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=50, 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_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, width=500)
#wildcard_window_left.grid(row=0, column=0, padx=5, pady=5, sticky="nsew")
text_label1 = customtkinter.CTkLabel(wildcard_window, 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, 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, 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.reactive_button = customtkinter.CTkButton(wildcard_window, font=customtkinter.CTkFont('Pretendard', 13), text="μ™€μΌλ“œμΉ΄λ“œ μ—…λ°μ΄νŠΈ", command= self.reactivate_wildcards)
self.reactive_button.grid(row=3, column=0, padx=5, pady=5, sticky="n")
self.wildcard_text_sample = customtkinter.CTkTextbox(wildcard_window, 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, 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()