| from pathlib import Path
|
| from PIL import Image
|
| from PIL.PngImagePlugin import PngImageFile, PngInfo
|
| import json
|
| from pprint import pprint
|
| import argparse
|
| from rich.console import Console
|
| from rich.progress import Progress
|
| from rich_argparse import RichHelpFormatter
|
|
|
|
|
| def parse_a111(params, verbose=False):
|
|
|
| params = params.split("\n")
|
|
|
| prompt = params[0].strip()
|
| neg = params[1].split(":")[1].strip()
|
|
|
| settings = {}
|
| try:
|
| settings = {
|
| s.split(":")[0].strip(): s.split(":")[1].strip()
|
| for s in params[2].split(",")
|
| }
|
|
|
| except IndexError:
|
| settings = {"raw": params[2].strip()}
|
|
|
| if verbose:
|
| print(f"PROMPT: {prompt}")
|
| print(f"NEG: {neg}")
|
| print("SETTINGS:")
|
| pprint(settings, indent=4)
|
|
|
| return {"prompt": prompt, "negative": neg, "settings": settings}
|
|
|
|
|
| import glob
|
|
|
| if __name__ == "__main__":
|
| parser = argparse.ArgumentParser(
|
| description="Crude metadata extractor from A111 pngs",
|
| formatter_class=RichHelpFormatter
|
| )
|
| parser.add_argument("inputs", nargs="*", help="Input image files")
|
| parser.add_argument("--output", help="Output JSON file")
|
| parser.add_argument("-v", "--verbose", action="store_true", help="Verbose mode")
|
| parser.add_argument(
|
| "--glob", help="Enable glob pattern matching", metavar="PATTERN"
|
| )
|
|
|
| args = parser.parse_args()
|
|
|
|
|
| if not args.glob and not args.inputs:
|
| parser.error("Either --glob flag or inputs must be provided.")
|
| if args.glob:
|
| glob_pattern = args.glob
|
| try:
|
| pattern_path = str(Path(glob_pattern).expanduser().resolve())
|
|
|
| if not any(glob.glob(pattern_path)):
|
| raise ValueError(f"No files found for glob pattern: {glob_pattern}")
|
| except Exception as e:
|
| console = Console()
|
| console.print(
|
| f"[bold red]Error: Invalid glob pattern '{glob_pattern}': {e}[/bold red]"
|
| )
|
|
|
| exit(1)
|
| else:
|
| glob_pattern = None
|
|
|
| input_files = []
|
|
|
| if glob_pattern:
|
| input_files = list(glob.glob(str(Path(glob_pattern).expanduser().resolve())))
|
| else:
|
| input_files = [Path(p) for p in args.inputs]
|
|
|
| console = Console()
|
| console.print("Input Files:", style="bold", end=" ")
|
| console.print(f"{len(input_files):03d} files", style="cyan")
|
|
|
|
|
| console.print("\nOutput File:", style="bold", end=" ")
|
| console.print(f"{Path(args.output).resolve().absolute()}", style="cyan")
|
|
|
| with Progress(console=console, auto_refresh=True) as progress:
|
|
|
| unique_info = {}
|
| last = None
|
|
|
| task = progress.add_task("[cyan]Extracting meta...", total=len(input_files) + 1)
|
| for p in input_files:
|
| im = Image.open(p)
|
| parsed = parse_a111(im.info["parameters"], args.verbose)
|
|
|
| if parsed != last:
|
| unique_info[Path(p).stem] = parsed
|
|
|
| last = parsed
|
| progress.update(task, advance=1)
|
| progress.refresh()
|
|
|
| unique_info = json.dumps(unique_info, indent=4)
|
| with open(args.output, "w") as f:
|
| f.write(unique_info)
|
| progress.update(task, advance=1)
|
| progress.refresh()
|
|
|
| console.print("\nProcessing completed!", style="bold green")
|
|
|