---
name: image_save_png
kind: function
lang: py
domain: ml
version: "1.0.0"
purity: impure
signature: "def image_save_png(img: PIL.Image.Image, path: str, metadata: dict | None = None) -> str"
description: "Guarda una PIL Image como PNG con metadata embebida en chunks tEXt (prompt, seed, steps, sampler, model). Crea directorio padre si no existe. Retorna path absoluto escrito."
tags: [image, png, pil, pillow, metadata, save, ml, reproducibility, pendiente-usar]
uses_functions: []
uses_types: []
returns: []
returns_optional: false
error_type: "error_go_core"
imports: [Pillow]
params:
  - name: img
    desc: "imagen PIL.Image.Image a guardar"
  - name: path
    desc: "ruta de destino del archivo PNG (absoluta o relativa)"
  - name: metadata
    desc: "dict opcional de pares clave/valor a embeber en chunks tEXt del PNG para reproducibilidad (prompt, seed, steps, etc.)"
output: "string: ruta absoluta del archivo PNG escrito"
tested: true
tests:
  - "crea imagen 8x8, guarda y retorna ruta absoluta"
  - "metadata se embebe en chunks tEXt y se puede releer con Image.text"
  - "sin metadata el PNG se guarda igualmente"
  - "crea directorio padre si no existe"
  - "valores numericos en metadata se convierten a str automaticamente"
test_file_path: "python/functions/ml/tests/test_image_save_png.py"
file_path: "python/functions/ml/image_save_png.py"
---

## Ejemplo

```python
from PIL import Image
from ml.image_save_png import image_save_png

img = Image.new("RGB", (512, 512), color=(128, 64, 200))
path = image_save_png(
    img,
    "outputs/gen_001.png",
    metadata={
        "prompt": "a cat on a purple sofa",
        "seed": 42,
        "steps": 20,
        "sampler": "euler_a",
        "model": "sd-v1-5",
    },
)
# path = "/home/lucas/.../outputs/gen_001.png"
# Los metadatos quedan embebidos en el PNG y son legibles con exiftool o PIL.
```

## Notas

- Usa `PngImagePlugin.PngInfo` para chunks `tEXt` (texto plano, no comprimido).
  Para texto largo/comprimido existe `add_itxt`, pero `add_text` es compatible
  con la mayoria de lectores (exiftool, A1111, ComfyUI, etc.).
- Los valores del dict se convierten a `str` automaticamente — se puede pasar
  int, float o bool sin castear.
- Si `metadata` es `None` o `{}`, el PNG se guarda sin chunks extra (igual que
  `img.save(path)`).
- Pillow no esta en los imports por defecto del registry para no bloquear
  `fn index`. Se importa lazy dentro de la funcion.
- impure: escribe en disco y crea directorios.
