Twitter iPhone pliant OnePlus 11 PS5 Disney+ Orange Livebox Windows 11

Tk code hexa d'une couleur à partir du nom

22 réponses
Avatar
perlgenome
Bonjour,

Pouvez vous me dire comment obtenir le code hexa =E0 partir d'un nom de
couleur en perl Tk. Existe il une m=E9thode qui pourrait me le fournir.
Par exemple, afin d'obtenir #FF0000 pour la couleur 'red' ! Comment
Perl Tk fait il pour faire la correspondance entre les noms de couleur
et le code hexa. J'en ai besoin pour mettre =E0 jour mon code dans mes
modules.

Merci.

10 réponses

1 2 3
Avatar
Olivier Miakinen
Le 07/06/2010 11:32, perlgenome a écrit :

J'ai opté pour ceci my $hexcol = sprintf("#%02x%02x%02x", map { int($_/
256) } $top->rgb('gray50')); en utilisant int.



C'est en effet un moyen de s'assurer que le résultat soit toujours
tronqué au lieu d'être arrondi (au cas où ce ne serait pas déjà garanti
par le sprintf).

Sinon y a t il un moyen de passer d'un code 3 digits à 6 digit :
Exemple :
FFF 255 255 255 #FFFFFF
FFC 255 255 204 #FFFFCC
FF9 255 255 153 #FFFF99

Voici un lien récapitulatif : http://www.seoconsultants.com/css/colors/web/safe/

Ainsi, il suffirait de tester via une regex s'il n'y a que 3
caractères et le passer en 6, mais je ne trouve pas la logique pour
passer de #FFC à #FFFFCC par exemple.



Avec une regex, cf. la réponse de Paul de 10:25 +0200 :
<news:.

Sinon, par calcul, il suffit de multiplier chaque valeur par 17.

F = 15 ; 15 × 17 = 255 = FF
C = 12 ; 12 × 17 = 204 = CC
9 = 9 ; 9 × 17 = 153 = 99
Avatar
perlgenome
On 7 juin, 12:03, Olivier Miakinen <om+ wrote:
Le 07/06/2010 11:32, perlgenome a écrit :



> J'ai opté pour ceci my $hexcol = sprintf("#%02x%02x%02x", map { int ($_/
> 256) } $top->rgb('gray50')); en utilisant int.

C'est en effet un moyen de s'assurer que le résultat soit toujours
tronqué au lieu d'être arrondi (au cas où ce ne serait pas déjà garanti
par le sprintf).

> Sinon y a t il un moyen de passer d'un code 3 digits à 6 digit :
> Exemple :
> FFF  255   255     255     #FFFFFF
> FFC        255     255     204     #FFFFCC
> FF9        255     255     153     #FFFF99

> Voici un lien récapitulatif :http://www.seoconsultants.com/css/colors /web/safe/

> Ainsi, il suffirait de tester via une regex s'il n'y a que 3
> caractères et le passer en 6, mais je ne trouve pas la logique pour
> passer de #FFC à #FFFFCC par exemple.

Avec une regex, cf. la réponse de Paul de 10:25 +0200 :
<news:.

Sinon, par calcul, il suffit de multiplier chaque valeur par 17.

 F = 15 ; 15 × 17 = 255 = FF
 C = 12 ; 12 × 17 = 204 = CC
 9 =  9 ;  9 × 17 = 153 = 99



C'est parfait :

for my $col (qw/FFF FFC FF9 FF6 FC0/) {
my ( $Red, $Green, $Blue ) = $col =~ m{^([0-9A-Z])([0-9A-Z])([0-9A-
Z])$}g;
$Red = hex($Red) * 17;
$Green = hex($Green) * 17;
$Blue = hex($Blue) * 17;
printf( "$col ($Red,$Green,$Blue) : #%02X%02X%02Xn", $Red, $Green,
$Blue );
}

Résultat :

FFF (255,255,255) : #FFFFFF
FFC (255,255,204) : #FFFFCC
FF9 (255,255,153) : #FFFF99
FF6 (255,255,102) : #FFFF66

Merci à tous les deux.

