File size: 7,769 Bytes
564378d 6364f3e 564378d 6364f3e 564378d 6364f3e 564378d 6364f3e 564378d 31fe7cc 564378d 6364f3e 564378d 6364f3e 564378d 6364f3e 564378d 6364f3e 31fe7cc 6364f3e 31fe7cc 6364f3e 31fe7cc 6364f3e 31fe7cc 6364f3e 31fe7cc 6364f3e 9bbea50 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 |
import gradio as gr
from PIL import Image
from PIL.ExifTags import TAGS
import numpy as np
import re
import json
import tempfile
import os
def get_image_metadata(img):
"""Extract metadata based on image format."""
metadata = {}
if img.format == 'PNG':
metadata = img.info
elif img.format in ['JPEG', 'TIFF']:
exif_data = img._getexif()
if exif_data:
for tag, value in exif_data.items():
tag_name = TAGS.get(tag, tag)
metadata[tag_name] = value
return metadata
def parse_parameters(parameters):
"""Parse the 'parameters' field to extract prompts and seed number."""
prompt = 'N/A'
negative_prompt = 'N/A'
adetailer_prompt_1 = 'N/A'
adetailer_prompt_2 = 'N/A'
seed_number = -1
# Extract the prompt
prompt_match = re.search(r'(.*?)Negative prompt:', parameters, re.DOTALL | re.IGNORECASE)
if prompt_match:
prompt = prompt_match.group(1).strip()
else:
prompt_match = re.search(r'(.*?)(Steps:|$)', parameters, re.DOTALL | re.IGNORECASE)
if prompt_match:
prompt = prompt_match.group(1).strip()
# Extract the negative prompt
negative_prompt_match = re.search(r'Negative prompt:(.*?)(Steps:|$)', parameters, re.DOTALL | re.IGNORECASE)
if negative_prompt_match:
negative_prompt = negative_prompt_match.group(1).strip()
# Extract ADetailer prompts
adetailer_prompt_1_match = re.search(r'ADetailer prompt:\s*"(.*?)"', parameters, re.IGNORECASE)
if adetailer_prompt_1_match:
adetailer_prompt_1 = adetailer_prompt_1_match.group(1).strip()
adetailer_prompt_2_match = re.search(r'ADetailer negative prompt 2nd:\s*"(.*?)"', parameters, re.IGNORECASE)
if adetailer_prompt_2_match:
adetailer_prompt_2 = adetailer_prompt_2_match.group(1).strip()
# Extract Seed Number
seed_match = re.search(r'Seed:\s*(\d+)', parameters, re.IGNORECASE)
if seed_match:
seed_number = seed_match.group(1).strip()
return prompt, negative_prompt, adetailer_prompt_1, adetailer_prompt_2, seed_number
def extract_metadata(image_file):
"""Extract and parse metadata from the uploaded image."""
try:
img = Image.open(image_file)
except Exception as e:
# Return placeholders in case of error
return (None, 'Error: Unable to open image.', *(['N/A'] * 7))
metadata = get_image_metadata(img)
img_display = np.array(img)
# Convert metadata to string
metadata_str = "\n".join([f"{key}: {value}" for key, value in metadata.items()])
# Initialize default values
prompt = negative_prompt = adetailer_prompt_1 = adetailer_prompt_2 = 'N/A'
seed_number = -1
comfy_prompt = comfy_workflow = 'N/A'
# Parse parameters if available
if 'parameters' in metadata:
parsed = parse_parameters(metadata['parameters'])
prompt, negative_prompt, adetailer_prompt_1, adetailer_prompt_2, seed_number = parsed
# Direct extraction with validation for Comfy Prompt
if 'prompt' in metadata and isinstance(metadata['prompt'], str):
comfy_prompt = metadata['prompt'].strip()
else:
comfy_prompt = 'N/A' # Fallback if prompt is missing or not a string
# Direct extraction with validation for Comfy Workflow
if 'workflow' in metadata and isinstance(metadata['workflow'], str):
comfy_workflow = metadata['workflow'].strip()
else:
comfy_workflow = 'N/A' # Fallback if workflow is missing or not a string
return (
img_display,
prompt,
negative_prompt,
seed_number,
adetailer_prompt_1,
adetailer_prompt_2,
metadata_str,
comfy_prompt,
comfy_workflow
)
def export_workflow(workflow_text):
"""
Converts the workflow text into JSON format and returns it as a downloadable file.
"""
print("Export workflow function called.")
if workflow_text == "N/A" or not workflow_text.strip():
print("No workflow data to export.")
return None, "No workflow data to export."
# Structure the JSON data
workflow_data = {
"comfy_workflow": workflow_text
}
# Create a temporary JSON file
try:
with tempfile.NamedTemporaryFile(mode='w', delete=False, suffix='.json') as tmp_file:
json.dump(workflow_data, tmp_file, indent=4)
tmp_file_path = tmp_file.name
print(f"Temporary JSON file created at: {tmp_file_path}")
except Exception as e:
print(f"Error creating temporary file: {e}")
return None, "Failed to create workflow JSON file."
# Check if the file was created successfully
if os.path.exists(tmp_file_path):
message = "Workflow exported successfully."
print(message)
return tmp_file_path, message
else:
message = "Failed to export workflow."
print(message)
return None, message
def main():
# Create Gradio User Interface
with gr.Blocks() as iface:
gr.Markdown("<h1>Automatic 1111/ Comfy Metadata Reader</h1>")
gr.Markdown("<p>Upload an image (PNG, JPEG) to extract its metadata and parse it for prompts.</p>")
with gr.Row():
with gr.Column(): # First column for image upload and preview
image_input = gr.File(label="Upload Image", type="filepath")
image_output = gr.Image(label="Image Preview")
original_metadata_output = gr.Textbox(label="Original Metadata", lines=20, interactive=False)
with gr.Column(): # Second column for metadata outputs
prompt_output = gr.Textbox(label="Prompt", lines=4, show_copy_button=True, interactive=False)
negative_prompt_output = gr.Textbox(label="Negative Prompt", lines=4, show_copy_button=True, interactive=False)
seed_output = gr.Textbox(label="Seed Number", lines=1, show_copy_button=True, interactive=False)
adetailer_prompt_1_output = gr.Textbox(label="ADetailer Prompt 1", lines=3, show_copy_button=True, interactive=False)
adetailer_prompt_2_output = gr.Textbox(label="ADetailer Prompt 2", lines=3, show_copy_button=True, interactive=False)
with gr.Column(): # Third column for additional metadata outputs
with gr.Row():
comfy_prompt_output = gr.Textbox(label="Comfy Prompt", lines=4, value="N/A", interactive=False)
with gr.Row():
comfy_workflow_output = gr.Textbox(label="Comfy Workflow", lines=20, value="N/A", interactive=False)
export_button = gr.Button("Export Workflow as JSON")
workflow_file = gr.File(label="Download Workflow JSON", visible=False)
with gr.Row():
export_message = gr.Textbox(label="Export Status", lines=1, interactive=False, visible=False)
# Set up the input-output relationships
image_input.change(
fn=extract_metadata,
inputs=image_input,
outputs=[
image_output,
prompt_output,
negative_prompt_output,
seed_output,
adetailer_prompt_1_output,
adetailer_prompt_2_output,
original_metadata_output,
comfy_prompt_output,
comfy_workflow_output,
]
)
# Connect the export button to the export function
export_button.click(
fn=export_workflow,
inputs=comfy_workflow_output,
outputs=[workflow_file, export_message],
queue=False
)
iface.launch()
if __name__ == "__main__":
main() |