bewiz commited on
Commit
2bc254b
·
verified ·
1 Parent(s): b949baa

Upload folder using huggingface_hub

Browse files
Files changed (3) hide show
  1. README.md +117 -0
  2. SD3 Batch Imagine.rar +3 -0
  3. app.py +138 -61
README.md CHANGED
@@ -4,3 +4,120 @@ app_file: app.py
4
  sdk: gradio
5
  sdk_version: 4.31.5
6
  ---
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4
  sdk: gradio
5
  sdk_version: 4.31.5
6
  ---
7
+
8
+
9
+ Sure, here is a detailed README for your script:
10
+
11
+ GroOvy SD3 Batch Imagine
12
+ Overview
13
+ The GroOvy SD3 Batch Imagine tool is designed for batch image generation using the SD3 Medium model. This tool allows users to input multiple prompts and generate images in batches, with options for negative prompts, and automated zipping of generated images for easy download. The integration with ComfyUI ensures a seamless workflow for AI-powered image generation.
14
+
15
+ Features
16
+ Batch Image Generation: Enter multiple prompts and generate images in bulk.
17
+ Negative Prompts: Specify negative prompts to refine image outputs.
18
+ Zip Interval: Set the interval at which images are zipped.
19
+ Real-time Progress Monitoring: Watch the progress of image generation in real-time.
20
+ Automated File Management: Generated images are automatically copied to user-specific folders and zipped at specified intervals.
21
+ Detailed Logging: Monitor detailed logs of the image generation process.
22
+ Prerequisites
23
+ Python 3.7 or higher
24
+ Required Python packages: requests, gradio, logging, shutil, zipfile, os, json, random, time
25
+ Installation
26
+ Clone the repository:
27
+ bash
28
+ Copy code
29
+ git clone https://github.com/your-repo/groovy-sd3-batch-imagine.git
30
+ Navigate to the project directory:
31
+ bash
32
+ Copy code
33
+ cd groovy-sd3-batch-imagine
34
+ Install the required packages:
35
+ bash
36
+ Copy code
37
+ pip install -r requirements.txt
38
+ Usage
39
+ Running the Application
40
+ To run the application, execute the following command in your terminal:
41
+
42
+ bash
43
+ Copy code
44
+ python app.py
45
+ Accessing the Interface
46
+ Once the application is running, you can access the Gradio interface via the provided local URL (http://127.0.0.1:7860) or a public URL if you choose to share it.
47
+
48
+ Interface Overview
49
+ Developer Information
50
+ This section provides information about the developer, BeWiZ, including contact details and social media links.
51
+
52
+ About SD3 Batch Imagine
53
+ Learn about the purpose and features of the GroOvy SD3 Batch Imagine tool.
54
+
55
+ Instructions
56
+ Follow these instructions to use the tool effectively:
57
+
58
+ Enter your prompts, one per empty line.
59
+ Enter your negative prompts, one per line (optional).
60
+ Set the zip interval to determine how many images will be included in each zip file.
61
+ Click "Process Prompts" to start generating images.
62
+ Click "Cancel Processing" to stop the current batch run.
63
+ Monitor the progress in real-time.
64
+ Download the generated zip files at the end of the process.
65
+ Components
66
+ Enter Prompts
67
+ Prompts: Input your image generation prompts here, one per empty line.
68
+ Negative Prompts: Input negative prompts here, one per line (optional).
69
+ Zip Interval: Specify the number of images per zip file.
70
+ Process Prompts Button: Start the batch image generation process.
71
+ Cancel Processing Button: Cancel the current batch run.
72
+ Progress: Displays real-time progress of image generation.
73
+ Generated Images
74
+ Gallery: Displays the generated images.
75
+ Zip Files
76
+ Zip Files: Displays the generated zip files for download.
77
+ Detailed Logs
78
+ Logs: Displays detailed logs of the image generation process.
79
+ Script Details
80
+ Constants
81
+ COMFYUI_DIR: Directory path for ComfyUI.
82
+ WORKFLOW_PATH: Path to the workflow JSON file.
83
+ OUTPUT_DIR: Directory path for output images.
84
+ URL: URL for sending the workflow to ComfyUI.
85
+ Functions
86
+ read_workflow(file_path)
87
+ Reads and returns the workflow JSON from the specified file path.
88
+
89
+ update_workflow(workflow, prompt, negative_prompt)
90
+ Updates the workflow with new prompts and negative prompts.
91
+
92
+ write_workflow(workflow, file_path)
93
+ Writes the updated workflow back to the specified file path.
94
+
95
+ send_workflow_to_comfyui(workflow, url)
96
+ Sends the updated workflow to ComfyUI and logs the response.
97
+
98
+ monitor_output_images(output_dir, previous_images, timeout=60)
99
+ Monitors the output directory for new images, returning the latest image found within the timeout period.
100
+
101
+ copy_file_with_retry(src, dst_dir, file_index, retries=5, delay=1)
102
+ Copies a file from the source to the destination directory, with retries in case of permission errors.
103
+
104
+ zip_files(output_images: List[str], zip_interval: int, zip_folder: str)
105
+ Creates zip files from the list of output images at specified intervals and saves them to the zip folder.
106
+
107
+ process_prompts(prompts_text, negative_prompt_text, user_folder, zip_interval)
108
+ Processes the prompts, generates images, copies them to the user folder, and zips them at specified intervals.
109
+
110
+ cancel_processing_fn()
111
+ Sets the cancel processing flag to True to stop the current batch run.
112
+
113
+ reset_cancel_processing_fn()
114
+ Resets the cancel processing flag to False.
115
+
116
+ Main Function
117
+ The main() function initializes the Gradio interface and sets up the UI components for entering prompts, monitoring progress, displaying generated images, zip files, and logs.
118
+
119
+ License
120
+ This project is licensed under the MIT License. See the LICENSE file for more details.
121
+
122
+ Contact
123
+ For any queries or support, please contact downlifted@gmail.com or reach out on Twitter @AiAnarchist.
SD3 Batch Imagine.rar ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:f1cd79d8cb6d2b736058367c93f8a7c4bf137af4782d9624080c4436475ee7ac
3
+ size 7112
app.py CHANGED
@@ -11,44 +11,44 @@ from typing import List
11
 
12
  # Define constants
13
  COMFYUI_DIR = r"C:\Users\bewiz\OneDrive\Desktop\AI\ComfyUI_windows_portable\ComfyUI"
14
- WORKFLOW_PATH = os.path.join(COMFYUI_DIR, 'sd3.json') # Updated to use the new workflow file
15
  OUTPUT_DIR = os.path.join(COMFYUI_DIR, 'output')
16
  URL = "http://127.0.0.1:8188/prompt"
17
 
18
  # Configure logging
19
  logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
20
 
21
- # Read the workflow JSON file
 
 
22
  def read_workflow(file_path):
23
  logging.info(f"Reading workflow from {file_path}")
24
  with open(file_path, 'r') as file:
25
  workflow = json.load(file)
26
  return workflow
27
 
28
- # Update the workflow with the new prompt
29
- def update_workflow(workflow, prompt):
30
- logging.info(f"Updating workflow with new prompt: {prompt}")
31
- workflow["6"]["inputs"]["text"] = prompt # Assuming the prompt should go into the same place in the new workflow
32
  return workflow
33
 
34
- # Write the updated workflow back to the JSON file
35
  def write_workflow(workflow, file_path):
36
  logging.info(f"Writing updated workflow to {file_path}")
37
  with open(file_path, 'w') as file:
38
  json.dump(workflow, file, indent=4)
39
 
40
- # Send the workflow to ComfyUI
41
  def send_workflow_to_comfyui(workflow, url):
42
  headers = {"Content-Type": "application/json"}
43
  try:
44
  response = requests.post(url, headers=headers, json={"prompt": workflow})
45
  response.raise_for_status()
46
  logging.info(f"Workflow sent successfully: {response.status_code}")
 
47
  except requests.exceptions.RequestException as e:
48
  logging.error(f"Error sending workflow to ComfyUI: {e}")
49
  raise
50
 
51
- # Monitor the output directory for new images
52
  def monitor_output_images(output_dir, previous_images, timeout=60):
53
  start_time = time.time()
54
  logging.info(f"Monitoring {output_dir} for new images...")
@@ -60,78 +60,117 @@ def monitor_output_images(output_dir, previous_images, timeout=60):
60
  logging.info(f"New image found: {latest_image}")
61
  return latest_image
62
  time.sleep(1)
63
- raise TimeoutError("Timed out waiting for new image.")
 
64
 
65
- # Move the file with retries if the file is in use
66
- def move_file_with_retry(src, dst_dir, retries=5, delay=1):
67
- dst = os.path.join(dst_dir, os.path.basename(src))
68
  for _ in range(retries):
69
  try:
70
- if os.path.exists(dst):
71
- base, ext = os.path.splitext(dst)
72
- dst = f"{base}_{random.randint(1000, 9999)}{ext}"
73
- shutil.move(src, dst)
74
  return dst
75
  except PermissionError:
76
  time.sleep(delay)
77
- raise PermissionError(f"Failed to move {src} to {dst} after {retries} retries")
78
 
79
- # Zip files at specified intervals
80
  def zip_files(output_images: List[str], zip_interval: int, zip_folder: str):
81
  zip_files = []
82
  for i in range(0, len(output_images), zip_interval):
83
- zip_filename = os.path.join(zip_folder, f"images_{i//zip_interval + 1}.zip")
84
  with zipfile.ZipFile(zip_filename, 'w') as zipf:
85
  for img in output_images[i:i+zip_interval]:
86
  zipf.write(img, os.path.basename(img))
87
  zip_files.append(zip_filename)
88
  return zip_files
89
 
90
- # Process the prompts
91
- def process_prompts(prompts_text, user_folder, zip_interval):
92
- prompts = prompts_text.strip().split('\n')
 
93
  output_images = []
 
 
94
 
95
  workflow = read_workflow(WORKFLOW_PATH)
96
 
97
  total_prompts = len(prompts)
98
  previous_images = os.listdir(OUTPUT_DIR)
99
- zip_files_list = []
 
100
 
101
  try:
102
  for i, prompt in enumerate(prompts):
 
 
 
103
  if not prompt.strip():
104
  continue
105
 
106
- updated_workflow = update_workflow(workflow, prompt)
 
 
107
  write_workflow(updated_workflow, WORKFLOW_PATH)
108
 
 
 
109
  send_workflow_to_comfyui(updated_workflow, URL)
110
- logging.info(f"Sent workflow to ComfyUI for prompt {i+1}/{total_prompts}")
111
 
112
- try:
 
 
113
  new_image = monitor_output_images(OUTPUT_DIR, previous_images)
114
- new_image_path = os.path.join(OUTPUT_DIR, new_image)
115
- moved_image_path = move_file_with_retry(new_image_path, user_folder)
116
- logging.info(f"New image generated and moved to user folder: {moved_image_path}")
117
- except TimeoutError as e:
118
- logging.error(f"Error monitoring output images: {e}")
 
 
 
 
 
 
 
 
 
 
 
 
119
  continue
120
 
121
- output_images.append(moved_image_path)
122
- time.sleep(2) # Wait for 2 seconds before updating the image
123
- yield moved_image_path, f"Processed {i + 1}/{total_prompts} - Done: {i + 1}, Left: {total_prompts - (i + 1)}"
 
 
 
 
 
 
124
 
125
- # Zip files at the specified interval
126
- zip_folder = os.path.join(user_folder, "zipped_images")
127
- os.makedirs(zip_folder, exist_ok=True)
128
- zip_files_list = zip_files(output_images, zip_interval, zip_folder)
 
 
 
 
129
 
130
  except KeyboardInterrupt:
131
  logging.info("Script interrupted by user.")
132
 
133
  return output_images, zip_files_list
134
 
 
 
 
 
 
 
 
 
135
  def main():
136
  with gr.Blocks(css="""
137
  .gradio-container {font-family: Arial, sans-serif;}
@@ -151,46 +190,84 @@ def main():
151
  90% { color: #da70d6; }
152
  100% { color: #ff69b4; }
153
  }
 
 
 
 
154
  """) as demo:
155
- gr.Markdown("""
156
- <h1 class="psychedelic-text">
157
- <span>G</span><span>r</span><span>o</span><span>o</span><span>v</span><span>y</span>-
158
- <span>S</span><span>t</span><span>y</span><span>l</span><span>S</span><span>u</span><span>i</span><span>t</span>;
159
- </h1>
160
- """)
161
-
162
- gr.Markdown("ComfyUI Workflow Automation\nWelcome to the Groovy ComfyUI Workflow Automation tool. Enter your prompts below, one per line, and the tool will process each prompt sequentially.")
163
-
164
  with gr.Row():
165
  with gr.Column(scale=1):
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
166
  gr.Markdown("### Enter Prompts")
167
- prompts_text = gr.Textbox(lines=20, placeholder="Enter your prompts here, one per line.")
 
168
  zip_interval = gr.Number(value=10, label="Zip Interval", precision=0)
169
  process_btn = gr.Button("Process Prompts")
 
170
  progress_text = gr.Markdown("Progress")
171
- output_image = gr.Image(label="Generated Image")
172
- zip_file_list = gr.File(label="Zipped Files")
 
 
 
 
173
 
174
  def generate_user_folder():
175
- user_folder = os.path.normpath(os.path.join(OUTPUT_DIR, f'SD3{random.randint(100, 999)}'))
176
  os.makedirs(user_folder, exist_ok=True)
177
  logging.info(f"Generated user folder: {user_folder}")
178
  return user_folder
179
 
180
- def on_click(prompts_text, zip_interval):
 
181
  user_folder = generate_user_folder()
182
  output_images, zip_files_list = [], []
183
- for image_path, progress_msg in process_prompts(prompts_text, user_folder, zip_interval):
184
- output_images.append(image_path)
185
- zip_files_list = zip_files(output_images, zip_interval, user_folder)
186
- yield image_path, zip_files_list, progress_msg
187
- latest_image = output_images[-1] if output_images else None
188
- return latest_image, zip_files_list
 
189
 
190
  process_btn.click(
191
  fn=on_click,
192
- inputs=[prompts_text, zip_interval],
193
- outputs=[output_image, zip_file_list, progress_text]
 
 
 
 
 
 
194
  )
195
 
196
  demo.launch(share=True)
 
11
 
12
  # Define constants
13
  COMFYUI_DIR = r"C:\Users\bewiz\OneDrive\Desktop\AI\ComfyUI_windows_portable\ComfyUI"
14
+ WORKFLOW_PATH = os.path.join(COMFYUI_DIR, 'sd3.json')
15
  OUTPUT_DIR = os.path.join(COMFYUI_DIR, 'output')
16
  URL = "http://127.0.0.1:8188/prompt"
17
 
18
  # Configure logging
19
  logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
20
 
21
+ # Shared state for cancellation
22
+ cancel_processing = False
23
+
24
  def read_workflow(file_path):
25
  logging.info(f"Reading workflow from {file_path}")
26
  with open(file_path, 'r') as file:
27
  workflow = json.load(file)
28
  return workflow
29
 
30
+ def update_workflow(workflow, prompt, negative_prompt):
31
+ logging.info(f"Updating workflow with new prompts: {prompt}, negative: {negative_prompt}")
32
+ workflow["6"]["inputs"]["text"] = prompt
33
+ workflow["71"]["inputs"]["text"] = negative_prompt
34
  return workflow
35
 
 
36
  def write_workflow(workflow, file_path):
37
  logging.info(f"Writing updated workflow to {file_path}")
38
  with open(file_path, 'w') as file:
39
  json.dump(workflow, file, indent=4)
40
 
 
41
  def send_workflow_to_comfyui(workflow, url):
42
  headers = {"Content-Type": "application/json"}
43
  try:
44
  response = requests.post(url, headers=headers, json={"prompt": workflow})
45
  response.raise_for_status()
46
  logging.info(f"Workflow sent successfully: {response.status_code}")
47
+ logging.debug(f"Response content: {response.content}")
48
  except requests.exceptions.RequestException as e:
49
  logging.error(f"Error sending workflow to ComfyUI: {e}")
50
  raise
51
 
 
52
  def monitor_output_images(output_dir, previous_images, timeout=60):
53
  start_time = time.time()
54
  logging.info(f"Monitoring {output_dir} for new images...")
 
60
  logging.info(f"New image found: {latest_image}")
61
  return latest_image
62
  time.sleep(1)
63
+ logging.info(f"Timeout while waiting for new images in {output_dir}")
64
+ return None
65
 
66
+ def copy_file_with_retry(src, dst_dir, file_index, retries=5, delay=1):
67
+ dst = os.path.join(dst_dir, f"SD3_{file_index:05d}.png")
 
68
  for _ in range(retries):
69
  try:
70
+ shutil.copy(src, dst)
 
 
 
71
  return dst
72
  except PermissionError:
73
  time.sleep(delay)
74
+ raise PermissionError(f"Failed to copy {src} to {dst} after {retries} retries")
75
 
 
76
  def zip_files(output_images: List[str], zip_interval: int, zip_folder: str):
77
  zip_files = []
78
  for i in range(0, len(output_images), zip_interval):
79
+ zip_filename = os.path.join(zip_folder, f"images_{i//zip_interval + 1}_{time.time_ns()}.zip")
80
  with zipfile.ZipFile(zip_filename, 'w') as zipf:
81
  for img in output_images[i:i+zip_interval]:
82
  zipf.write(img, os.path.basename(img))
83
  zip_files.append(zip_filename)
84
  return zip_files
85
 
86
+ def process_prompts(prompts_text, negative_prompt_text, user_folder, zip_interval):
87
+ global cancel_processing
88
+ prompts = [line.strip() for line in prompts_text.split('\n\n') if line.strip()]
89
+ negative_prompts = [line.strip() for line in negative_prompt_text.split('\n') if line.strip()]
90
  output_images = []
91
+ zip_files_list = []
92
+ file_index = 1
93
 
94
  workflow = read_workflow(WORKFLOW_PATH)
95
 
96
  total_prompts = len(prompts)
97
  previous_images = os.listdir(OUTPUT_DIR)
98
+
99
+ logs = ""
100
 
101
  try:
102
  for i, prompt in enumerate(prompts):
103
+ if cancel_processing:
104
+ logging.info("Processing cancelled by user.")
105
+ break
106
  if not prompt.strip():
107
  continue
108
 
109
+ negative_prompt = negative_prompts[i] if i < len(negative_prompts) else ""
110
+
111
+ updated_workflow = update_workflow(workflow, prompt, negative_prompt)
112
  write_workflow(updated_workflow, WORKFLOW_PATH)
113
 
114
+ logging.debug(f"Updated workflow: {json.dumps(updated_workflow, indent=4)}")
115
+
116
  send_workflow_to_comfyui(updated_workflow, URL)
117
+ logging.info(f"Sent workflow to ComfyUI for prompt {i + 1}/{total_prompts}")
118
 
119
+ new_image = None
120
+ retries = 0
121
+ while new_image is None and retries < 5:
122
  new_image = monitor_output_images(OUTPUT_DIR, previous_images)
123
+ if new_image is None:
124
+ retries += 1
125
+ logging.warning(f"Retrying ({retries}/5)...")
126
+ time.sleep(5)
127
+ else:
128
+ time.sleep(2)
129
+
130
+ if new_image is None:
131
+ logging.error("Error monitoring output images: Timed out waiting for new image.")
132
+ continue
133
+
134
+ new_image_path = os.path.join(OUTPUT_DIR, new_image)
135
+ try:
136
+ copied_image_path = copy_file_with_retry(new_image_path, user_folder, file_index)
137
+ logging.info(f"New image generated and copied to user folder: {copied_image_path}")
138
+ except PermissionError as e:
139
+ logging.error(f"Failed to copy file after retries: {e}")
140
  continue
141
 
142
+ output_images.append(copied_image_path)
143
+ previous_images.append(new_image)
144
+ file_index += 1
145
+
146
+ if len(output_images) % zip_interval == 0 and not cancel_processing:
147
+ zip_folder = os.path.join(user_folder, "zipped_images")
148
+ os.makedirs(zip_folder, exist_ok=True)
149
+ new_zip_files = zip_files(output_images[-zip_interval:], zip_interval, zip_folder)
150
+ zip_files_list.extend(new_zip_files)
151
 
152
+ logs += f"Processed {i + 1}/{total_prompts} - Done: {i + 1}, Left: {total_prompts - (i + 1)}\n"
153
+ yield output_images, zip_files_list, logs
154
+
155
+ if cancel_processing or (len(output_images) % zip_interval != 0):
156
+ zip_folder = os.path.join(user_folder, "zipped_images")
157
+ os.makedirs(zip_folder, exist_ok=True)
158
+ new_zip_files = zip_files(output_images, zip_interval, zip_folder)
159
+ zip_files_list.extend(new_zip_files)
160
 
161
  except KeyboardInterrupt:
162
  logging.info("Script interrupted by user.")
163
 
164
  return output_images, zip_files_list
165
 
166
+ def cancel_processing_fn():
167
+ global cancel_processing
168
+ cancel_processing = True
169
+
170
+ def reset_cancel_processing_fn():
171
+ global cancel_processing
172
+ cancel_processing = False
173
+
174
  def main():
175
  with gr.Blocks(css="""
176
  .gradio-container {font-family: Arial, sans-serif;}
 
190
  90% { color: #da70d6; }
191
  100% { color: #ff69b4; }
192
  }
193
+ .image-container img {
194
+ width: 250px;
195
+ height: 250px;
196
+ }
197
  """) as demo:
 
 
 
 
 
 
 
 
 
198
  with gr.Row():
199
  with gr.Column(scale=1):
200
+ gr.Markdown("### beWiZ's GroOvy SD3 Batch Imagine")
201
+ gr.HTML('<div class="image-container"><img src="https://raw.githubusercontent.com/downlifted/Groovy-StyleSuite/main/groovy.png" alt="GroOvy - SD3 Batch Imagine Logo"></div>')
202
+ with gr.Accordion("Developer Information", open=False):
203
+ gr.Markdown("### Made by BeWiZ")
204
+ gr.Markdown('<div class="image-container"><a href="https://twitter.com/AiAnarchist"><img src="https://raw.githubusercontent.com/downlifted/pictoprompt/master/aia.png" alt="BeWiZ Logo"></a></div>')
205
+ gr.Markdown("Contact: [downlifted@gmail.com](mailto:downlifted@gmail.com)")
206
+ gr.Markdown("Twitter: [@AiAnarchist](https://x.com/AiAnarchist)")
207
+ with gr.Accordion("About SD3 Batch Imagine", open=False):
208
+ gr.Markdown("""
209
+ ### SD3 Batch Imagine: Batch Image Generation
210
+ Produce large batches of images using the latest SD3 Medium model. This tool allows you to generate images quickly and efficiently.
211
+ - **ComfyUI**: For seamless integration and image processing.
212
+ - **Hugging Face**: For state-of-the-art language models.
213
+ - **Gradio**: For an intuitive user interface.
214
+ """)
215
+
216
+ with gr.Accordion("Instructions", open=True):
217
+ gr.Markdown("""
218
+ **SD3 Batch Imagine Instructions**
219
+ - Enter your prompts below, one per empty line.
220
+ - Enter your negative prompts below, one per line. (Optional)
221
+ - Set the zip interval to determine how many images will be included in each zip file.
222
+ - Click "Process Prompts" to start generating images.
223
+ - Click "Cancel Processing" to stop the current batch run.
224
+ - Watch the progress as images are generated in real-time.
225
+ - At the end of the process, zip files containing your images will be available for download.
226
+ """)
227
+
228
+ with gr.Column(scale=2):
229
  gr.Markdown("### Enter Prompts")
230
+ prompts_text = gr.Textbox(lines=20, placeholder="Enter your prompts here, one per empty line.", label="Prompts")
231
+ negative_prompts_text = gr.Textbox(lines=5, placeholder="Enter your negative prompts here, one per line.", label="Negative Prompts")
232
  zip_interval = gr.Number(value=10, label="Zip Interval", precision=0)
233
  process_btn = gr.Button("Process Prompts")
234
+ cancel_btn = gr.Button("Cancel Processing")
235
  progress_text = gr.Markdown("Progress")
236
+ gallery_output = gr.Gallery(label="Generated Images")
237
+ zip_files_output = gr.Files(label="Zip Files")
238
+
239
+ with gr.Column(scale=1):
240
+ gr.Markdown("### Detailed Logs")
241
+ logs_output = gr.Textbox(lines=10, interactive=False, label="Logs")
242
 
243
  def generate_user_folder():
244
+ user_folder = os.path.normpath(os.path.join(OUTPUT_DIR, f'SD3{random.randint(1000, 9999)}'))
245
  os.makedirs(user_folder, exist_ok=True)
246
  logging.info(f"Generated user folder: {user_folder}")
247
  return user_folder
248
 
249
+ def on_click(prompts_text, negative_prompts_text, zip_interval):
250
+ reset_cancel_processing_fn()
251
  user_folder = generate_user_folder()
252
  output_images, zip_files_list = [], []
253
+ logs = ""
254
+ for images, zip_files, log_msg in process_prompts(prompts_text, negative_prompts_text, user_folder, zip_interval):
255
+ output_images = images
256
+ zip_files_list = zip_files
257
+ logs = log_msg
258
+ yield images, zip_files_list, logs
259
+ return output_images, zip_files_list, logs
260
 
261
  process_btn.click(
262
  fn=on_click,
263
+ inputs=[prompts_text, negative_prompts_text, zip_interval],
264
+ outputs=[gallery_output, zip_files_output, logs_output]
265
+ )
266
+
267
+ cancel_btn.click(
268
+ fn=cancel_processing_fn,
269
+ inputs=[],
270
+ outputs=[]
271
  )
272
 
273
  demo.launch(share=True)