CoreImage est un framework Apple pour le traitement d’images et de vidéos en temps réel, fournissant des dizaines de CIFilter intégrés pour la correction des couleurs, le flou, les superpositions de textures et la détection. Selon la Documentation Apple, CoreImage utilise le GPU pour un traitement haute performance des pixels sur les appareils iOS. Le framework prend en charge CIImage en tant qu’objet image immuable et des chaînes de filtres pour composer des effets sans perte de qualité.
Points essentiels
CoreImage est un framework Apple pour le traitement d’images raster et de vidéos, présenté pour la première fois dans macOS 10.4 Tiger et porté sur iOS 5.0. Contrairement à Core Graphics ou UIKit, CoreImage fonctionne au niveau des shaders de pixels, en utilisant le GPU pour des calculs parallèles. Cela permet d’appliquer des effets complexes — flou, correction des couleurs, morphing — à des images en mégapixels en quelques millisecondes.
L’architecture de CoreImage est construite sur le concept d’évaluation paresseuse (lazy evaluation) : CIFilter n’effectue aucun traitement jusqu’au rendu dans CIContext. Le développeur construit une chaîne de plusieurs CIFilter, en connectant la sortie d’un filtre à l’entrée d’un autre, et seul l’appel render lance le pipeline GPU complet. Cela minimise le nombre de passes à travers la carte graphique et maintient les performances.
CoreImage prend en charge une large gamme de couleurs (P3, sRGB, sRGB linéaire), les images HDR et le travail avec des formats de pixels 16 et 32 bits. Sur les appareils dotés d’un Neural Engine, CoreImage peut combiner des shaders GPU avec Core ML pour un traitement intelligent — par exemple, une correction automatique des couleurs basée sur l’apprentissage automatique, comme implémenté dans l’application Photos sur iOS 17.
Trois classes principales forment le cœur de CoreImage : CIImage (données), CIFilter (opération) et CIContext (environnement d’exécution). Chaque classe est responsable de sa propre phase du pipeline et ne mélange pas les responsabilités.
CIImage est un objet léger qui décrit une image mais ne contient pas directement de données pixels. Il peut être créé à partir d’UIImage, CGImage, d’une texture Metal, d’une texture GL ou d’un fichier sur disque. CIImage est immuable — toute application de filtre crée un nouveau CIImage sans modifier l’original. Cela permet de construire des chaînes de transformation sans copier les données entre les étapes.
Une caractéristique importante : CIImage n’est lié ni à la résolution d’écran ni à l’espace colorimétrique jusqu’au rendu. Le même CIImage peut être rendu en UIImage pour l’écran et en fichier TIFF pour l’impression avec des paramètres différents — CoreImage adapte automatiquement le traitement au contexte cible.
CIFilter est la classe principale pour appliquer des effets. Chaque CIFilter est un programme shader avec des paramètres d’entrée (inputImage, inputIntensity, inputRadius, etc.) et une image de sortie. Apple fournit plus de 200 CIFilter intégrés, regroupés par catégories : CICategoryColorEffect (correction des couleurs), CICategoryBlur (flou), CICategoryStylize (stylisation), CICategoryGeometryAdjust (transformations géométriques).
Pour créer un CIFilter personnalisé, le développeur écrit un shader Metal (CIKernel) — un shader de fragments en Metal Shading Language qui traite chaque pixel indépendamment. Après compilation, le shader est enregistré comme sous-classe de CIFilter et peut être utilisé dans des chaînes aux côtés des filtres intégrés d’Apple.
| Catégorie | Exemple de filtre | Objectif |
|---|---|---|
| ColorEffect | CIColorControls | Luminosité, contraste, saturation |
| Blur | CIGaussianBlur | Flou gaussien avec rayon réglable |
| Stylize | CIPixellate | Pixelisation avec échelle définie |
| GeometryAdjust | CIAffineTransform | Rotation, échelle, translation via matrice affine |
| Composite | CISourceOverCompositing | Composition d’images avec canal alpha |
CIContext est un objet lourd qui gère l’allocation des ressources GPU, la compilation des shaders et la mise en tampon. Créer un CIContext est une opération coûteuse, c’est pourquoi Apple recommande de le créer une fois pour tout le cycle de vie de l’application et de le réutiliser. Le contexte est lié à un GPU spécifique (Metal, OpenGL) ou au CPU et détermine l’espace colorimétrique de l’image de sortie.
La bibliothèque CIFilter est en constante expansion : iOS 17 a ajouté de nouveaux filtres pour le traitement HDR et l’apprentissage automatique. Tous les filtres intégrés sont documentés dans la Documentation Développeur Apple et peuvent être recherchés par catégories ou noms. Pour découvrir les filtres disponibles sur l’appareil, utilisez CIFilter.filterNames(inCategory:).
La capacité principale de CoreImage est de composer plusieurs CIFilter en une chaîne. La sortie d’un filtre est alimentée à l’entrée d’un autre via le paramètre inputImage. CoreImage optimise la chaîne au moment du rendu : les filtres adjacents travaillant dans le même espace colorimétrique sont combinés en une seule passe GPU (kernel fusion). Cela offre un gain de performance sans intervention du développeur.
Pour créer un effet personnalisé, le développeur écrit une fonction Metal avec l’annotation [[kernel]]. La fonction reçoit les coordonnées du pixel et retourne une couleur. CoreImage transmet le shader au GPU, où il s’exécute en parallèle pour tous les pixels de l’image. Les filtres personnalisés sont particulièrement utiles pour des effets visuels uniques : sépia avec courbe non linéaire, flou de dispersion ou simulation de grain de pellicule.
#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 gère automatiquement le cache des résultats intermédiaires. Si la même chaîne de filtres est appliquée à différentes images, CoreImage peut réutiliser les shaders compilés. Pour des performances maximales, évitez de créer un CIContext pour chaque trame — utilisez un seul contexte et réinitialisez les paramètres d’entrée du filtre.
CIDetector est un sous-système de CoreImage pour détecter des objets sémantiques dans une image sans utiliser Vision ou Core ML. CIDetector prend en charge quatre types de détection : visages (CIDetectorTypeFace), texte (CIDetectorTypeText), codes QR (CIDetectorTypeQRCode) et rectangles (CIDetectorTypeRectangle). Le détecteur fonctionne sur le CPU avec une optimisation pour les instructions NEON, garantissant une vitesse stable sur les appareils sans GPU puissant.
Le détecteur de visages CIDetectorTypeFace retourne un tableau de CIFaceFeature avec les coordonnées des limites du visage, la position des yeux et de la bouche. Depuis iOS 12, CIDetector détecte également les sourires (hasSmile) et la position de l’œil gauche/droit (leftEyeClosed, rightEyeClosed). La précision de la détection est suffisante pour la plupart des applications AR et photo, mais pour les scénarios critiques, Apple recommande Vision.framework.
CIDetectorTypeRectangle trouve des zones rectangulaires dans une image — documents, cartes de visite, écrans d’appareils. Le détecteur retourne CIRectangleFeature avec quatre points formant le contour du rectangle. Selon la WWDC 2024, le détecteur de rectangles utilise la même architecture de réseau neuronal que Vision, mais avec une consommation mémoire réduite. Cela le rend préférable pour le traitement de flux d’images en temps réel, par exemple dans les applications de numérisation de documents.
Des exemples pratiques aideront à consolider la compréhension de CoreImage. Examinons deux scénarios typiques : appliquer un filtre de couleur à une photo et la détection de visages avec dessin de cadre englobant.
Un exemple de base du filtre CISepiaTone, qui convertit une image couleur en tons sépia. Le filtre accepte le paramètre inputIntensity de 0 (original) à 1 (effet maximal). Notez l’évaluation paresseuse : le CIImage retourné par filter.outputImage ne contient pas de pixels — le rendu n’a lieu que lorsque context.createCGImage est appelé.
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’exemple suivant utilise CIDetector pour trouver des visages dans une image et dessiner un rectangle autour de chaque visage détecté. CIFaceFeature contient des coordonnées dans le système de coordonnées de l’image (origine en bas à gauche), donc lors du dessin sur UIKit, une transformation de coordonnées via transformation affine est nécessaire.
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 personne sourit")
}
}
L’exemple final démontre une chaîne de trois filtres : correction des couleurs, vignettage et superposition de texture. Notez que l’outputImage du premier filtre est passée comme inputImage au second — sans rendu intermédiaire. Lorsque createCGImage est appelé, CoreImage combine les trois opérations en une seule passe 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)
Foire aux questions
CoreImage fonctionne sur le GPU et est optimisé pour les opérations sur les pixels (filtres, correction des couleurs), tandis que Core Graphics est une bibliothèque CPU pour le dessin vectoriel et les contextes 2D. CoreImage est plus rapide pour le traitement par lots d’images, Core Graphics est plus précis pour le dessin étape par étape d’interfaces.
Oui — CoreImage prend en charge le traitement de trames vidéo individuelles via AVPlayerItemVideoOutput ou AVCaptureOutput. Pour le traitement en flux, utilisez AVVideoComposition avec CIFilter, ce qui permet d’appliquer des effets sans copier les trames entre le CPU et le GPU.
CoreImage travaille par défaut dans l’espace colorimétrique sRGB (kCGColorSpaceSRGB). Lors de la création d’un CIContext, vous pouvez spécifier un espace alternatif — sRGB linéaire étendu pour le HDR ou Display P3 pour les écrans à large gamme.
Il n’y a pas de limite sur le nombre de filtres dans une chaîne, mais tous les 5–7 filtres consécutifs créent une passe GPU supplémentaire. Pour plus de 10 filtres, il est recommandé de diviser la chaîne en groupes et de rendre les résultats intermédiaires pour éviter de dépasser la limite de registres du shader.
Oui — CIDetector fonctionne sur le CPU en utilisant les instructions NEON sur tous les appareils avec iOS 5.0 et supérieur. La précision de la détection est la même sur tous les appareils, mais la vitesse est plus élevée sur les puces Apple A12+ grâce à l’accélération matérielle des réseaux de neurones.
Résumé
Nous développerons une application mobile clé en main
IT Sectr crée des applications iOS et Android pour les startups et les entreprises depuis 2017. Nous vous conseillerons et vous proposerons la meilleure solution.
Lisez aussi