Djibril
FC0 (255,204,0) : #FFCC00
Avatar
perlgenome
On 7 juin, 12:25, perlgenome wrote:
On 7 juin, 12:03, Olivier Miakinen <om+ wrote:



> Le 07/06/2010 11:32, perlgenome a écrit :

> > J'ai opté pour ceci my $hexcol = sprintf("#%02x%02x%02x", map { i nt($_/
> > 256) } $top->rgb('gray50')); en utilisant int.

> C'est en effet un moyen de s'assurer que le résultat soit toujours
> tronqué au lieu d'être arrondi (au cas où ce ne serait pas déj à garanti
> par le sprintf).

> > Sinon y a t il un moyen de passer d'un code 3 digits à 6 digit :
> > Exemple :
> > FFF  255   255     255     #FFFFFF
> > FFC        255     255     204     #FFFFCC
> > FF9        255     255     153     #FFFF99

> > Voici un lien récapitulatif :http://www.seoconsultants.com/css/colo rs/web/safe/

> > Ainsi, il suffirait de tester via une regex s'il n'y a que 3
> > caractères et le passer en 6, mais je ne trouve pas la logique pour
> > passer de #FFC à #FFFFCC par exemple.

> Avec une regex, cf. la réponse de Paul de 10:25 +0200 :
> <news:.

> Sinon, par calcul, il suffit de multiplier chaque valeur par 17.

>  F = 15 ; 15 × 17 = 255 = FF
>  C = 12 ; 12 × 17 = 204 = CC
>  9 =  9 ;  9 × 17 = 153 = 99

C'est parfait :

for my $col (qw/FFF FFC FF9 FF6 FC0/) {
  my ( $Red, $Green, $Blue ) = $col =~ m{^([0-9A-Z])([0-9A-Z])([0-9 A-
Z])$}g;
  $Red   = hex($Red) * 17;
  $Green = hex($Green) * 17;
  $Blue  = hex($Blue) * 17;
  printf( "$col ($Red,$Green,$Blue) : #%02X%02X%02Xn", $Red, $Green,
$Blue );

}

Résultat :

FFF (255,255,255) : #FFFFFF
FFC (255,255,204) : #FFFFCC
FF9 (255,255,153) : #FFFF99
FF6 (255,255,102) : #FFFF66

Merci à tous les deux.

Djibril
FC0 (255,204,0) : #FFCC00



D'ailleurs Paul,

Vu que tu as trouvé le bug de rgb avec des codes hexa (4bits), je
soumet un patch sur le CPAN pour le bug de rgb ou je te laisse le
faire ?
Avatar
Olivier Miakinen
Le 07/06/2010 12:25, perlgenome a écrit :

> J'ai opté pour ceci my $hexcol = sprintf("#%02x%02x%02x", map { int($_/
> 256) } $top->rgb('gray50')); en utilisant int.





Au fait, ça marchera si les valeurs retournées par $top->rgb() sont bien
toutes des multiples de 257 -- et en toute logique ça devrait être le cas.

Dans le cas plus qu'improbable où tu peux obtenir n'importe quel entier
entre 0 et 65535, il vaudrait mieux arrondir le résultat de la division
par 257 plutôt que tronquer le résultat de la division par 256 :

my $hexcol = sprintf("#%02x%02x%02x",
map { int($_/257 + 0.5) } $top->rgb('gray50'));

FFFF
-> FF par int($_/256)
-> FF par int($_/257)
-> FF par int($_/257 + 0.5)

FFFE
-> FF par int($_/256)
-> FE par int($_/257) *mauvais*
-> FF par int($_/257 + 0.5)

FEFF
-> FE par int($_/256)
-> FE par int($_/257)
-> FE par int($_/257 + 0.5)

FF00
-> FF par int($_/256) *mauvais*
-> FE par int($_/257)
-> FE par int($_/257 + 0.5)


Sinon, par calcul, il suffit de multiplier chaque valeur par 17.

F = 15 ; 15 × 17 = 255 = FF
C = 12 ; 12 × 17 = 204 = CC
9 = 9 ; 9 × 17 = 153 = 99



C'est parfait :

