Connaà®tre la valeur héxadécimal à partir d'une couleur et vice-versa
Tchouboudou
Membre
Bonjour...
Je me demandais en cours (parce que c'est pas très interessant l'EPS), comment connaà®tre la valeur héxadécimal d'une couleur. J'ai donc regarder la classe NSColor. Grâce à mon fameux anglais, j'ai pas trouvé... C'est pourquoi je m'adresse à vous, pour m'aider dans la recherche de la solution.
Merci d'avance,
Tchouboudou
By the way, je sais pas si j'ai posté dans le bon forum
Je me demandais en cours (parce que c'est pas très interessant l'EPS), comment connaà®tre la valeur héxadécimal d'une couleur. J'ai donc regarder la classe NSColor. Grâce à mon fameux anglais, j'ai pas trouvé... C'est pourquoi je m'adresse à vous, pour m'aider dans la recherche de la solution.
Merci d'avance,
Tchouboudou
By the way, je sais pas si j'ai posté dans le bon forum
Connectez-vous ou Inscrivez-vous pour répondre.
Réponses
Le plus simple est d'utiliser stringWithFormat en utilisant le format "%02X" pour écrire un octet sous forme décimale.
Pour info, le "X" indiquant le format hexadécimal (x minuscule si tu prèfères que les lettres a-f soient en minuscules et non majuscules), le "2" indiquant que tu le veux sur 2 caractères minimum, et le "0" devant indiquant que si le résultat est sur moins de 2 caractères, tu remplis les blancs avec des zéros (et non pas des espaces comme c'est le cas par défaut)
Comme les composantes d'une couleur sont stoquées sous forme de float entre 0.0 et 1.0 en Cocoa, il faut les multiplier par 255 avant de les convertir en hexa.
Ce qui donne un truc comme : (Attention à ce que ta NSColor passée utilise le RGBColorSpace)
Quitte à les scanner 2 caractères par 2 caractères, pour récupérer 3 ints distincs, qu'il suffira ensuite de diviser par 255.0 pour avoir les valeurs des composantes red, green, blue.
Je te laisse regarder ça si c'est ça que tu veux, histoire de t'entraà®ner à chercher un peu aussi (et puis surtout parce que je suis loin d'être un as de NSScanner )
Très bien Ali !
Et rien que pour toi, je te donne l'exemple de NSScanner selon ce que tu viens de dire !
Tu verras, NSScanner deviendra vite ton ami...
Edit : correction suite au post de Ali.
.
Tchouboudou : tu as vérifié que ta NSColor utilisait le RGBColorSpace ? (si ce n'est pas le cas, tu auras une exception et donc à priori plantage ensuite). Il aurait été intéressant de faire un NSLog de [sender color] aussi, par exemple...
Je t'avais mis le code simpliste, mais un petit "NSColor* rgbColor = [aColor colorUsingColorSpaceName]" avant d'en extraire les red,green et blue components (de cette rgbColor et non plus de aColor du coup) serait quand même mieux pour s'assurer d'être dans le bon ColorSpace avant (plutôt que de le présupposer)
Ceci dit tu ne nous aide pas beaucoup : quand tu dis "le code ne marche pas", tu peux préciser ce que tu entends par là ? Il ne se compile pas, le compilo affiche des erreurs (si oui lesquelles !) ? Il plante au moment de l'execution (si oui avec quel message) ? Tu as testé les méthodes isolément ?
Voilà ce que affiche [sender color] : NSCalibratedRGBColorSpace 0.8985 1 0.241167 1
En effet le résultat d'un float (valeur de chaque composante, entre 0.0 et 1.0) multiplié par un entier est un float. Et moi je demande à stringWithFormat de l'interpréter comme un entier (et de l'écrire sous forme hexa), donc en gros de lire la mémoire comme si les bits qu'il y a dans la variable représentaient un entier, alors qu'en fait ils représentent un float. C'est là qu'il s'embrouille...
Conclusion : il faut caster chaque composante qu'on a multiplié par 255 en un type entier, voire même plus précisément un [tt](unsigned char)[/tt] (puisque ça n'est codé que sur un octet, ne prenant que des valeurs entre 0x00 et 0xFF pour chaque composante).
[EDIT]Je viens à l'instant de tester le code pour le valider, c'était bien ça. J'ai aussi rajouté la conversion en couleur RGB pour éviter tout souci.
Non, tu ne te trompes pas.
Merci à ton oeil perspicace.
.
PS: Sinon pour ceux qui n'auraient pas vu mon edit (surtout Tchouboudou), j'ai rajouté plus haut la conversion de la couleur dans l'espace RGB avant d'en extraire les composantes, par sécurité et pour rendre la méthode générique.
Bonjour,
Je me permets de faire remonter ce fil car le code de bru est exactement ce que je cherchais.
Le problème est qu'il ne se compile pas...
cette ligne:
ok=[scan scanHexInt:&composant]
me donne comme warning:
"passing argument 1 of 'scanHexInt:' makes pointer from integer without a cast"
C'est sans doute tout con mais je n'arrive pas à résoudre ce problème :why?:
Ce code est bien compliqué . Le C fournit direct
char * hexcol="C0B508";
long composant=strtol(hexcol,NULL,16);
et si hexcol est une NSString prendre [hexcol UTF8String].
char * hexcol="C0B508";
unsigned int composant;
sscanf(hexcol,"%x",&composant);
Comme tu peux le voir, ce n'est pas le cas, j'ai bien mis le symbole & devant composant. Je sais bien que tu as mis "par exemple" mais je ne vois pas du tout ce que cela peut-être d'autre
Je n'ai pas compris. Que fait-on de composant après? C'est un long qui contient la valeur décimale de hexcol mais peut-on créer une variable NSColor avec un long?
EDIT: [[hexcol substringWithRange:NSMakeRange(ix*2, 2)] UTF8String] ::)
Bon, ça marchotte. je dessine bien avec la couleur choisie mais si je scrolle dans ma vue ou si j'agrandis ma fenêtre: boom! ça plante. :-\\
Mon NSColor ne doit pas avoir une valeur très catholique. (car si je mets un NSColor bidon, du style redColor, tout fonctionne)
Comment as-tu déclaré composant ?
int composant car scanHexInt: l'exige
Oui , je n'avais lu que la partie "lecture de la valeur composant" pas la couleur.
Pour la couleur, je mettrais :
Résumons
composant est un int
&composant est donc un pointeur sur int
et le prototype de scanHexInt est
- (BOOL)scanHexInt:(unsigned *)intValue
Essaie avec composant déclaré en unsigned int ou en castant (unsigned *) &composantÂ
c'est fait.
Pour le coup, je trouve cela peu lisible (et ton code ne se compile pas). J'ai préféré opter pour ton idée à base de strtol et j'ai écrit une méthode très simple, au code certainement peu apprécié des adorateurs de la factorisation à outrance
J'ai abandonné l'utilisation du NSScanner que je ne maà®trise pas du tout.
(Sinon, je vais ouvrir un autre fil car je rencontre un problème avec NSColor similaire à celui que j'avais connu avec NSDate)
@interface NSColor(RocouAdditions)
+(NSColor*)ColorValueForHex:(NSString*)hexcol;
@end
@implementation NSColor(RocouAdditions)
+(NSColor*)ColorValueForHex:(NSString*)hexcol
{
CGFloat c1,c2,c3;
c1=strtol([[hexcol substringWithRange:NSMakeRange(0, 2)] UTF8String],NULL,16);
c2=strtol([[hexcol substringWithRange:NSMakeRange(2, 2)] UTF8String],NULL,16);
c3=strtol([[hexcol substringWithRange:NSMakeRange(4, 2)] UTF8String],NULL,16);
return [NSColor colorWithDeviceRed:c1/255.0 green:c2/255.0 blue:c3/255.0 alpha:1];
}
@end
Ha oui, j'oublie toujours; merci beaucoup!
Sinon j'ai pas essayé, mais strtol ne sait pas prendre une chaà®ne hexa à 6 caractères ? (et donc retourner un long entre 0 et 256^3) ? Si c'est le cas j'aurais plutôt demandé à strtol de convertir tout d'un coup, et découpé (avec des masques) le résultat après, genre : L'avantage de cette méthode est qu'elle sait aussi gérer les cas où hexcol commence par "0x", genre une valeur hexa "0x123456".
Après pour faire propre et avoir une catégorie assez générique, on peut rajouter la gestion de l'alpha, de manière automatique tant qu'à faire : Voilà ... ce qui est d'ailleurs encore améliorable en faisant un meilleur test pour isRGBA (genre en passant un 2e paramètre non NULL à strtol pour vérifier le nombre de caractères effectivement lus, pour affiner les cas où l'on passerait des valeurs de hexcol bizarres genre @ 0x123456 zk ...
Si cela compile, (il y avait simplement un ; en fin du #define à supprimer)