cleanup: remove temporary debug files

This commit is contained in:
Vito Sansevero
2025-08-11 15:15:45 -07:00
parent 6fdfdea89c
commit 97cc4c175f
2 changed files with 0 additions and 466 deletions
-213
View File
@@ -1,213 +0,0 @@
#!/usr/bin/env python3
"""
Debug script to extract and analyze PNG metadata from the test image
to understand what should be displayed in the gallery views.
"""
import json
from PIL import Image
from PIL.PngImagePlugin import PngInfo
def extract_png_metadata(image_path):
"""Extract PNG metadata chunks from an image file."""
try:
with Image.open(image_path) as img:
metadata = {}
# Extract text chunks
if hasattr(img, 'text'):
for key, value in img.text.items():
metadata[key] = value
print(f"Found text chunk: {key} = {value[:100]}{'...' if len(value) > 100 else ''}")
# Try to extract PNG info
if hasattr(img, 'info'):
print(f"\nImage info keys: {list(img.info.keys())}")
for key, value in img.info.items():
if isinstance(value, str):
print(f"Info {key}: {value[:100]}{'...' if len(value) > 100 else ''}")
return metadata
except Exception as e:
print(f"Error reading PNG metadata: {e}")
return {}
def parse_comfyui_data(metadata):
"""Parse ComfyUI workflow and prompt data from PNG metadata."""
workflow_data = None
prompt_data = None
# Look for workflow data
workflow_fields = ['workflow', 'Workflow', 'comfy', 'ComfyUI']
for field in workflow_fields:
if field in metadata:
try:
workflow_data = json.loads(metadata[field])
print(f"\nFound workflow data in field '{field}'")
if isinstance(workflow_data, dict) and 'nodes' in workflow_data:
print(f"Workflow has {len(workflow_data['nodes'])} nodes")
break
except json.JSONDecodeError as e:
print(f"Failed to parse workflow field '{field}': {e}")
# Look for prompt data
prompt_fields = ['prompt', 'Prompt', 'parameters', 'Parameters']
for field in prompt_fields:
if field in metadata:
try:
# Clean up NaN values that might break JSON parsing
cleaned_json = metadata[field]
cleaned_json = cleaned_json.replace(': NaN', ': null')
cleaned_json = cleaned_json.replace(':NaN', ':null')
cleaned_json = cleaned_json.replace('NaN', 'null')
prompt_data = json.loads(cleaned_json)
print(f"\nFound prompt data in field '{field}'")
if isinstance(prompt_data, dict):
print(f"Prompt data has {len(prompt_data)} nodes")
break
except json.JSONDecodeError as e:
print(f"Failed to parse prompt field '{field}': {e}")
return workflow_data, prompt_data
def extract_generation_params(workflow_data, prompt_data):
"""Extract generation parameters from ComfyUI data."""
params = {
'checkpoint': 'Unknown',
'positive_prompt': 'No prompt found',
'negative_prompt': 'No negative prompt found',
'steps': 'Unknown',
'cfg_scale': 'Unknown',
'sampler': 'Unknown',
'seed': 'Unknown'
}
# Parse prompt data first (more reliable)
if prompt_data:
print("\nAnalyzing prompt data...")
for node_id, node in prompt_data.items():
node_type = node.get('class_type', '')
inputs = node.get('inputs', {})
print(f" Node {node_id}: {node_type}")
if inputs:
print(f" Inputs: {list(inputs.keys())}")
if node_type == 'CheckpointLoaderSimple' and 'ckpt_name' in inputs:
params['checkpoint'] = inputs['ckpt_name']
print(f" Found checkpoint: {params['checkpoint']}")
elif node_type == 'PromptManager' and 'text' in inputs:
params['positive_prompt'] = inputs['text']
print(f" Found PromptManager text: {params['positive_prompt'][:100]}...")
elif node_type == 'CLIPTextEncode' and 'text' in inputs:
text = inputs['text'].lower()
if any(neg_word in text for neg_word in ['bad anatomy', 'unfinished', 'censored', 'negative', 'embedding:']):
params['negative_prompt'] = inputs['text']
print(f" Found negative prompt: {params['negative_prompt'][:100]}...")
elif params['positive_prompt'] == 'No prompt found':
params['positive_prompt'] = inputs['text']
print(f" Found positive prompt: {params['positive_prompt'][:100]}...")
elif 'sampler' in node_type.lower() or node_type in ['KSampler', 'SamplerCustomAdvanced', 'DetailDaemonSamplerNode']:
if 'seed' in inputs:
params['seed'] = inputs['seed']
if 'steps' in inputs:
params['steps'] = inputs['steps']
if 'cfg' in inputs:
params['cfg_scale'] = inputs['cfg']
if 'sampler_name' in inputs:
params['sampler'] = inputs['sampler_name']
if 'scheduler' in inputs:
params['scheduler'] = inputs['scheduler']
print(f" Found {node_type}: seed={inputs.get('seed', 'N/A')}, steps={inputs.get('steps', 'N/A')}, cfg={inputs.get('cfg', 'N/A')}, sampler={inputs.get('sampler_name', 'N/A')}")
# Also check for BasicScheduler which might have steps
elif node_type == 'BasicScheduler' and 'steps' in inputs:
if params['steps'] == 'Unknown':
params['steps'] = inputs['steps']
print(f" Found BasicScheduler with steps: {params['steps']}")
# Check for CFG values
elif node_type == 'CFGGuider' and 'cfg' in inputs:
if params['cfg_scale'] == 'Unknown':
params['cfg_scale'] = inputs['cfg']
print(f" Found CFGGuider with cfg: {params['cfg_scale']}")
# Check for seed in various nodes
elif 'seed' in inputs:
if params['seed'] == 'Unknown':
params['seed'] = inputs['seed']
print(f" Found {node_type} with seed: {params['seed']}")
elif 'noise_seed' in inputs:
if params['seed'] == 'Unknown':
params['seed'] = inputs['noise_seed']
print(f" Found {node_type} with noise_seed: {params['seed']}")
# Check for noise/seed generators
elif node_type in ['RandomNoise', 'EmptyLatentImage'] and 'seed' in inputs:
if params['seed'] == 'Unknown':
params['seed'] = inputs['seed']
print(f" Found {node_type} with seed: {params['seed']}")
# Fallback to workflow data if needed
if workflow_data and workflow_data.get('nodes'):
print("\nAnalyzing workflow data...")
for node in workflow_data['nodes']:
node_type = node.get('type', '')
widgets = node.get('widgets_values', [])
if node_type == 'CheckpointLoaderSimple' and widgets:
if params['checkpoint'] == 'Unknown':
params['checkpoint'] = widgets[0]
print(f" Found checkpoint in workflow: {params['checkpoint']}")
elif node_type == 'PromptManager' and widgets:
if params['positive_prompt'] == 'No prompt found':
params['positive_prompt'] = widgets[0]
print(f" Found PromptManager in workflow: {params['positive_prompt'][:100]}...")
elif node_type == 'KSampler' and len(widgets) >= 4:
if params['seed'] == 'Unknown':
params['seed'] = widgets[0]
params['steps'] = widgets[1]
params['cfg_scale'] = widgets[2]
params['sampler'] = widgets[3]
print(f" Found KSampler in workflow: seed={params['seed']}, steps={params['steps']}")
return params
def main():
print("=== PNG Metadata Debug Tool ===\n")
image_path = "test_metadata_file.png"
print(f"Analyzing: {image_path}")
# Extract raw metadata
metadata = extract_png_metadata(image_path)
print(f"\nFound {len(metadata)} metadata fields:")
for key in metadata.keys():
print(f" - {key}")
# Parse ComfyUI data
workflow_data, prompt_data = parse_comfyui_data(metadata)
# Extract generation parameters
params = extract_generation_params(workflow_data, prompt_data)
print("\n=== EXTRACTED PARAMETERS ===")
for key, value in params.items():
print(f"{key}: {value}")
print("\n=== RAW METADATA FIELDS ===")
for key, value in metadata.items():
if len(value) < 200:
print(f"{key}: {value}")
else:
print(f"{key}: {value[:200]}... (truncated)")
if __name__ == "__main__":
main()
-253
View File
@@ -1,253 +0,0 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Metadata Parsing Test</title>
<style>
body { font-family: Arial, sans-serif; margin: 20px; background: #1a1a1a; color: #fff; }
.result { background: #2a2a2a; padding: 20px; margin: 10px 0; border-radius: 8px; }
.error { background: #3a1a1a; border: 1px solid #ff6b6b; }
.success { background: #1a3a1a; border: 1px solid #6bcf7f; }
input[type="file"] { margin: 20px 0; padding: 10px; background: #3a3a3a; color: #fff; border: none; border-radius: 4px; }
pre { white-space: pre-wrap; word-wrap: break-word; }
</style>
</head>
<body>
<h1>PNG Metadata Parsing Test</h1>
<p>Select the test_metadata_file.png to verify metadata extraction works correctly.</p>
<input type="file" id="fileInput" accept=".png" />
<div id="results"></div>
<script>
// Copy the updated parsing functions from metadata.html
async function parsePNGMetadata(arrayBuffer) {
const dataView = new DataView(arrayBuffer);
let offset = 8; // Skip PNG signature
const metadata = {};
while (offset < arrayBuffer.byteLength - 8) {
const length = dataView.getUint32(offset);
const type = new TextDecoder().decode(arrayBuffer.slice(offset + 4, offset + 8));
if (type === 'tEXt' || type === 'iTXt' || type === 'zTXt') {
const chunkData = arrayBuffer.slice(offset + 8, offset + 8 + length);
let text;
if (type === 'tEXt') {
text = new TextDecoder().decode(chunkData);
} else if (type === 'iTXt') {
const textData = new TextDecoder().decode(chunkData);
const parts = textData.split('\0');
if (parts.length >= 5) {
metadata[parts[0]] = parts[4];
}
text = textData;
} else if (type === 'zTXt') {
text = new TextDecoder().decode(chunkData);
}
const nullIndex = text.indexOf('\0');
if (nullIndex !== -1) {
const key = text.substring(0, nullIndex);
const value = text.substring(nullIndex + 1);
metadata[key] = value;
}
}
offset += 8 + length + 4;
}
return metadata;
}
function extractComfyUIData(metadata) {
let workflowData = null;
let promptData = null;
const workflowFields = ['workflow', 'Workflow', 'comfy', 'ComfyUI'];
const promptFields = ['prompt', 'Prompt', 'parameters', 'Parameters'];
for (const field of workflowFields) {
if (metadata[field]) {
try {
let cleanedJson = metadata[field];
cleanedJson = cleanedJson.replace(/:\s*NaN\b/g, ': null');
cleanedJson = cleanedJson.replace(/\bNaN\b/g, 'null');
workflowData = JSON.parse(cleanedJson);
break;
} catch (e) {
console.log('Failed to parse workflow field:', field);
}
}
}
for (const field of promptFields) {
if (metadata[field]) {
try {
let cleanedJson = metadata[field];
cleanedJson = cleanedJson.replace(/:\s*NaN\b/g, ': null');
cleanedJson = cleanedJson.replace(/\bNaN\b/g, 'null');
promptData = JSON.parse(cleanedJson);
break;
} catch (e) {
console.log('Failed to parse prompt field:', field);
}
}
}
return { workflow: workflowData, prompt: promptData };
}
function parseWorkflowData(comfyData) {
let checkpoint = 'Unknown';
let positivePrompt = 'No prompt found';
let negativePrompt = 'No negative prompt found';
let steps = 'Unknown';
let cfgScale = 'Unknown';
let sampler = 'Unknown';
let seed = 'Unknown';
// Parse prompt data first (more reliable for actual generation parameters)
if (comfyData.prompt) {
console.log('Parsing prompt data...');
const promptNodes = comfyData.prompt;
for (const nodeId in promptNodes) {
const node = promptNodes[nodeId];
console.log(`Node ${nodeId}: ${node.class_type}`);
// Checkpoint
if (node.class_type === 'CheckpointLoaderSimple' && node.inputs) {
checkpoint = node.inputs.ckpt_name || checkpoint;
}
// Prompts
if (node.class_type === 'PromptManager' && node.inputs && node.inputs.text) {
positivePrompt = node.inputs.text;
}
if (node.class_type === 'CLIPTextEncode' && node.inputs && node.inputs.text) {
const text = node.inputs.text.toLowerCase();
if (text.includes('bad anatomy') || text.includes('unfinished') ||
text.includes('censored') || text.includes('weird anatomy') ||
text.includes('negative') || text.includes('embedding:')) {
negativePrompt = node.inputs.text;
} else if (positivePrompt === 'No prompt found') {
positivePrompt = node.inputs.text;
}
}
// Sampling parameters - check multiple sampler types
if ((node.class_type === 'KSampler' ||
node.class_type === 'KSamplerAdvanced' ||
node.class_type === 'SamplerCustom' ||
node.class_type === 'SamplerCustomAdvanced') && node.inputs) {
seed = node.inputs.seed || seed;
steps = node.inputs.steps || steps;
cfgScale = node.inputs.cfg || cfgScale;
sampler = node.inputs.sampler_name || sampler;
}
// New ComfyUI node types for modern workflows
if (node.class_type === 'CFGGuider' && node.inputs && node.inputs.cfg) {
cfgScale = node.inputs.cfg;
}
if (node.class_type === 'BasicScheduler' && node.inputs && node.inputs.steps) {
steps = node.inputs.steps;
}
if (node.class_type === 'KSamplerSelect' && node.inputs && node.inputs.sampler_name) {
sampler = node.inputs.sampler_name;
}
if ((node.class_type === 'RandomNoise' || node.class_type === 'SeedHistory') && node.inputs) {
if (node.inputs.noise_seed) {
seed = Array.isArray(node.inputs.noise_seed) ? node.inputs.noise_seed[0] : node.inputs.noise_seed;
} else if (node.inputs.seed) {
seed = node.inputs.seed;
}
}
}
}
return {
checkpoint,
positivePrompt,
negativePrompt,
steps,
cfgScale,
sampler,
seed
};
}
document.getElementById('fileInput').addEventListener('change', async (event) => {
const file = event.target.files[0];
if (!file) return;
const resultsDiv = document.getElementById('results');
resultsDiv.innerHTML = '<div class="result">Processing...</div>';
try {
const arrayBuffer = await file.arrayBuffer();
const metadata = await parsePNGMetadata(arrayBuffer);
const comfyData = extractComfyUIData(metadata);
const params = parseWorkflowData(comfyData);
const expectedParams = {
checkpoint: 'illustrious/realism/Realism_Illustrious_BSY_PATREON_FP16_V4.5_C27.safetensors',
steps: 35,
cfgScale: 4.0,
sampler: 'euler_ancestral',
positivePrompt: 'An amateur candid photo of kiko9natsumi, looking at the viewer.',
negativePrompt: 'embedding:'
};
let html = '<div class="result success"><h2>✅ Metadata Extraction Test Results</h2>';
for (const [key, value] of Object.entries(params)) {
const expected = expectedParams[key];
let status = '✅';
let statusText = 'OK';
if (expected && (key === 'negativePrompt' ? !String(value).includes(String(expected)) : value !== expected)) {
status = '❌';
statusText = `Expected: ${expected}`;
} else if (value === 'Unknown' || value === 'No prompt found') {
status = '⚠️';
statusText = 'Not found';
}
html += `
<div style="margin: 10px 0; padding: 10px; background: rgba(255,255,255,0.1); border-radius: 4px;">
<strong>${key}:</strong> ${status} ${String(value).substring(0, 100)}${String(value).length > 100 ? '...' : ''}
<br><small style="color: #aaa;">${statusText}</small>
</div>
`;
}
html += '</div>';
html += `
<div class="result">
<h3>Raw Metadata Fields Found:</h3>
<pre>${Object.keys(metadata).join(', ')}</pre>
</div>
`;
resultsDiv.innerHTML = html;
} catch (error) {
resultsDiv.innerHTML = `<div class="result error"><h2>❌ Error</h2><p>${error.message}</p></div>`;
console.error('Error processing image:', error);
}
});
</script>
</body>
</html>