for my $col (qw/FFF FFC FF9 FF6 FC0/) {
my ( $Red, $Green, $Blue ) = $col =~ m{^([0-9A-Z])([0-9A-Z])([0-9A-
Z])$}g;
$Red = hex($Red) * 17;
$Green = hex($Green) * 17;
$Blue = hex($Blue) * 17;
printf( "$col ($Red,$Green,$Blue) : #%02X%02X%02Xn", $Red, $Green,
$Blue );
}



La solution de Paul me semblait plus simple :

<cit. news:
$HexColor =~ s/^#([0-9A-Z])([0-9A-Z])([0-9A-Z])$/#$1$1$2$2$3$3/i
if $HexColor =~ m/^#[0-9A-Z]{3}$/i;
</cit.>
Avatar
perlgenome
On 7 juin, 12:37, Olivier Miakinen <om+ wrote:
Le 07/06/2010 12:25, perlgenome a écrit :



>> > J'ai opté pour ceci my $hexcol = sprintf("#%02x%02x%02x", map { int($_/
>> > 256) } $top->rgb('gray50')); en utilisant int.

Au fait, ça marchera si les valeurs retournées par $top->rgb() sont b ien
toutes des multiples de 257 -- et en toute logique ça devrait être le cas.

Dans le cas plus qu'improbable où tu peux obtenir n'importe quel entier
entre 0 et 65535, il vaudrait mieux arrondir le résultat de la division
par 257 plutôt que tronquer le résultat de la division par 256 :

   my $hexcol = sprintf("#%02x%02x%02x",
         map { int($_/257 + 0.5) } $top->rgb('gray50'));

FFFF
 -> FF par int($_/256)
 -> FF par int($_/257)
 -> FF par int($_/257 + 0.5)

FFFE
 -> FF par int($_/256)
 -> FE par int($_/257)  *mauvais*
 -> FF par int($_/257 + 0.5)

FEFF
 -> FE par int($_/256)
 -> FE par int($_/257)
 -> FE par int($_/257 + 0.5)

FF00
 -> FF par int($_/256)  *mauvais*
 -> FE par int($_/257)
 -> FE par int($_/257 + 0.5)



>> Sinon, par calcul, il suffit de multiplier chaque valeur par 17.

>>  F = 15 ; 15 × 17 = 255 = FF
>>  C = 12 ; 12 × 17 = 204 = CC
>>  9 =  9 ;  9 × 17 = 153 = 99

> C'est parfait :

> for my $col (qw/FFF FFC FF9 FF6 FC0/) {
>   my ( $Red, $Green, $Blue ) = $col =~ m{^([0-9A-Z])([0-9A-Z])([0 -9A-
> Z])$}g;
>   $Red   = hex($Red) * 17;
>   $Green = hex($Green) * 17;
>   $Blue  = hex($Blue) * 17;
>   printf( "$col ($Red,$Green,$Blue) : #%02X%02X%02Xn", $Red, $Green,
> $Blue );
> }

La solution de Paul me semblait plus simple :

<cit.news:
 $HexColor =~ s/^#([0-9A-Z])([0-9A-Z])([0-9A-Z])$/#$1$1$2$2$3$3/i
   if $HexColor =~ m/^#[0-9A-Z]{3}$/i;
</cit.>



Bien vu.

Pour ma méthode, en faite, voici le code :

