"""Tratamiento B/N de Creators Latam: negro 29 (la tinta), blanco 246 (el Papel), curva en S suave, sin grano (SISTEMA §12).

Uso:  python3 foto-bn.py entrada.jpg [más.jpg ...] --out carpeta/   (sin archivos: corre la prueba)
Sirve para lotes y bocetos; la foto final de una sesión se edita en Lightroom con el ajuste «CL · B/N 01».
"""
import sys, pathlib
import numpy as np
from PIL import Image, ImageOps

MEZCLA = (0.35, 0.50, 0.15)   # R, G, B: rojos y naranjas algo más claros (piel); azules más oscuros
NEGRO, BLANCO = 0.114, 0.965  # 29/255 y 246/255: la tinta y el Papel; la foto nunca queda más oscura que el texto


def tratar(im):
    a = np.asarray(im.convert('RGB'), dtype=np.float32) / 255
    l = a @ np.array(MEZCLA, dtype=np.float32)
    lo, hi = np.percentile(l, [1, 99])
    x = np.clip((l - lo) / max(hi - lo, 1e-3), 0, 1)
    x = 0.65 * x + 0.35 * (x * x * (3 - 2 * x))           # curva en S suave
    x = NEGRO + x * (BLANCO - NEGRO)                        # sin grano: al recomprimir se vuelve ruido
    return Image.fromarray((x * 255).round().astype(np.uint8), 'L')


def _prueba():
    grad = Image.fromarray(np.ascontiguousarray(np.broadcast_to(np.arange(256, dtype=np.uint8)[None, :, None], (64, 256, 3))))
    v = np.asarray(tratar(grad), dtype=np.float32)
    assert (v.min(), v.max()) == (29, 246), f'negro y blanco deben ser 29 y 246, no {v.min():.0f} y {v.max():.0f}'
    assert (np.diff(v[0]) >= 0).all(), 'la curva no es monótona'
    assert v[:, :32].mean() < v[:, -32:].mean(), 'la curva invirtió los tonos'
    print('prueba ok')


if __name__ == '__main__':
    args = sys.argv[1:]
    if not args:
        _prueba(); sys.exit()
    out = pathlib.Path(args[args.index('--out') + 1]) if '--out' in args else pathlib.Path('.')
    out.mkdir(parents=True, exist_ok=True)
    for f in (a for i, a in enumerate(args) if a != '--out' and (i == 0 or args[i - 1] != '--out')):
        p = pathlib.Path(f)
        tratar(ImageOps.exif_transpose(Image.open(p))).save(out / f'{p.stem}-bn.jpg', quality=88)
        print(out / f'{p.stem}-bn.jpg')
