Comment colorer des icônes au runtime en Objective-C sur iOS
Ecrit par Dumè Siacci le
GoodBarber vous permet de créer de belles applications, à votre image, en quelques clics. Parmi les centaines de nouveaux éléments de la V2, nous avons mis en place un système vous permettant de modifier les couleurs de vos icônes de TabBar simplement pour créer de jolis effets.
Nous avons choisi de vous proposer un large choix d’icônes, mais il était évidemment impossible d’anticiper toutes les possibilités de customisation. Pour des raisons de cohérence, et notamment car nous vous proposons toujours d’utiliser une TabBar au design standard, nous avons choisi de conserver comme base un set d’icônes au format standard (PNG blanc jouant uniquement sur la transparence).
Afin de mettre en place un système permettant de colorer les images depuis les applications clientes en fonction des paramètres renseignés (couleur au format hexa), nous avons suivi le raisonnement suivant.
Nous avons choisi de vous proposer un large choix d’icônes, mais il était évidemment impossible d’anticiper toutes les possibilités de customisation. Pour des raisons de cohérence, et notamment car nous vous proposons toujours d’utiliser une TabBar au design standard, nous avons choisi de conserver comme base un set d’icônes au format standard (PNG blanc jouant uniquement sur la transparence).
Afin de mettre en place un système permettant de colorer les images depuis les applications clientes en fonction des paramètres renseignés (couleur au format hexa), nous avons suivi le raisonnement suivant.
Colorer une image avec CGImageCreateWithMask
La fonction la plus adaptée pour colorer une image en fonction d’un masque (notre icône de base en l’occurence) est CGImageCreateWithMask. Cette fonction prend un premier paramètre correspondant à l’image devant être découpée selon le masque (la couleur) et le masque proprement dit (l’icône). Très basiquement, le masque est une image en niveau de gris, dans lequel les pixels blancs sont ignorés, et les pixels noirs sont conservés en opacité selon leur intensité de noir. Il est donc nécessaire de transformer préalablement nos icônes afin qu’elles respectent cette spécification.
Cela se fait en deux étapes : créer un négatif de l’image d’origine (nous savons que les icônes contiennent uniquement des pixels blancs, dont nous voulons qu’il deviennent noirs), et y ajouter un background blanc.
Pour des raisons de commodités d’utilisation, nous avons créé une catégorie d’UIImage.
Cela se fait en deux étapes : créer un négatif de l’image d’origine (nous savons que les icônes contiennent uniquement des pixels blancs, dont nous voulons qu’il deviennent noirs), et y ajouter un background blanc.
Pour des raisons de commodités d’utilisation, nous avons créé une catégorie d’UIImage.
Créer un négatif de l'image et remplacer la transparence par un fond blanc
-(UIImage *) negativeImage
{
UIGraphicsBeginImageContext(self.size);
CGContextSetBlendMode(UIGraphicsGetCurrentContext(), kCGBlendModeCopy);
[self drawInRect:CGRectMake(0, 0, self.size.width, self.size.height)];
CGContextSetBlendMode(UIGraphicsGetCurrentContext(), kCGBlendModeDifference);
CGContextSetFillColorWithColor(UIGraphicsGetCurrentContext(),[UIColor whiteColor].CGColor);
CGContextFillRect(UIGraphicsGetCurrentContext(), CGRectMake(0, 0, self.size.width, self.size.height));
UIImage *negativeImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return negativeImage;
}
- (UIImage *) imageWithWhiteBackground
{
UIImage *negative = [self negativeImage];
UIGraphicsBeginImageContext(negative.size);
CGContextSetRGBFillColor (UIGraphicsGetCurrentContext(), 1, 1, 1, 1);
CGRect thumbnailRect = CGRectZero;
thumbnailRect.origin = CGPointZero;
thumbnailRect.size.width = negative.size.width;
thumbnailRect.size.height = negative.size.height;
CGContextTranslateCTM(UIGraphicsGetCurrentContext(), 0.0, negative.size.height);
CGContextScaleCTM(UIGraphicsGetCurrentContext(), 1.0, -1.0);
CGContextFillRect(UIGraphicsGetCurrentContext(), thumbnailRect);
CGContextDrawImage(UIGraphicsGetCurrentContext(), thumbnailRect, negative.CGImage);
UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return newImage;
}
Une fois que nous avons obtenu un masque au bon format, nous pouvons l’appliquer sur une image de couleur pleine (voire éventuellement une texture) grâce à CGImageCreateWithMask.
Appliquer une image de couleur pleine au masque
+ (UIImage *) image:(UIImage *)image withMaskColor:(UIColor *)color
{
UIImage *formattedImage = [image imageWithWhiteBackground];
CGRect rect = {0, 0, formattedImage.size.width, formattedImage.size.height};
UIGraphicsBeginImageContextWithOptions(rect.size, NO, 0);
[color setFill];
UIRectFill(rect);
UIImage *tempColor = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
CGImageRef maskRef = [formattedImage CGImage];
CGImageRef maskcg = CGImageMaskCreate(CGImageGetWidth(maskRef),
CGImageGetHeight(maskRef),
CGImageGetBitsPerComponent(maskRef),
CGImageGetBitsPerPixel(maskRef),
CGImageGetBytesPerRow(maskRef),
CGImageGetDataProvider(maskRef), NULL, false);
CGImageRef maskedcg = CGImageCreateWithMask([tempColor CGImage], maskcg);
CGImageRelease(maskcg);
UIImage *result = [UIImage imageWithCGImage:maskedcg];
CGImageRelease(maskedcg);
return result;
}
On imaginera facilement comment adapter ce code pour appliquer une texture, sous forme d'image, plutôt qu'un aplât de couleur.
Pour des raisons d’optimisation, il est utile de mettre en cache l’UIImage générée (sur le système de fichiers ou en mémoire) plutôt que d’appeler cette méthode à chaque affichage.
Pour des raisons d’optimisation, il est utile de mettre en cache l’UIImage générée (sur le système de fichiers ou en mémoire) plutôt que d’appeler cette méthode à chaque affichage.
Liens utiles
- Documentation officielle Apple : Bitmap Images and Image Masks dans la documentation iOS
POUR ALLER PLUS LOIN :
- Chez GoodBarber, vous pouvez travailler le design de votre app en fonction de vos envies. Chaque modification est permise grâce à un fichier qui propose de nombreux paramétrages. Nous vous proposions déjà de nombreuses fonctionnalités pour mettre en forme les objets et les éléments de votre application mobile, mais nous ne nous sommes pas arrêtés là ! Découvrez notre nouveau menu Style Global : pour mettre en couleurs votre application et la rendre esthétique sur un écran de mobile. Suivez les étapes de notre méthode pour tout comprendre.
- GoodBarber est là pour vous accompagner dans votre développement, de la création de votre app jusqu'à sa publication sur le store ios ou android. En fonction de celui que vous avez choisi, découvrez comment soumettre son application dans Google Play . Ce fichier vous présentera les étapes qui aboutiront à l'apparition de votre application sur l'écran de votre mobile.
- En fonction du système d'exploitation sur lequel vous souhaitez retrouver votre app, ios ou android, la méthode de soumission n'est pas la même. Aujourd'hui nous vous expliquons comment créer un compte développeur Google Play . L'ouverture d'un tel fichier ne nécessite que quelques étapes, mais qui peuvent paraître compliquées sans aide. Grâce aux conseils de GoodBarber, votre application se retrouvera bientôt sur l'écran de votre samsung !
- Android a développé un nouveau fichier concernant les notifications qui s'affichent sur l'écran de vos utilisateurs. Découvrez Firebase Cloud Messaging pour rester à jour dans l'envoi des notifications push sur android et comprendre la nouvelle méthode de fonctionnement du logiciel. Si vous avez développé votre app sur ios, vous n'êtes pas concerné par ce changement.