sub hex_to_rgb {
my ( $CompositeWidget, $HexColor ) = @_;

$HexColor = uc($HexColor);
$HexColor =~ s/^#([0-9A-Z])([0-9A-Z])([0-9A-Z])$/#$1$1$2$2$3$3/

my ( $Red, $Green, $Blue ) = ();
if ( $HexColor =~ m{^#(?:[0-9A-Z]{2}){3}$} ) {
$Red = hex( substr( $HexColor, 1, 2 ) );
$Green = hex( substr( $HexColor, 3, 2 ) );
$Blue = hex( substr( $HexColor, 5, 2 ) );
}
elsif ( $HexColor =~ m{^#} ) {
$CompositeWidget->_error_bg( "Invalid color : We need color name
or #RRGGBB or #RGB n", 1 );
}

# Color name (Tk work in 16 bits)
else {
( $Red, $Green, $Blue ) = map { int( ( $_ / 257 ) + 0.5 ) }
$CompositeWidget->rgb($HexColor);
}

return ( $Red, $Green, $Blue );
}

return ( $Red, $Green, $Blue );
}
Avatar
Jerome Quelin
Paul Gaborit wrote:
Un truc du genre devrait faire l'affaire :

$HexColor =~ s/^#([0-9A-Z])([0-9A-Z])([0-9A-Z])$/#$1$1$2$2$3$3/i
if $HexColor =~ m/^#[0-9A-Z]{3}$/i;



euh, pourquoi faire 2 correspondances de regex quand une seule suffit ?

$hexColor = "#$1$1$2$2$3$3"
if $HexColor =~ m/^#([0-9A-F])([0-9A-F])([0-9A-F])$/i;

à noter aussi que la classe de caractères s'arrete après le f.

jerome
--

Avatar
Jerome Quelin
Olivier Miakinen wrote:
Malgré mes bonnes résolutions, je n'ai pas encore commencé à programmer
en Perl. Du coup je ne sais pas répondre à cette question : c'est le
sprintf qui tronque, ou bien c'est une conversion automatique de réel en
entier, avant le passage à sprintf ? Et, question essentielle, est-ce
que ce comportement est garanti ?



extrait de perldoc -f sprintf :

%x an unsigned integer, in hexadecimal

noter le *integer* ==> perl va convertir automatiquement, c'est garanti.
et la conversion se fait dans sprintf, et non pas avant. en effet, il est
tout à fait possible de passer à sprintf un réel :

$ perl -e 'printf "%xn", 14.32'
e

jerome
--

Avatar
Paul Gaborit
À (at) Mon, 07 Jun 2010 13:44:28 +0200,
Jerome Quelin écrivait (wrote):

extrait de perldoc -f sprintf :

%x an unsigned integer, in hexadecimal

noter le *integer* ==> perl va convertir automatiquement, c'est
garanti.



Ok pour la conversion en entier... mais se fera-t-elle toujours par
troncation (c'est le cas aujourd'hui) ou pourrait-elle un jour se faire
par arrondi ?

et la conversion se fait dans sprintf, et non pas avant. en effet, il est
tout à fait possible de passer à sprintf un réel :



Ça, c'est sûr ! ;-)

--
Paul Gaborit - <http://perso.mines-albi.fr/~gaborit/>
Perl en français - <http://perl.mines-albi.fr/>
Avatar
Paul Gaborit
À (at) Mon, 07 Jun 2010 13:40:07 +0200,
Jerome Quelin écrivait (wrote):

euh, pourquoi faire 2 correspondances de regex quand une seule suffit ?



Oui, pourquoi ? Peut-être parce que j'ai écrit le code en deux fois :
d'abord la substitution puis ensuite le test pour savoir s'il fallait
l'appliquer... ;-)

$hexColor = "#$1$1$2$2$3$3"
if $HexColor =~ m/^#([0-9A-F])([0-9A-F])([0-9A-F])$/i;

à noter aussi que la classe de caractères s'arrete après le f.



Là, par contre, c'est de l'inattention. En fait, j'ai cherché un
équivalent plus simple ou plus clair mais [[:xdigit:]] est plus long que
[0-9a-f] (même si on doit ajouter le /i) !

--
Paul Gaborit - <http://perso.mines-albi.fr/~gaborit/>
Perl en français - <http://perl.mines-albi.fr/>
Avatar
Paul Gaborit
À (at) Mon, 7 Jun 2010 03:31:24 -0700 (PDT),
perlgenome écrivait (wrote):

Vu que tu as trouvé le bug de rgb avec des codes hexa (4bits), je
soumet un patch sur le CPAN pour le bug de rgb ou je te laisse le
faire ?



Fonce... J'ai le flemme de le faire d'autant qu'il faut encore trouver
où est le bug et faire le patch ! ;-)

--
Paul Gaborit - <http://perso.mines-albi.fr/~gaborit/>
Perl en français - <http://perl.mines-albi.fr/>
1 2 3