File size: 3,543 Bytes
1030ba2
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
# ui/metadata.py
import json
import gradio as gr
from PIL import Image
from PIL.PngImagePlugin import PngInfo

# Import shared state for access to parameter key lists
from . import shared_state

# --- Core Metadata Functions ---

def extract_metadata_from_pil_image(pil_image: Image.Image) -> dict:
    """Extracts a 'parameters' dictionary from a PIL image's text chunk."""
    if pil_image is None: 
        return {}
    
    pnginfo_data = getattr(pil_image, 'text', None)
    if not isinstance(pnginfo_data, dict):
        return {}
    
    params_json_str = pnginfo_data.get('parameters')
    if not params_json_str:
        return {}
    
    try:
        extracted_params = json.loads(params_json_str)
        return extracted_params if isinstance(extracted_params, dict) else {}
    except json.JSONDecodeError as e:
        print(f"Error decoding metadata JSON: {e}")
        return {}

def write_image_metadata(pil_image: Image.Image, params_dict: dict) -> Image.Image:
    """Creates a PngInfo object with the given parameters and attaches it to the image."""
    metadata = PngInfo()
    metadata.add_text("parameters", json.dumps(params_dict))
    pil_image.info = metadata # The .info attribute is the correct place to assign the PngInfo object
    return pil_image

# --- UI Handler Functions (Moved from demo_gradio_svc.py) ---

def handle_image_upload_for_metadata(gallery_pil_list):
    """

    Checks an uploaded image for metadata and shows a confirmation modal if found.

    This function is triggered by the 'upload' event of the image gallery.

    """
    if not gallery_pil_list:
        return gr.update(visible=False)
    
    # The gallery component returns a list of (image, name) tuples.
    pil_image = gallery_pil_list[0][0] if isinstance(gallery_pil_list[0], tuple) else gallery_pil_list[0]
    
    if isinstance(pil_image, Image.Image):
        extracted_metadata = extract_metadata_from_pil_image(pil_image)
        # Show the modal only if metadata exists and contains relevant keys.
        if extracted_metadata and any(key in extracted_metadata for key in shared_state.CREATIVE_PARAM_KEYS):
            return gr.update(visible=True)
            
    return gr.update(visible=False)

def ui_load_params_from_image_metadata(gallery_data_list):
    """

    Loads ONLY the creative parameters from image metadata and returns UI updates.

    """
    updates = [gr.update()] * len(shared_state.CREATIVE_PARAM_KEYS)
    if not gallery_data_list:
        return updates
        
    pil_image = gallery_data_list[0][0] if isinstance(gallery_data_list[0], tuple) else gallery_data_list[0]
    extracted_metadata = extract_metadata_from_pil_image(pil_image)
    
    if not extracted_metadata:
        gr.Info("No parameters found in image.")
        return updates
        
    gr.Info(f"Applying creative settings from image...")
    for i, key in enumerate(shared_state.CREATIVE_PARAM_KEYS):
        if key in extracted_metadata:
            # Return a Gradio update object for each changed parameter.
            updates[i] = gr.update(value=extracted_metadata[key])
            
    return updates

def apply_and_hide_modal(gallery_data_list):
    """

    A wrapper function that applies the metadata and then hides the confirmation modal.

    """
    # The first output hides the modal, the rest are the parameter updates.
    return [gr.update(visible=False)] + ui_load_params_from_image_metadata(gallery_data_list)