CoreImage è un framework Apple per l’elaborazione di immagini e video in tempo reale, che fornisce decine di CIFilter integrati per correzione del colore, sfocatura, sovrapposizione di texture e rilevamento. Secondo la Documentazione Apple, CoreImage utilizza la GPU per l’elaborazione ad alte prestazioni dei pixel sui dispositivi iOS. Il framework supporta CIImage come oggetto immagine immutabile e catene di filtri per comporre effetti senza perdita di qualità.
Punti chiave
CoreImage è un framework Apple per l’elaborazione di immagini raster e video, introdotto per la prima volta in macOS 10.4 Tiger e portato su iOS 5.0. A differenza di Core Graphics o UIKit, CoreImage opera a livello di pixel shader, utilizzando la GPU per calcoli paralleli. Ciò consente di applicare effetti complessi — sfocatura, correzione del colore, morphing — a immagini con risoluzione megapixel in millisecondi.
L’architettura di CoreImage è basata sul concetto di valutazione pigra (lazy evaluation): CIFilter non esegue elaborazione fino al rendering in CIContext. Lo sviluppatore costruisce una catena di più CIFilter, collegando l’uscita di un filtro all’ingresso di un altro, e solo la chiamata render avvia la pipeline GPU completa. Ciò minimizza il numero di passaggi attraverso la scheda grafica e mantiene le prestazioni.
CoreImage supporta un’ampia gamma cromatica (P3, sRGB, sRGB lineare), immagini HDR e lavoro con formati pixel a 16 e 32 bit. Sui dispositivi con Neural Engine, CoreImage può combinare shader GPU con Core ML per l’elaborazione intelligente — ad esempio, la correzione automatica del colore basata sull’apprendimento automatico, come implementato nell’app Foto su iOS 17.
Tre classi principali formano il nucleo di CoreImage: CIImage (dati), CIFilter (operazione) e CIContext (ambiente di esecuzione). Ogni classe è responsabile della propria fase di pipeline e non mescola le responsabilità.
CIImage è un oggetto leggero che descrive un’immagine ma non contiene direttamente dati pixel. Può essere creato da UIImage, CGImage, texture Metal, texture GL o un file su disco. CIImage è immutabile — qualsiasi applicazione di filtro crea un nuovo CIImage senza modificare l’originale. Ciò consente di costruire catene di trasformazione senza copiare dati tra i passaggi.
Una caratteristica importante: CIImage non è legato alla risoluzione dello schermo o allo spazio colore fino al rendering. Lo stesso CIImage può essere renderizzato in un UIImage per lo schermo e in un file TIFF per la stampa con parametri diversi — CoreImage adatta automaticamente l’elaborazione al contesto di destinazione.
CIFilter è la classe principale per applicare effetti. Ogni CIFilter è un programma shader con parametri di input (inputImage, inputIntensity, inputRadius, ecc.) e un’immagine di output. Apple fornisce oltre 200 CIFilter integrati, raggruppati per categorie: CICategoryColorEffect (correzione del colore), CICategoryBlur (sfocatura), CICategoryStylize (stilizzazione), CICategoryGeometryAdjust (trasformazioni geometriche).
Per creare un CIFilter personalizzato, lo sviluppatore scrive uno shader Metal (CIKernel) — uno shader di frammenti in Metal Shading Language che elabora ogni pixel indipendentemente. Dopo la compilazione, lo shader viene registrato come sottoclasse di CIFilter e può essere utilizzato in catene insieme ai filtri integrati di Apple.
| Categoria | Esempio filtro | Scopo |
|---|---|---|
| ColorEffect | CIColorControls | Luminosità, contrasto, saturazione |
| Blur | CIGaussianBlur | Sfocatura gaussiana con raggio regolabile |
| Stylize | CIPixellate | Pixelizzazione con scala specificata |
| GeometryAdjust | CIAffineTransform | Rotazione, scala, traslazione tramite matrice affine |
| Composite | CISourceOverCompositing | Composizione di immagini con canale alfa |
CIContext è un oggetto pesante che gestisce l’allocazione delle risorse GPU, la compilazione degli shader e il buffering. Creare un CIContext è un’operazione costosa, quindi Apple raccomanda di crearlo una volta per l’intero ciclo di vita dell’applicazione e riutilizzarlo. Il contesto è legato a una GPU specifica (Metal, OpenGL) o alla CPU e determina lo spazio colore dell’immagine di output.
La libreria CIFilter è in continua espansione: iOS 17 ha aggiunto nuovi filtri per l’elaborazione HDR e l’apprendimento automatico. Tutti i filtri integrati sono documentati nella Documentazione per sviluppatori Apple e possono essere cercati per categorie o nomi. Per scoprire i filtri disponibili sul dispositivo, usa CIFilter.filterNames(inCategory:).
La capacità principale di CoreImage è comporre più CIFilter in una catena. L’uscita di un filtro viene alimentata all’ingresso di un altro tramite il parametro inputImage. CoreImage ottimizza la catena in fase di rendering: i filtri adiacenti che lavorano nello stesso spazio colore vengono combinati in un singolo passaggio GPU (kernel fusion). Ciò offre un guadagno in termini di prestazioni senza intervento dello sviluppatore.
Per creare un effetto personalizzato, lo sviluppatore scrive una funzione Metal con l’annotazione [[kernel]]. La funzione riceve le coordinate del pixel e restituisce un colore. CoreImage passa lo shader alla GPU, dove viene eseguito in parallelo per tutti i pixel dell’immagine. I filtri personalizzati sono particolarmente utili per effetti visivi unici: seppia con curva non lineare, sfocatura di dispersione o simulazione di grana della pellicola.
#include <CoreImage/CoreImage.h>
[[kernel]] float4 customFilter(sample_t s, float intensity) {
float4 result;
result.rgb = s.rgb * (1.0 - intensity) + s.r * intensity;
result.a = s.a;
return result;
}
CoreImage gestisce automaticamente la cache dei risultati intermedi. Se la stessa catena di filtri viene applicata a immagini diverse, CoreImage può riutilizzare gli shader compilati. Per massime prestazioni, evita di creare un CIContext per ogni fotogramma — usa un unico contesto e reimposta i parametri di input del filtro.
CIDetector è un sottosistema di CoreImage per rilevare oggetti semantici in un’immagine senza utilizzare Vision o Core ML. CIDetector supporta quattro tipi di rilevamento: volti (CIDetectorTypeFace), testo (CIDetectorTypeText), codici QR (CIDetectorTypeQRCode) e rettangoli (CIDetectorTypeRectangle). Il rilevatore funziona sulla CPU con ottimizzazione per le istruzioni NEON, garantendo una velocità stabile sui dispositivi senza una GPU potente.
Il rilevatore di volti CIDetectorTypeFace restituisce un array di CIFaceFeature con le coordinate dei confini del volto, la posizione degli occhi e della bocca. Da iOS 12, CIDetector rileva anche i sorrisi (hasSmile) e la posizione dell’occhio sinistro/destro (leftEyeClosed, rightEyeClosed). La precisione del rilevamento è sufficiente per la maggior parte delle applicazioni AR e foto, ma per scenari critici Apple raccomanda Vision.framework.
CIDetectorTypeRectangle trova aree rettangolari in un’immagine — documenti, biglietti da visita, schermi di dispositivi. Il rilevatore restituisce CIRectangleFeature con quattro punti che formano il contorno del rettangolo. Secondo la WWDC 2024, il rilevatore di rettangoli utilizza la stessa architettura di rete neurale di Vision, ma con un consumo di memoria inferiore. Ciò lo rende preferibile per l’elaborazione di flussi di fotogrammi in tempo reale, ad esempio nelle applicazioni di scansione documenti.
Esempi pratici aiuteranno a consolidare la comprensione di CoreImage. Esaminiamo due scenari tipici: applicare un filtro colore a una foto e il rilevamento dei volti con disegno del rettangolo delimitatore.
Un esempio base del filtro CISepiaTone, che converte un’immagine a colori in toni seppia. Il filtro accetta il parametro inputIntensity da 0 (originale) a 1 (effetto massimo). Nota la valutazione pigra: il CIImage restituito da filter.outputImage non contiene pixel — il rendering avviene solo quando viene chiamato context.createCGImage.
import CoreImage
guard let inputImage = CIImage(image: uiImage) else { return }
let filter = CIFilter(name: "CISepiaTone")
filter?.setValue(inputImage, forKey: kCIInputImageKey)
filter?.setValue(0.8, forKey: kCIInputIntensityKey)
let context = CIContext()
let outputImage = filter?.outputImage
let cgImage = context.createCGImage(outputImage!, from: inputImage.extent)
let resultImage = UIImage(cgImage: cgImage!)
L’esempio seguente utilizza CIDetector per trovare volti in un’immagine e disegnare un rettangolo intorno a ciascun volto rilevato. CIFaceFeature contiene coordinate nel sistema di coordinate dell’immagine (origine in basso a sinistra), quindi quando si disegna su UIKit, è necessaria una trasformazione delle coordinate tramite trasformazione affine.
let detector = CIDetector(
ofType: CIDetectorTypeFace,
context: context,
options: [CIDetectorAccuracy: CIDetectorAccuracyHigh]
)
let features = detector?.features(in: inputImage) as? [CIFaceFeature]
for face in features ?? [] {
print("Face bounds: \(face.bounds)")
if face.hasSmile {
print("La persona sorride")
}
}
L’esempio finale dimostra una catena di tre filtri: correzione del colore, vignettatura e sovrapposizione di texture. Nota che l’outputImage del primo filtro viene passato come inputImage al secondo — senza rendering intermedio. Quando viene chiamato createCGImage, CoreImage combina tutte e tre le operazioni in un singolo passaggio GPU.
let colorFilter = CIFilter(name: "CIColorControls")
colorFilter?.setValue(inputImage, forKey: kCIInputImageKey)
colorFilter?.setValues([
kCIInputBrightnessKey: 0.1,
kCIInputContrastKey: 1.2
])
let vignetteFilter = CIFilter(name: "CIVignette")
vignetteFilter?.setValue(colorFilter?.outputImage, forKey: kCIInputImageKey)
vignetteFilter?.setValue(2.0, forKey: "inputRadius")
let finalImage = vignetteFilter?.outputImage
let result = context.createCGImage(finalImage!, from: inputImage.extent)
Domande frequenti
CoreImage funziona sulla GPU ed è ottimizzato per operazioni sui pixel (filtri, correzione del colore), mentre Core Graphics è una libreria CPU per disegno vettoriale e contesti 2D. CoreImage è più veloce per l’elaborazione di massa delle immagini, Core Graphics è più preciso per il disegno passo passo dell’interfaccia.
Sì — CoreImage supporta l’elaborazione di singoli fotogrammi video tramite AVPlayerItemVideoOutput o AVCaptureOutput. Per l’elaborazione in streaming, utilizza AVVideoComposition con CIFilter, che consente di applicare effetti senza copiare fotogrammi tra CPU e GPU.
CoreImage per impostazione predefinita lavora nello spazio colore sRGB (kCGColorSpaceSRGB). Durante la creazione di un CIContext, è possibile specificare uno spazio alternativo — sRGB lineare esteso per HDR o Display P3 per display a gamma ampia.
Non c’è limite al numero di filtri in una catena, ma ogni 5–7 filtri consecutivi creano un passaggio GPU aggiuntivo. Per più di 10 filtri, si consiglia di suddividere la catena in gruppi e renderizzare i risultati intermedi per evitare di superare il limite dei registri dello shader.
Sì — CIDetector funziona sulla CPU utilizzando le istruzioni NEON su tutti i dispositivi con iOS 5.0 e successivi. La precisione del rilevamento è la stessa su tutti i dispositivi, ma la velocità è maggiore sui chip Apple A12+ grazie all’accelerazione hardware delle reti neurali.
Riepilogo
Svilupperemo un'applicazione mobile chiavi in mano
IT Sectr crea applicazioni iOS e Android per startup e aziende dal 2017. Ti consulteremo e ti proporremo la soluzione migliore.
Leggi anche