1+ import tkinter as tk
2+ from tkinter import filedialog
3+ import subprocess
4+ import os
5+ from PIL import ImageTk , Image
6+
7+ # File path for saving and loading the values
8+ config_file_path = os .path .join (os .path .dirname (__file__ ), "config.txt" )
9+
10+ # Function to save the values to a file
11+ def save_config ():
12+ config_data = {
13+ "mode" : mode_entry .get () or "" ,
14+ "threads" : threads_entry .get () or "" ,
15+ "model" : model_entry .get () or "" ,
16+ "vae" : vae_model_dir_entry .get () or "" ,
17+ "lora_model_dir" : lora_model_dir_entry .get () or "" ,
18+ "positive_prompt" : positive_prompt_entry .get () or "" ,
19+ "negative_prompt" : negative_prompt_entry .get () or "" ,
20+ "cfg_scale" : cfg_scale_entry .get () or "" ,
21+ "height" : height_entry .get () or "" ,
22+ "width" : width_entry .get () or "" ,
23+ "steps" : steps_entry .get () or "" ,
24+ "seed" : seed_entry .get () or "" ,
25+ "control_model" : control_model_entry .get () or "" ,
26+ "control_image" : control_image_entry .get () or "" ,
27+ "control_st" : control_st_entry .get () or ""
28+ }
29+
30+ with open (config_file_path , "w" ) as f :
31+ for key , value in config_data .items ():
32+ f .write (f"{ key } : { value } \n " )
33+
34+ # Function to load the values from the file
35+ def load_config ():
36+ if os .path .exists (config_file_path ):
37+ with open (config_file_path , "r" ) as f :
38+ config_data = {}
39+ for line in f :
40+ line = line .strip ()
41+ if line :
42+ if ": " in line :
43+ key , value = line .split (": " , 1 )
44+ config_data [key ] = value
45+
46+ mode_entry .delete (0 , tk .END )
47+ mode_entry .insert (0 , config_data .get ("mode" , "" ))
48+
49+ threads_entry .delete (0 , tk .END )
50+ threads_entry .insert (0 , config_data .get ("threads" , "" ))
51+
52+ model_entry .delete (0 , tk .END )
53+ model_entry .insert (0 , config_data .get ("model" , "" ))
54+
55+ vae_model_dir_entry .delete (0 , tk .END )
56+ vae_model_dir_entry .insert (0 , config_data .get ("vae_model_dir" , "" ))
57+
58+ lora_model_dir_entry .delete (0 , tk .END )
59+ lora_model_dir_entry .insert (0 , config_data .get ("lora_model_dir" , "" ))
60+
61+ positive_prompt_entry .delete (0 , tk .END )
62+ positive_prompt_entry .insert (0 , config_data .get ("positive_prompt" , "" ))
63+
64+ negative_prompt_entry .delete (0 , tk .END )
65+ negative_prompt_entry .insert (0 , config_data .get ("negative_prompt" , "" ))
66+
67+ cfg_scale_entry .delete (0 , tk .END )
68+ cfg_scale_entry .insert (0 , config_data .get ("cfg_scale" , "" ))
69+
70+ height_entry .delete (0 , tk .END )
71+ height_entry .insert (0 , config_data .get ("height" , "" ))
72+
73+ width_entry .delete (0 , tk .END )
74+ width_entry .insert (0 , config_data .get ("width" , "" ))
75+
76+ steps_entry .delete (0 , tk .END )
77+ steps_entry .insert (0 , config_data .get ("steps" , "" ))
78+
79+ seed_entry .delete (0 , tk .END )
80+ seed_entry .insert (0 , config_data .get ("seed" , "" ))
81+
82+ control_model_entry .delete (0 , tk .END )
83+ control_model_entry .insert (0 , config_data .get ("control_model" , "" ))
84+
85+ control_image_entry .delete (0 , tk .END )
86+ control_image_entry .insert (0 , config_data .get ("control_image" , "" ))
87+
88+ control_st_entry .delete (0 , tk .END )
89+ control_st_entry .insert (0 , config_data .get ("control_st" , "" ))
90+
91+ def run_sd ():
92+ # Save the values before running the program
93+ save_config ()
94+
95+ mode = mode_entry .get ()
96+ threads = threads_entry .get ()
97+ model = model_entry .get ()
98+ vae = vae_model_dir_entry .get ()
99+ lora_model_dir = lora_model_dir_entry .get ()
100+ positive_prompt = positive_prompt_entry .get ()
101+ negative_prompt = negative_prompt_entry .get ()
102+ cfg_scale = cfg_scale_entry .get ()
103+ height = height_entry .get ()
104+ width = width_entry .get ()
105+ steps = steps_entry .get ()
106+ seed = seed_entry .get ()
107+ control_model = control_model_entry .get ()
108+ control_image = control_image_entry .get ()
109+ control_st = control_st_entry .get ()
110+
111+ command = ['./sd' , '-M' , mode ,'-t' , threads , '-m' , model , '--lora-model-dir' ,lora_model_dir , '--vae' , vae , '-p' , positive_prompt , '-n' , negative_prompt , '--cfg-scale' , cfg_scale , '-H' , height , '-W' , width , '--steps' , steps ,'-s' , seed , '--control-net' , control_model ,'--control-image' , control_image ,'--control-strength' , control_st ,'--sampling-method' ,'lcm' ,'-v' ]
112+
113+ subprocess .run (command )
114+
115+ def browse_file (entry ):
116+ filename = filedialog .askopenfilename (initialdir = '/' , title = 'Select File' )
117+ entry .delete (0 , tk .END )
118+ entry .insert (tk .END , filename )
119+
120+ def browse_directory (entry ):
121+ directory = filedialog .askdirectory (initialdir = '/' , title = 'Select Directory' )
122+ entry .delete (0 , tk .END )
123+ entry .insert (tk .END , directory )
124+
125+ def on_hotkey (event ):
126+ if event .keysym == "r" and event .state == 8 : # Check for ALT key
127+ run_sd () # Call the button's function
128+
129+ root = tk .Tk ()
130+ root .title ("Stable-diffusion.cpp simple GUI" )
131+
132+ def check_file_modification ():
133+ global photo , last_modified
134+
135+ # Check if the output image file exists and has been modified
136+ if os .path .exists (output_image_path ) and os .path .getmtime (output_image_path ) > last_modified :
137+ # Load the updated image
138+ image = Image .open (output_image_path )
139+ photo = ImageTk .PhotoImage (image )
140+
141+ # Update the image in the GUI
142+ image_label .config (image = photo )
143+
144+ # Update the last modified timestamp
145+ last_modified = os .path .getmtime (output_image_path )
146+
147+ # Schedule the next check after a certain interval (in milliseconds)
148+ root .after (1000 , check_file_modification )
149+
150+
151+ output_image_path = "output.png" # Replace with the actual path of the output image file
152+ photo = None
153+
154+ # Mode
155+ mode_label = tk .Label (root , text = "Run mode (txt2img or img2img or convert):" )
156+ mode_label .grid (row = 0 , column = 0 )
157+ mode_entry = tk .Entry (root )
158+ mode_entry .grid (row = 0 , column = 1 )
159+
160+ # Threads
161+ threads_label = tk .Label (root , text = "Number of Threads:" )
162+ threads_label .grid (row = 1 , column = 0 )
163+ threads_entry = tk .Entry (root )
164+ threads_entry .grid (row = 1 , column = 1 )
165+
166+ # Model
167+ model_label = tk .Label (root , text = "Path to Model:" )
168+ model_label .grid (row = 2 , column = 0 )
169+ model_entry = tk .Entry (root ,width = 100 )
170+ model_entry .grid (row = 2 , column = 1 )
171+
172+ # VAE
173+ vae_model_dir_label = tk .Label (root , text = "Path to vae:" )
174+ vae_model_dir_label .grid (row = 3 , column = 0 )
175+ vae_model_dir_entry = tk .Entry (root ,width = 100 )
176+ vae_model_dir_entry .grid (row = 3 , column = 1 )
177+
178+ # LoRa Model Directory
179+ lora_model_dir_label = tk .Label (root , text = "LoRa Model Directory:" )
180+ lora_model_dir_label .grid (row = 4 , column = 0 )
181+ lora_model_dir_entry = tk .Entry (root ,width = 100 )
182+ lora_model_dir_entry .grid (row = 4 , column = 1 )
183+
184+ # Prompt
185+ positive_prompt_label = tk .Label (root , text = "Prompt:" )
186+ positive_prompt_label .grid (row = 5 , column = 0 )
187+ positive_prompt_entry = tk .Entry (root ,width = 100 )
188+ positive_prompt_entry .grid (row = 5 , column = 1 )
189+
190+ # Negative Prompt
191+ negative_prompt_label = tk .Label (root , text = "Negative Prompt:" )
192+ negative_prompt_label .grid (row = 6 , column = 0 )
193+ negative_prompt_entry = tk .Entry (root ,width = 100 )
194+ negative_prompt_entry .grid (row = 6 , column = 1 )
195+
196+ # CFG Scale
197+ cfg_scale_label = tk .Label (root , text = "CFG Scale:" )
198+ cfg_scale_label .grid (row = 7 , column = 0 )
199+ cfg_scale_entry = tk .Entry (root )
200+ cfg_scale_entry .grid (row = 7 , column = 1 )
201+
202+ # Height
203+ height_label = tk .Label (root , text = "Image Height:" )
204+ height_label .grid (row = 8 , column = 0 )
205+ height_entry = tk .Entry (root )
206+ height_entry .grid (row = 8 , column = 1 )
207+
208+ # Width
209+ width_label = tk .Label (root , text = "Image Width:" )
210+ width_label .grid (row = 9 , column = 0 )
211+ width_entry = tk .Entry (root )
212+ width_entry .grid (row = 9 , column = 1 )
213+
214+ # Steps
215+ steps_label = tk .Label (root , text = "Number of Steps:" )
216+ steps_label .grid (row = 10 , column = 0 )
217+ steps_entry = tk .Entry (root )
218+ steps_entry .grid (row = 10 , column = 1 )
219+
220+ # Seed
221+ seed_label = tk .Label (root , text = "Seed:" )
222+ seed_label .grid (row = 11 , column = 0 )
223+ seed_entry = tk .Entry (root )
224+ seed_entry .grid (row = 11 , column = 1 )
225+
226+ # ControlNet model
227+ control_model_label = tk .Label (root , text = "ControlNet model:" )
228+ control_model_label .grid (row = 12 , column = 0 )
229+ control_model_entry = tk .Entry (root ,width = 100 )
230+ control_model_entry .grid (row = 12 , column = 1 )
231+
232+ # ControlNet image
233+ control_image_label = tk .Label (root , text = "ControlNet image:" )
234+ control_image_label .grid (row = 13 , column = 0 )
235+ control_image_entry = tk .Entry (root ,width = 100 )
236+ control_image_entry .grid (row = 13 , column = 1 )
237+
238+ # ControlNet strength
239+ control_st_label = tk .Label (root , text = "ControlNet strength:" )
240+ control_st_label .grid (row = 14 , column = 0 )
241+ control_st_entry = tk .Entry (root )
242+ control_st_entry .grid (row = 14 , column = 1 )
243+
244+ # Run button
245+ run_button = tk .Button (root , text = "Run SD" , command = run_sd )
246+ run_button .grid (row = 15 , column = 0 )
247+ root .bind ("<Key>" , on_hotkey ) # Bind the hotkey to the root window
248+
249+ # Create a Label widget to display the image
250+ image_label = tk .Label (root )
251+ image_label .grid (row = 0 , column = 2 , rowspan = 12 , padx = 20 ) # Adjust rowspan and padx as needed
252+
253+ load_config ()
254+
255+ # Initialize the last modified timestamp
256+ last_modified = os .path .getmtime (output_image_path ) if os .path .exists (output_image_path ) else 0
257+
258+ # Start the file modification checking
259+ check_file_modification ()
260+
261+ root .mainloop ()
0 commit comments