Pipeline volti
Multi-pass Vision, blur ellittico, pennello manuale e ripristino dall'originale.
Flusso automatico
- Orientamento — EXIF →
CIImage.oriented(forExifOrientation:), così Vision e il salvataggio lavorano su pixel upright. - Downscale solo per detection — lato lungo max 1920px; la sfocatura resta a piena risoluzione.
- Multi-pass Vision — sull’immagine (e su varianti preprocessate) partono:
VNDetectFaceLandmarksRequestVNDetectFaceRectanglesRequest
- Deduplica — IoU > 0.45 → stesso volto; preferenza a osservazioni con landmarks e confidence più alta.
- Regione blur — bounding box ristretto al volto (≈90% altezza + padding); se ci sono landmarks, il box segue contour e sopracciglia evitando strisce sui capelli.
- Blur —
CIGaussianBlur+ mascheraCIRadialGradientellittica blended conCIBlendWithMask.
Preprocess per il recall
Oltre all’originale, ogni pass genera una variante e la scarta subito (autoreleasepool):
| Filtro | Parametri | Perché |
|---|---|---|
CIExposureAdjust | EV +0.8 / +1.5 | volti in ombra |
CIColorControls | brightness +0.18, contrast 1.35 | scene piatte |
CIGammaAdjust | power 0.65 | controluce |
Intensità
Lo slider UI mappa 0.25…0.85 (etichette Leggera / Media / Forte). Il raggio blur è:
radius = max(8, min(w, h) * (0.04 + intensity * 0.07))
cambiando solo l’intensità, Vision non viene rieseguito: si riapplicano le faceRegions cacheate sull’originale.
Pennello manuale
BlurSpot è normalizzato (centro 0–1, raggio rispetto al lato corto). In modalità Sfocatura manuale ogni tap aggiunge uno spot e lo applica a caldo. In modalità Ripristina censura lo stesso formato di spot guida un blend dall’immagine originale verso quella corrente — stessa maschera ellittica, sorgente diversa.
Gli spot manuali sopravvivono a un cambio di intensità: dopo il re-blur automatico vengono riapplicati in ordine.
Filigrana e salvataggio
WatermarkService disegna il logo Talea (~18% del lato corto, opacità 0.45) in basso a destra solo su displayImage. Il salvataggio:
- riusa l’UTI originale (JPEG/PNG/…);
- forza orientation = 1 dopo aver raddrizzato i pixel;
- per JPEG usa qualità lossy = 1.0;
- scrive con PhotoKit
addOnly.
Memoria
Vincoli pratici adottati:
cacheIntermediates: falsesulCIContext;- una variante Vision per volta dentro
autoreleasepool; - history limitata a 10 frame;
- cache watermark invalidata quando cambia la source image.