Éclaircir ou assombrir par programme une couleur hexadécimale (ou RVB et mélanger les couleurs)


504

Voici une fonction sur laquelle je travaillais pour éclaircir ou assombrir par programme une couleur hexadécimale d'une quantité spécifique. Passez juste une chaîne comme "3F6D2A"pour la couleur ( col) et un entier base10 ( amt) pour la quantité d'éclaircir ou d'assombrir. Pour foncer, passez un nombre négatif (ie -20).

La raison pour laquelle je l'ai fait était à cause de toutes les solutions que j'ai trouvées, jusqu'à présent, elles semblaient trop compliquer le problème. Et j'avais le sentiment que cela pouvait être fait avec seulement quelques lignes de code. S'il vous plaît laissez-moi savoir si vous rencontrez des problèmes ou si vous avez des ajustements à faire pour accélérer le processus.

function LightenDarkenColor(col, amt) {
  col = parseInt(col, 16);
  return (((col & 0x0000FF) + amt) | ((((col >> 8) & 0x00FF) + amt) << 8) | (((col >> 16) + amt) << 16)).toString(16);
}


// TEST
console.log( LightenDarkenColor("3F6D2A",40) );

Pour le développement, voici une version plus facile à lire:

function LightenDarkenColor(col, amt) {
  var num = parseInt(col, 16);
  var r = (num >> 16) + amt;
  var b = ((num >> 8) & 0x00FF) + amt;
  var g = (num & 0x0000FF) + amt;
  var newColor = g | (b << 8) | (r << 16);
  return newColor.toString(16);
}


// TEST
console.log(LightenDarkenColor("3F6D2A", -40));

Et enfin une version pour gérer les couleurs qui peuvent (ou non) avoir le "#" au début. De plus, ajustement pour des valeurs de couleur incorrectes:

function LightenDarkenColor(col,amt) {
    var usePound = false;
    if ( col[0] == "#" ) {
        col = col.slice(1);
        usePound = true;
    }

    var num = parseInt(col,16);

    var r = (num >> 16) + amt;

    if ( r > 255 ) r = 255;
    else if  (r < 0) r = 0;

    var b = ((num >> 8) & 0x00FF) + amt;

    if ( b > 255 ) b = 255;
    else if  (b < 0) b = 0;

    var g = (num & 0x0000FF) + amt;

    if ( g > 255 ) g = 255;
    else if  ( g < 0 ) g = 0;

    return (usePound?"#":"") + (g | (b << 8) | (r << 16)).toString(16);
}

OK, maintenant ce ne sont plus seulement quelques lignes, mais cela semble beaucoup plus simple et si vous n'utilisez pas le "#" et n'avez pas besoin de vérifier les couleurs hors plage, ce ne sont que quelques lignes.

Si vous n'utilisez pas le "#", vous pouvez simplement l'ajouter dans du code comme:

var myColor = "3F6D2A";
myColor = LightenDarkenColor(myColor,10);
thePlaceTheColorIsUsed = ("#" + myColor);

Je suppose que ma principale question est, ai-je raison ici? Cela n'inclut-il pas certaines situations (normales)?


1
Si vous n'obtenez pas les résultats escomptés lors de la modification des couleurs, je vous suggère de regarder dans l'espace colorimétrique LAB, qui est plus proche de la vision humaine. De nombreuses langues ont des bibliothèques de conversion. D'après mon expérience, les nuances d'orange peuvent être problématiques lors de l'assombrissement ou de l'éclaircissement.
Henrik

Très bon point. Cependant, l'objectif principal de cette question était de trouver, d'une part, la formule d'exécution la plus rapide et la plus petite taille ... et d'autre part, sa précision. Par conséquent, pourquoi je ne me suis pas occupé de la conversion en HSL ou autre chose. Ici, la vitesse et la taille sont plus importantes. Mais, comme vous pouvez le voir avec ma version 2 de la formule. L'utilisation de LERP pour ombrer se traduira par des oranges agréables sur toute la plage de teintes. Jetez un œil au nuancier ci-dessous et faites-moi savoir si cette gamme de nuances n'est pas sacrément proche de la précision réelle.
Pimp Trizkit

Je suis un peu confus avec la structure ici, mais vous avez raison, les niveaux d'orange pour shadowColor1 semblent très bons.
Henrik

Lol, tu veux dire shadowColor2. Je suppose que la structure dont vous parlez est la disposition générale de la réponse elle-même? Des conseils pour être plus clair?
Pimp Trizkit

3
Il y a juste un problème dans la fonction avec # ci-dessus, c'est qu'elle ne crée pas les zéros de tête si le code hexadécimal final commence par des zéros. Par exemple, si le code hexadécimal est # 00a6b7, il le sortira en tant que # a6b7, ce qui ne fonctionnera pas s'il est utilisé en tant que CSS. Vous pouvez corriger cela en remplaçant la ligne de retour par ceci: var string = "000000" + (g | (b << 8) | (r << 16)). ToString (16); return (usePound? "#": "") + string.substr (string.length-6);
Rafael Levy

Réponses:


877

Eh bien, cette réponse est devenue sa propre bête. Beaucoup de nouvelles versions, ça devenait stupide depuis longtemps. Un grand merci à tous les très nombreux contributeurs à cette réponse. Mais, afin de rester simple pour les masses. J'ai archivé toutes les versions / l'historique de l'évolution de cette réponse sur mon github . Et j'ai tout recommencé sur StackOverflow ici avec la dernière version. Un merci spécial à Mike «Pomax» Kamermans pour cette version. Il m'a donné le nouveau calcul.


Cette fonction ( pSBC) prendra une couleur Web HEX ou RVB. pSBCpeut l'ombrer plus sombre ou plus clair, ou le mélanger avec une deuxième couleur, et peut également le passer à travers mais convertir de Hex en RGB (Hex2RGB) ou RGB en Hex (RGB2Hex). Le tout sans même savoir quel format de couleur vous utilisez.

Cela fonctionne très rapidement, probablement le plus rapide, surtout compte tenu de ses nombreuses fonctionnalités. Cela a pris beaucoup de temps. Voir toute l'histoire sur mon github . Si vous voulez le moyen le plus petit et le plus rapide possible de teinter ou de mélanger, consultez les Micro Fonctions ci-dessous et utilisez l'un des démons de vitesse à 2 lignes. Ils sont parfaits pour les animations intenses, mais cette version ici est assez rapide pour la plupart des animations.

Cette fonction utilise le mélange de journaux ou le mélange linéaire. Cependant, il ne se convertit PAS en HSL pour éclaircir ou assombrir correctement une couleur. Par conséquent, les résultats de cette fonction seront différents de ceux des fonctions beaucoup plus grandes et beaucoup plus lentes qui utilisent HSL.

jsFiddle avec pSBC

github> pSBC Wiki

Fonctionnalités:

  • Détecte et accepte automatiquement les couleurs Hex standard sous forme de chaînes. Par exemple: "#AA6622"ou "#bb551144".
  • Détecte automatiquement et accepte les couleurs RVB standard sous forme de chaînes. Par exemple: "rgb(123,45,76)"ou "rgba(45,15,74,0.45)".
  • Nuances de couleurs au blanc ou au noir en pourcentage.
  • Mélange les couleurs ensemble en pourcentage.
  • Fait la conversion Hex2RGB et RGB2Hex en même temps ou en solo.
  • Accepte les codes de couleur HEX à 3 chiffres (ou 4 chiffres avec alpha) sous la forme #RGB (ou #RGBA). Cela les élargira. Par exemple:"#C41" devient "#CC4411".
  • Accepte et (linéaire) mélange les canaux alpha. Si la c0couleur (de) ou la couleur c1(de) a un canal alpha, alors la couleur renvoyée aura un canal alpha. Si les deux couleurs ont un canal alpha, la couleur renvoyée sera un mélange linéaire des deux canaux alpha en utilisant le pourcentage donné (comme s'il s'agissait d'un canal de couleur normal). Si une seule des deux couleurs a un canal alpha, cet alpha sera simplement transmis à la couleur retournée. Cela permet de mélanger / ombrer une couleur transparente tout en maintenant le niveau de transparence. Ou, si les niveaux de transparence doivent également se fondre, assurez-vous que les deux couleurs ont des alphas. Lors de l'ombrage, il passera directement par le canal alpha. Si vous voulez un ombrage de base qui ombrage également le canal alpha, utilisez rgb(0,0,0,1)ou rgb(255,255,255,1)commec1(à) couleur (ou leurs équivalents hexadécimaux). Pour les couleurs RVB, le canal alpha de la couleur renvoyée sera arrondi à 3 décimales.
  • Les conversions RGB2Hex et Hex2RGB sont implicites lors de l'utilisation du mélange. Quelle que soit la c0couleur (de); la couleur renvoyée sera toujours au format de couleur de la couleur c1(à), s'il en existe une. S'il n'y a pas de c1(à) couleur, alors passez 'c'comme c1couleur et il nuancera et convertira quelle que soit la c0couleur. Si seule la conversion est souhaitée, transmettez 0également le pourcentage ( p). Si la c1couleur est omise ou si un non stringest transmis, il ne sera pas converti.
  • Une fonction secondaire est également ajoutée au global. pSBCrpeut être passé une couleur hexadécimale ou RVB et il renvoie un objet contenant ces informations de couleur. Il se présente sous la forme: {r: XXX, g: XXX, b: XXX, a: X.XXX}. Où .r, .get .bont une plage de 0 à 255. Et quand il n'y a pas d'alpha: .aest -1. Autrement:.a a une plage de 0,000 à 1.000.
  • Pour une sortie RVB, il émet en sortie rgba()sur rgb()lorsqu'une couleur avec un canal alpha a été passé dans c0(de) et / ouc1 (à).
  • La vérification des erreurs mineures a été ajoutée. Ce n'est pas parfait. Il peut encore planter ou créer du charabia. Mais ça va attraper des trucs. Fondamentalement, si la structure est incorrecte à certains égards ou si le pourcentage n'est pas un nombre ou hors de portée, il reviendra null. Un exemple:, pSBC(0.5,"salt") == nulloù comme il le pense #saltest une couleur valide. Supprimez les quatre lignes qui se terminent par return null;pour supprimer cette fonction et la rendre plus rapide et plus petite.
  • Utilise le mélange de journaux. Passez truepour l(le 4ème paramètre) pour utiliser le mélange linéaire.

Code:

// Version 4.0
const pSBC=(p,c0,c1,l)=>{
    let r,g,b,P,f,t,h,i=parseInt,m=Math.round,a=typeof(c1)=="string";
    if(typeof(p)!="number"||p<-1||p>1||typeof(c0)!="string"||(c0[0]!='r'&&c0[0]!='#')||(c1&&!a))return null;
    if(!this.pSBCr)this.pSBCr=(d)=>{
        let n=d.length,x={};
        if(n>9){
            [r,g,b,a]=d=d.split(","),n=d.length;
            if(n<3||n>4)return null;
            x.r=i(r[3]=="a"?r.slice(5):r.slice(4)),x.g=i(g),x.b=i(b),x.a=a?parseFloat(a):-1
        }else{
            if(n==8||n==6||n<4)return null;
            if(n<6)d="#"+d[1]+d[1]+d[2]+d[2]+d[3]+d[3]+(n>4?d[4]+d[4]:"");
            d=i(d.slice(1),16);
            if(n==9||n==5)x.r=d>>24&255,x.g=d>>16&255,x.b=d>>8&255,x.a=m((d&255)/0.255)/1000;
            else x.r=d>>16,x.g=d>>8&255,x.b=d&255,x.a=-1
        }return x};
    h=c0.length>9,h=a?c1.length>9?true:c1=="c"?!h:false:h,f=this.pSBCr(c0),P=p<0,t=c1&&c1!="c"?this.pSBCr(c1):P?{r:0,g:0,b:0,a:-1}:{r:255,g:255,b:255,a:-1},p=P?p*-1:p,P=1-p;
    if(!f||!t)return null;
    if(l)r=m(P*f.r+p*t.r),g=m(P*f.g+p*t.g),b=m(P*f.b+p*t.b);
    else r=m((P*f.r**2+p*t.r**2)**0.5),g=m((P*f.g**2+p*t.g**2)**0.5),b=m((P*f.b**2+p*t.b**2)**0.5);
    a=f.a,t=t.a,f=a>=0||t>=0,a=f?a<0?t:t<0?a:a*P+t*p:0;
    if(h)return"rgb"+(f?"a(":"(")+r+","+g+","+b+(f?","+m(a*1000)/1000:"")+")";
    else return"#"+(4294967296+r*16777216+g*65536+b*256+(f?m(a*255):0)).toString(16).slice(1,f?undefined:-2)
}

Usage:

// Setup:

let color1 = "rgb(20,60,200)";
let color2 = "rgba(20,60,200,0.67423)";
let color3 = "#67DAF0";
let color4 = "#5567DAF0";
let color5 = "#F3A";
let color6 = "#F3A9";
let color7 = "rgb(200,60,20)";
let color8 = "rgba(200,60,20,0.98631)";

// Tests:

/*** Log Blending ***/
// Shade (Lighten or Darken)
pSBC ( 0.42, color1 ); // rgb(20,60,200) + [42% Lighter] => rgb(166,171,225)
pSBC ( -0.4, color5 ); // #F3A + [40% Darker] => #c62884
pSBC ( 0.42, color8 ); // rgba(200,60,20,0.98631) + [42% Lighter] => rgba(225,171,166,0.98631)

// Shade with Conversion (use "c" as your "to" color)
pSBC ( 0.42, color2, "c" ); // rgba(20,60,200,0.67423) + [42% Lighter] + [Convert] => #a6abe1ac

// RGB2Hex & Hex2RGB Conversion Only (set percentage to zero)
pSBC ( 0, color6, "c" ); // #F3A9 + [Convert] => rgba(255,51,170,0.6)

// Blending
pSBC ( -0.5, color2, color8 ); // rgba(20,60,200,0.67423) + rgba(200,60,20,0.98631) + [50% Blend] => rgba(142,60,142,0.83)
pSBC ( 0.7, color2, color7 ); // rgba(20,60,200,0.67423) + rgb(200,60,20) + [70% Blend] => rgba(168,60,111,0.67423)
pSBC ( 0.25, color3, color7 ); // #67DAF0 + rgb(200,60,20) + [25% Blend] => rgb(134,191,208)
pSBC ( 0.75, color7, color3 ); // rgb(200,60,20) + #67DAF0 + [75% Blend] => #86bfd0

/*** Linear Blending ***/
// Shade (Lighten or Darken)
pSBC ( 0.42, color1, false, true ); // rgb(20,60,200) + [42% Lighter] => rgb(119,142,223)
pSBC ( -0.4, color5, false, true ); // #F3A + [40% Darker] => #991f66
pSBC ( 0.42, color8, false, true ); // rgba(200,60,20,0.98631) + [42% Lighter] => rgba(223,142,119,0.98631)

// Shade with Conversion (use "c" as your "to" color)
pSBC ( 0.42, color2, "c", true ); // rgba(20,60,200,0.67423) + [42% Lighter] + [Convert] => #778edfac

// RGB2Hex & Hex2RGB Conversion Only (set percentage to zero)
pSBC ( 0, color6, "c", true ); // #F3A9 + [Convert] => rgba(255,51,170,0.6)

// Blending
pSBC ( -0.5, color2, color8, true ); // rgba(20,60,200,0.67423) + rgba(200,60,20,0.98631) + [50% Blend] => rgba(110,60,110,0.83)
pSBC ( 0.7, color2, color7, true ); // rgba(20,60,200,0.67423) + rgb(200,60,20) + [70% Blend] => rgba(146,60,74,0.67423)
pSBC ( 0.25, color3, color7, true ); // #67DAF0 + rgb(200,60,20) + [25% Blend] => rgb(127,179,185)
pSBC ( 0.75, color7, color3, true ); // rgb(200,60,20) + #67DAF0 + [75% Blend] => #7fb3b9

/*** Other Stuff ***/
// Error Checking
pSBC ( 0.42, "#FFBAA" ); // #FFBAA + [42% Lighter] => null  (Invalid Input Color)
pSBC ( 42, color1, color5 ); // rgb(20,60,200) + #F3A + [4200% Blend] => null  (Invalid Percentage Range)
pSBC ( 0.42, {} ); // [object Object] + [42% Lighter] => null  (Strings Only for Color)
pSBC ( "42", color1 ); // rgb(20,60,200) + ["42"] => null  (Numbers Only for Percentage)
pSBC ( 0.42, "salt" ); // salt + [42% Lighter] => null  (A Little Salt is No Good...)

// Error Check Fails (Some Errors are not Caught)
pSBC ( 0.42, "#salt" ); // #salt + [42% Lighter] => #a5a5a500  (...and a Pound of Salt is Jibberish)

// Ripping
pSBCr ( color4 ); // #5567DAF0 + [Rip] => [object Object] => {'r':85,'g':103,'b':218,'a':0.941}

L'image ci-dessous aidera à montrer la différence entre les deux méthodes de mélange:


Micro fonctions

Si vous voulez vraiment de la vitesse et de la taille, vous devrez utiliser RGB et non HEX. RVB est plus simple et plus simple, HEX écrit trop lentement et se décline en trop de saveurs pour un simple deux lignes (IE. Il pourrait s'agir d'un code HEX à 3, 4, 6 ou 8 chiffres). Vous devrez également sacrifier certaines fonctionnalités, pas de vérification d'erreur, ni HEX2RGB ni RGB2HEX. De plus, vous devrez choisir une fonction spécifique (en fonction de son nom de fonction ci-dessous) pour les calculs de mélange de couleurs, et si vous souhaitez un ombrage ou un mélange. Ces fonctions prennent en charge les canaux alpha. Et lorsque les deux couleurs d'entrée ont des alphas, Linear les mélange. Si une seule des deux couleurs a un alpha, il la transmettra directement à la couleur résultante. Voici deux fonctions de revêtement incroyablement rapides et petites:

const RGB_Linear_Blend=(p,c0,c1)=>{
    var i=parseInt,r=Math.round,P=1-p,[a,b,c,d]=c0.split(","),[e,f,g,h]=c1.split(","),x=d||h,j=x?","+(!d?h:!h?d:r((parseFloat(d)*P+parseFloat(h)*p)*1000)/1000+")"):")";
    return"rgb"+(x?"a(":"(")+r(i(a[3]=="a"?a.slice(5):a.slice(4))*P+i(e[3]=="a"?e.slice(5):e.slice(4))*p)+","+r(i(b)*P+i(f)*p)+","+r(i(c)*P+i(g)*p)+j;
}

const RGB_Linear_Shade=(p,c)=>{
    var i=parseInt,r=Math.round,[a,b,c,d]=c.split(","),P=p<0,t=P?0:255*p,P=P?1+p:1-p;
    return"rgb"+(d?"a(":"(")+r(i(a[3]=="a"?a.slice(5):a.slice(4))*P+t)+","+r(i(b)*P+t)+","+r(i(c)*P+t)+(d?","+d:")");
}

const RGB_Log_Blend=(p,c0,c1)=>{
    var i=parseInt,r=Math.round,P=1-p,[a,b,c,d]=c0.split(","),[e,f,g,h]=c1.split(","),x=d||h,j=x?","+(!d?h:!h?d:r((parseFloat(d)*P+parseFloat(h)*p)*1000)/1000+")"):")";
    return"rgb"+(x?"a(":"(")+r((P*i(a[3]=="a"?a.slice(5):a.slice(4))**2+p*i(e[3]=="a"?e.slice(5):e.slice(4))**2)**0.5)+","+r((P*i(b)**2+p*i(f)**2)**0.5)+","+r((P*i(c)**2+p*i(g)**2)**0.5)+j;
}

const RGB_Log_Shade=(p,c)=>{
    var i=parseInt,r=Math.round,[a,b,c,d]=c.split(","),P=p<0,t=P?0:p*255**2,P=P?1+p:1-p;
    return"rgb"+(d?"a(":"(")+r((P*i(a[3]=="a"?a.slice(5):a.slice(4))**2+t)**0.5)+","+r((P*i(b)**2+t)**0.5)+","+r((P*i(c)**2+t)**0.5)+(d?","+d:")");
}

Vous voulez plus d'informations? Lisez l'intégralité du texte sur github .

PT

(Ps Si quelqu'un a le calcul pour une autre méthode de mélange, veuillez partager.)


8
Une version PHP pour ceux qui en ont besoin: gist.github.com/chaoszcat/5325115#file-gistfile1-php
Lionel Chan

28
J'ai utilisé TinyColor -tinycolor.darken(color,amount);
FWrnr le

4
Great post ... :) ... vient de créer l'extension Swift: gist.github.com/matejukmar/1da47f7a950d1ba68a95
Matej Ukmar

2
Voici la version PHP de la version mise à jour de shadowColor2: function shadeColor2($color, $percent) { $color = str_replace("#", "", $color); $t=$percent<0?0:255; $p=$percent<0?$percent*-1:$percent; $RGB = str_split($color, 2); $R=hexdec($RGB[0]); $G=hexdec($RGB[1]); $B=hexdec($RGB[2]); return '#'.substr(dechex(0x1000000+(round(($t-$R)*$p)+$R)*0x10000+(round(($t-$G)*$p)+$G)*0x100+(round(($t-$B)*$p)+$B)),1); }
Kevin M

2
Désolé, j'ai apparemment manqué ce point. Il y a peut-être deux raisons. La première et évidente est que j'utilise Math.Round et que vous n'utilisez pas de nombres décimaux pour une coloration précise (les couleurs n'ont pas de décimales en hexadécimal). Par exemple, si le canal rouge est 8, ajoutez 10%vous obtenez à 8.8quels tours 9. Ensuite, 9.09%retirez de 9et vous obtenez 8.1819. Qui arrondit 8donc c'est un mauvais exemple. Mais il illustre encore que vous prenez 9.09%des 9et non 8.8. Il pourrait donc y avoir des chiffres qui ne correspondent pas exactement à mon exemple ici.
Pimp Trizkit

122

J'ai fait une solution qui fonctionne très bien pour moi:

function shadeColor(color, percent) {

    var R = parseInt(color.substring(1,3),16);
    var G = parseInt(color.substring(3,5),16);
    var B = parseInt(color.substring(5,7),16);

    R = parseInt(R * (100 + percent) / 100);
    G = parseInt(G * (100 + percent) / 100);
    B = parseInt(B * (100 + percent) / 100);

    R = (R<255)?R:255;  
    G = (G<255)?G:255;  
    B = (B<255)?B:255;  

    var RR = ((R.toString(16).length==1)?"0"+R.toString(16):R.toString(16));
    var GG = ((G.toString(16).length==1)?"0"+G.toString(16):G.toString(16));
    var BB = ((B.toString(16).length==1)?"0"+B.toString(16):B.toString(16));

    return "#"+RR+GG+BB;
}

Exemple éclaircir:

shadeColor("#63C6FF",40);

Exemple assombrir:

shadeColor("#63C6FF",-40);

4
Sympa, j'aime le pourcentage! +1 Tho, je ferais peut-être R = ((R<255)?R:255).toString(16);alors R = R.length==1 ? "0"+R : Rpour la vitesse. Et je ne suis pas sûr du point de la toUpperCase?
Pimp Trizkit

C'est inutile. J'ajoute seulement cela pour une jolie impression pendant le test. Je vais éditer ça.
Pablo

Très agréable. Cependant, 100% plus léger ne devrait-il pas devenir entièrement blanc et 100% sombre toujours noir, quelle que soit la couleur? il semble que -100 ne rende aucune couleur noire, mais 100 (positif) ne la rend pas entièrement blanche.
Kevin M

4
ne fonctionne pas avec des couleurs unies comme # ff0000, # 00ff00, # 0000ff
Hitori

Pour le faire fonctionner avec la couleur noire, je viens de faire ce hack var R = parseInt(color.substring(1, 3), 16) var G = parseInt(color.substring(3, 5), 16) var B = parseInt(color.substring(5, 7), 16) if (R == 0) R = 32; if (G == 0) G = 32; if (B == 0) B = 32;
Irfan Raza

21

Voici une doublure super simple basée sur la réponse d'Eric

function adjust(color, amount) {
    return '#' + color.replace(/^#/, '').replace(/../g, color => ('0'+Math.min(255, Math.max(0, parseInt(color, 16) + amount)).toString(16)).substr(-2));
}

Exemples:

adjust('#ffffff', -20) => "#ebebeb"
adjust('000000', 20) => "#141414"

7
"super simple".
Andrew

5

C'est ce que j'ai utilisé en fonction de votre fonction. Je préfère utiliser les étapes par rapport au pourcentage car c'est plus intuitif pour moi.

Par exemple, 20% d'une valeur de 200 bleus est très différent de 20% d'une valeur de 40 bleus.

Quoi qu'il en soit, voici ma modification, merci pour votre fonction d'origine.

function adjustBrightness(col, amt) {

    var usePound = false;

    if (col[0] == "#") {
        col = col.slice(1);
        usePound = true;
    }

    var R = parseInt(col.substring(0,2),16);
    var G = parseInt(col.substring(2,4),16);
    var B = parseInt(col.substring(4,6),16);

    // to make the colour less bright than the input
    // change the following three "+" symbols to "-"
    R = R + amt;
    G = G + amt;
    B = B + amt;

    if (R > 255) R = 255;
    else if (R < 0) R = 0;

    if (G > 255) G = 255;
    else if (G < 0) G = 0;

    if (B > 255) B = 255;
    else if (B < 0) B = 0;

    var RR = ((R.toString(16).length==1)?"0"+R.toString(16):R.toString(16));
    var GG = ((G.toString(16).length==1)?"0"+G.toString(16):G.toString(16));
    var BB = ((B.toString(16).length==1)?"0"+B.toString(16):B.toString(16));

    return (usePound?"#":"") + RR + GG + BB;

}

J'ai trouvé cela beaucoup plus utile que la première réponse parce que la première réponse rendait mes couleurs très intenses au lieu d'être juste plus sombres. Cheers Eric
Worm

4

J'ai essayé votre fonction et il y avait un petit bug: si une valeur finale 'r' est à 1 chiffre seulement, le résultat apparaît comme: 'a0a0a' quand la bonne valeur est '0a0a0a', par exemple. Je l'ai juste corrigé rapidement en ajoutant ceci au lieu de votre retour:

var rStr = (r.toString(16).length < 2)?'0'+r.toString(16):r.toString(16);
var gStr = (g.toString(16).length < 2)?'0'+g.toString(16):g.toString(16);
var bStr = (b.toString(16).length < 2)?'0'+b.toString(16):b.toString(16);

return (usePound?"#":"") + rStr + gStr + bStr;

Ce n'est peut-être pas si agréable mais ça fait le travail. Grande fonction, BTW. Juste ce dont j'avais besoin. :)


1
Merci pour le débogage et le compliment! Dommage que ce ne soit pas une réponse à la question de savoir s'il existe ou non un moyen plus rapide, ce qui est ma principale question. Comme peut-être un utilisant toutes les conversions hexadécimales et aucune base. Je suppose que tu m'as dit si j'avais le bon code (+1). Malheureusement, le correctif a ajouté beaucoup plus de frais généraux (maintenant votre appel à String 6 fois) et un peu moins de KISS. Il serait peut-être plus rapide de vérifier si le nombre base10 est de 15 ou moins, avant la conversion base16. Mais j'aime!
Pimp Trizkit

4

avez-vous pensé à une conversion rgb> hsl? alors il suffit de déplacer la luminosité de haut en bas? c'est comme ça que j'irais.

Un rapide coup d'œil à certains algorithmes m'a permis d'accéder aux sites suivants.

PHP: http://serennu.com/colour/rgbtohsl.php

Javascript: http://mjijackson.com/2008/02/rgb-to-hsl-and-rgb-to-hsv-color-model-conversion-algorithms-in-javascript

MODIFIER le lien ci-dessus n'est plus valide. Vous pouvez afficher git hub pour la source de la page ou l' essentiel

Alternativement, une autre question StackOverflow pourrait être un bon endroit pour chercher.


Même si ce n'est pas le bon choix pour l'OP, ce qui suit est une approximation du code que je proposais à l'origine. (En supposant que vous ayez des fonctions de conversion rgb / hsl)

var SHADE_SHIFT_AMOUNT = 0.1; 

function lightenShade(colorValue)
{
    if(colorValue && colorValue.length >= 6)
    {
        var redValue = parseInt(colorValue.slice(-6,-4), 16);
        var greenValue = parseInt(colorValue.slice(-4,-2), 16);
        var blueValue = parseInt(colorValue.slice(-2), 16);

        var hsl = rgbToHsl(redValue, greenValue, blueValue);
        hsl[2]= Math.min(hsl[2] + SHADE_SHIFT_AMOUNT, 1);
        var rgb = hslToRgb(hsl[0], hsl[1], hsl[2]);
        return "#" + rgb[0].toString(16) + rgb[1].toString(16) + rgb[2].toString(16);
    }
    return null;
}

function darkenShade(colorValue)
{
    if(colorValue && colorValue.length >= 6)
    {
        var redValue = parseInt(colorValue.slice(-6,-4), 16);
        var greenValue = parseInt(colorValue.slice(-4,-2), 16);
        var blueValue = parseInt(colorValue.slice(-2), 16);

        var hsl = rgbToHsl(redValue, greenValue, blueValue);
        hsl[2]= Math.max(hsl[2] - SHADE_SHIFT_AMOUNT, 0);
        var rgb = hslToRgb(hsl[0], hsl[1], hsl[2]);
        return "#" + rgb[0].toString(16) + rgb[1].toString(16) + rgb[2].toString(16);
    }
    return null;
}

Cela suppose:

  1. Vous avez des fonctions hslToRgbet rgbToHsl.
  2. Le paramètre colorValueest une chaîne sous la forme #RRGGBB

Bien que si nous discutons de CSS, il existe une syntaxe pour spécifier hsl / hsla pour IE9 / Chrome / Firefox.


Intéressant, mais ne devrais-je pas alors convertir une chaîne hexadécimale en RVB en HSL? On dirait que c'est plus compliqué. Peut-être que je manque quelque chose. Mais, je cherche une manière KISS de le faire, aussi vite que possible (temps d'exécution). Je me sens idéalement, si je pouvais tout faire en hex, ce serait le plus rapide. Mais, la solution que j'ai développée ici implique d'aller en rgb pour pouvoir ajouter un montant incrémentiel.
Pimp Trizkit

Oui, je suppose que ce serait plus lent, plus compliqué et si vous n'utilisez pas de conversion rgb en hsl ailleurs, ce ne serait probablement pas la solution la plus simpliste. Ce serait cependant plus précis que d'ajouter aux valeurs RVB, même si je ne suis pas moi-même une personne de couleur. Tout dépend de la précision que vous voulez être, je suppose.
James Khoury

Quelle est la perte de précision que vous mentionnez? Je suppose que vous voulez dire que toutes les couleurs [web] ne sont pas accessibles avec rgb ou quelque chose?
Pimp Trizkit

Comme je l'ai dit, je ne sais pas grand-chose sur la couleur: wiki Color Theory
James Khoury

@Pimp Trizkit: C'est moins précis parce que (et ce n'est que ma théorie ... je ne suis pas un expert en couleurs), vous changez chaque canal de la même quantité, peu importe la quantité de cette couleur au départ. Je pense que cela entraînerait une diminution de la saturation car vous rapprochez les canaux les uns des autres (en pourcentage). Bien sûr, si vous débordez / débordez, c'est inévitable de toute façon.
Matthew Crumley

2

Version C # ... notez que je reçois des chaînes de couleur dans ce format # FF12AE34, et que je dois découper le #FF.

    private string GetSmartShadeColorByBase(string s, float percent)
    {
        if (string.IsNullOrEmpty(s))
            return "";
        var r = s.Substring(3, 2);
        int rInt = int.Parse(r, NumberStyles.HexNumber);
        var g = s.Substring(5, 2);
        int gInt = int.Parse(g, NumberStyles.HexNumber);
        var b = s.Substring(7, 2);
        int bInt = int.Parse(b, NumberStyles.HexNumber);

        var t = percent < 0 ? 0 : 255;
        var p = percent < 0 ? percent*-1 : percent;

        int newR = Convert.ToInt32(Math.Round((t - rInt) * p) + rInt);
        var newG = Convert.ToInt32(Math.Round((t - gInt) * p) + gInt);
        var newB = Convert.ToInt32(Math.Round((t - bInt) * p) + bInt);

        return String.Format("#{0:X2}{1:X2}{2:X2}", newR, newG, newB);
    }

5
Jamais utilisé C # auparavant, mais il semble que les trois dernières déclarations de variables soient bizarres. Un intet deux varspour le même type de données.
Pimp Trizkit du

4
Le mot-clé var en C # signifie que le compilateur infère le type au moment de la compilation. Ainsi, dans l'exemple ci-dessus, int et var définissent une variable du même type - int. Ceci est utile si vous avez un nom de type long ou si vous souhaitez référencer un type anonyme. C'est bizarre parce que user1618171 a mélangé deux styles de déclaration de variable - probablement une faute de frappe.
Daniel James Bryars

2

Je voulais changer une couleur à un niveau de luminosité spécifique - quelle que soit la luminosité de la couleur avant - voici une fonction JS simple qui semble bien fonctionner, même si je suis sûr qu'elle pourrait être plus courte

function setLightPercentage(col: any, p: number) {
    const R = parseInt(col.substring(1, 3), 16);
    const G = parseInt(col.substring(3, 5), 16);
    const B = parseInt(col.substring(5, 7), 16);
    const curr_total_dark = (255 * 3) - (R + G + B);

    // calculate how much of the current darkness comes from the different channels
    const RR = ((255 - R) / curr_total_dark);
    const GR = ((255 - G) / curr_total_dark);
    const BR = ((255 - B) / curr_total_dark);

    // calculate how much darkness there should be in the new color
    const new_total_dark = ((255 - 255 * (p / 100)) * 3);

    // make the new channels contain the same % of available dark as the old ones did
    const NR = 255 - Math.round(RR * new_total_dark);
    const NG = 255 - Math.round(GR * new_total_dark);
    const NB = 255 - Math.round(BR * new_total_dark);

    const RO = ((NR.toString(16).length === 1) ? "0" + NR.toString(16) : NR.toString(16));
    const GO = ((NG.toString(16).length === 1) ? "0" + NG.toString(16) : NG.toString(16));
    const BO = ((NB.toString(16).length === 1) ? "0" + NB.toString(16) : NB.toString(16));

    return "#" + RO + GO + BO;}

Coolio! Je suppose que cela pa une portée 0-100? Je ne sais même pas comment définir correctement la luminosité en RVB, c'est une chose HSL. Par exemple, est #FF00FFplus lumineux que #FF0000? Si c'est le cas, cela impliquerait que le magenta est deux fois plus brillant que le rouge. Par conséquent, le test rouge pur est utilisé. Passez en rouge pur #FF0000, réglé à 50% de luminosité, et nous y arrivons #FF4040, est-ce vrai? J'aurais deviné faire une luminosité rouge de 50%, nous deviendrions plus sombres, vu que sa luminosité est déjà entièrement .. comme dans #800000ou une luminosité de 150% #FF8080. Le rose est-il un rouge plus vif? ou le rouge est-il déjà pleinement lumineux?
Pimp Trizkit

Vous avez raison - j'aurais dû mentionner que p doit être compris entre 1 et 100!
Torbjörn Josefsson

# FF00FF a 255 comme valeur dans le canal rouge, 0 dans le canal vert et 255 dans le canal bleu. Plus les valeurs combinées dans les canaux sont élevées, plus la luminosité de la couleur est élevée. Le nombre p indique que nous voulons que la nouvelle couleur soit 50% aussi lumineuse que la couleur d'origine. Je ne suis pas à 100% que # FF4040 est la bonne réponse à "50% aussi lumineux que possible Rouge". Produire des nuances plus sombres (avec, dans ce cas, une valeur inférieure dans le canal rouge) nécessiterait une modification
Torbjörn Josefsson

Oui, je viens de souligner l'ambiguïté de parler de luminosité en RVB. S'il est converti en HSL, le Lcanal est littéralement la luminosité. Mon problème [mental personnel] ici est que, pour moi, il #FF0000est parfaitement clair. Et #FF4040est plus léger mais pas plus lumineux .... pour moi, plus léger signifie plus proche du blanc, comme le rose. Et la luminosité est la quantité de son obtenu, et son plein rouge, donc rouge, est pleinement lumineux. Par conséquent, #FF0000ne peut pas être rendu plus brillant .. mais plutôt .. plus léger ... peut-être que je suis juste un monstre, lol !! Je ne connais vraiment pas la théorie des couleurs, alors, je parle vraiment de mon ...
Pimp Trizkit

Mais je sais que lorsque je change la luminosité de mon moniteur, les rouges ne deviennent pas roses ... pour moi. C'est donc probablement là que j'ai commencé ma logique.
Pimp Trizkit

1

La méthode suivante vous permettra d'éclaircir ou d'assombrir la valeur d'exposition d'une chaîne de couleur hexadécimale (Hex):

private static string GetHexFromRGB(byte r, byte g, byte b, double exposure)
{
    exposure = Math.Max(Math.Min(exposure, 1.0), -1.0);
    if (exposure >= 0)
    {
        return "#"
            + ((byte)(r + ((byte.MaxValue - r) * exposure))).ToString("X2")
            + ((byte)(g + ((byte.MaxValue - g) * exposure))).ToString("X2")
            + ((byte)(b + ((byte.MaxValue - b) * exposure))).ToString("X2");
    }
    else
    {
        return "#"
            + ((byte)(r + (r * exposure))).ToString("X2")
            + ((byte)(g + (g * exposure))).ToString("X2")
            + ((byte)(b + (b * exposure))).ToString("X2");
    }

}

Pour la dernière valeur de paramètre dans GetHexFromRGB (), passez une valeur double quelque part entre -1 et 1 (-1 est noir, 0 est inchangé, 1 est blanc):

// split color (#e04006) into three strings
var r = Convert.ToByte("e0", 16);
var g = Convert.ToByte("40", 16);
var b = Convert.ToByte("06", 16);

GetHexFromRGB(r, g, b, 0.25);  // Lighten by 25%;

0

Comment colorer une teinte simple en PHP?

<?php
function shadeColor ($color='#cccccc', $percent=-25) {

  $color = Str_Replace("#",Null,$color);

  $r = Hexdec(Substr($color,0,2));
  $g = Hexdec(Substr($color,2,2));
  $b = Hexdec(Substr($color,4,2));

  $r = (Int)($r*(100+$percent)/100);
  $g = (Int)($g*(100+$percent)/100);
  $b = (Int)($b*(100+$percent)/100);

  $r = Trim(Dechex(($r<255)?$r:255));  
  $g = Trim(Dechex(($g<255)?$g:255));  
  $b = Trim(Dechex(($b<255)?$b:255));

  $r = ((Strlen($r)==1)?"0{$r}":$r);
  $g = ((Strlen($g)==1)?"0{$g}":$g);
  $b = ((Strlen($b)==1)?"0{$b}":$b);

  return (String)("#{$r}{$g}{$b}");
}

echo shadeColor(); // #999999

Ceci est une version php de la réponse de Pablo. Malheureusement, c'est plus long et plus lent que la solution finale et il n'éclaircit pas les couleurs avec précision. Cela les obscurcit exactement. Testez avec du rouge pur (# FF0000), un éclaircissement de 25% devrait être (# FF4040). Consultez la fin de ma réponse pour la version PHP de Kevin M de la solution finale v2.
Pimp Trizkit

0

J'ai fait un portage de l'excellente bibliothèque xcolor pour supprimer sa dépendance jQuery. Il y a une tonne de fonctions, y compris l'éclaircissement et l'assombrissement des couleurs.

Vraiment, la conversion hexadécimale en RVB est une fonction complètement distincte de l'éclaircissement ou de l'assombrissement des couleurs. Gardez les choses au sec, s'il vous plaît. Dans tous les cas, une fois que vous avez une couleur RVB, vous pouvez simplement ajouter la différence entre le niveau d'éclairage souhaité et le niveau d'éclairage que vous avez à chacune des valeurs RVB:

var lightness = function(level) {
    if(level === undefined) {
        return Math.max(this.g,this.r,this.b)
    } else {
        var roundedLevel = Math.round(level) // fractions won't work here
        var levelChange = roundedLevel - this.lightness()

        var r = Math.max(0,this.r+levelChange)
        var g = Math.max(0,this.g+levelChange)
        var b = Math.max(0,this.b+levelChange)

        if(r > 0xff) r = 0xff
        if(g > 0xff) g = 0xff
        if(b > 0xff) b = 0xff

        return xolor({r: r, g: g, b: b})
    }
}

var lighter = function(amount) {
    return this.lightness(this.lightness()+amount)
}

Voir https://github.com/fresheneesz/xolor pour plus de la source.


Je n'ai pas encore analysé le code en ce qui concerne mon OP (vitesse / taille / précision). Mais au début, il y a quelques commentaires à faire: 1) Je conviens que la conversion hexadécimale en RVB peut être considérée comme une fonction complètement distincte. SI mon problème était destiné à être résolu avec une fonction sèche, ce qui n'était pas une exigence. L'intention ici était d'avoir une réponse (voir ma version 2) qui était super rapide et super minuscule (2 lignes!) Et une qui éclaircissait et assombrissait une couleur hexagonale ... spécifiquement ... en tant que autonome autonome une fonction. De sorte que, dans son utilisation finale, il s'agira d'un simple appel de fonction unique. <
Suite

2) Et le cas de la version 3, à la demande générale, est l'intention d'avoir une fonction universelle autonome complètement autonome, aussi rapide et aussi petite que possible, qui peut aveuglément prendre une couleur hexadécimale ou RVB et dans toutes leurs variations. Par conséquent, une conversion de hex en RVB est nécessaire. <suite>
Pimp Trizkit

3) Sur simple analyse du code. Il semble qu'il fonctionnerait beaucoup plus lentement et il est évidemment beaucoup plus grand que ma version 2 (qui est la vraie réponse à mon OP; la version 3 était pour les masses). Pour être honnête, je devrais comparer ce code avec ma version RVB 2 qui ne fait pas de conversion et semble répondre à votre point sur la sécheresse. Et à vrai dire, votre port n'est pas beaucoup plus simple à comprendre que mon 2 paquebot pour hex. Donc, bien que sa sécheuse, ce n'est pas vraiment beaucoup plus simple, le cas échéant. (la sécheresse n'a pas beaucoup aidé pour la compréhension) <suite.
Pimp Trizkit

4) Ma version RVB 2 est une fonction de ligne sans conversion 2 si vous le souhaitez. Ma solution particulière pour mon hex voulu d'origine OP. C'est pourquoi il existe deux types différents de version 2. Mais vous mentionnez le point sur la sécheresse et les conversions hexadécimales, nous nous concentrons donc vraiment sur la version 3. La version 3 est arrivée beaucoup plus tard; seulement après que la version 2 ait été populaire. <suite>
Pimp Trizkit

5) Bien que je convienne que la sécheresse contribue généralement à l'universalité. Et dans la plupart des cas, pour la compréhension. Malheureusement, cela a un coût dans cet exemple. Ces coûts sont que sa beaucoup plus grande et apparemment beaucoup plus lente et utilise apparemment plus de mémoire à la fois sur la pile (avec sa nature récursive) et globale (2 fonctions; par rapport à la v2).
Pimp Trizkit

0

Je souhaite depuis longtemps pouvoir produire des teintes / nuances de couleurs, voici ma solution JavaScript:

const varyHue = function (hueIn, pcIn) {
    const truncate = function (valIn) {
        if (valIn > 255) {
            valIn = 255;
        } else if (valIn < 0)  {
            valIn = 0;
        }
        return valIn;
    };

    let red   = parseInt(hueIn.substring(0, 2), 16);
    let green = parseInt(hueIn.substring(2, 4), 16);
    let blue  = parseInt(hueIn.substring(4, 6), 16);
    let pc    = parseInt(pcIn, 10);    //shade positive, tint negative
    let max   = 0;
    let dif   = 0;

    max = red;

    if (pc < 0) {    //tint: make lighter
        if (green < max) {
            max = green;
        }

        if (blue < max) {
            max = blue;
        }

        dif = parseInt(((Math.abs(pc) / 100) * (255 - max)), 10);

        return leftPad(((truncate(red + dif)).toString(16)), '0', 2)  + leftPad(((truncate(green + dif)).toString(16)), '0', 2) + leftPad(((truncate(blue + dif)).toString(16)), '0', 2);
    } else {    //shade: make darker
        if (green > max) {
            max = green;
        }

        if (blue > max) {
            max = blue;
        }

        dif = parseInt(((pc / 100) * max), 10);

        return leftPad(((truncate(red - dif)).toString(16)), '0', 2)  + leftPad(((truncate(green - dif)).toString(16)), '0', 2) + leftPad(((truncate(blue - dif)).toString(16)), '0', 2);
    }
};

Quelques exemples d'utilisation seraient utiles. Et peut-être une explication pour expliquer pourquoi cette version sur les autres. Cette version semble fonctionner considérablement plus lentement. Et c'est beaucoup plus long. Et il ne semble pas se colorer avec précision. Il ressemble à votre utilisation de LERP, ou quelque chose de similaire .. ce qui est bon. Malheureusement, ce n'est qu'à partir d'un canal, alors cette même valeur est utilisée sur tous les canaux. Ce n'est pas correct, afin d'obtenir une plus grande précision, vous devez LERP chaque canal individuellement. Comme ma réponse à cette question. De plus, il est plus petit et plus rapide et vérifie les erreurs et gère les RVB, et effectue les conversions, je pourrais continuer
Pimp Trizkit

Un exemple d'utilisation: varieHue ("6e124c", 77) où le premier argument est la couleur en hexadécimal et le second le pourcentage de changement. Un pourcentage de variation positif nuance (assombrit) tandis qu'une valeur négative teinte (éclaircit) le résultat. J'ai écrit la routine comme ma première tentative quelques heures seulement avant de tomber sur cette page et de la publier simplement par intérêt. Je ne savais pas que je devais améliorer vos efforts ou que j'avais besoin de votre approbation avant de le faire. C'est entièrement mon propre travail sans référence à personne d'autre. Je n'ai pas entendu parler de LERP, je vais le vérifier, merci pour la suggestion.
user2655360

Hé, eh bien, bien sûr, vous n'avez rien à faire! Et nous vous remercions tous pour vos efforts! Mes premières préoccupations principales étaient celles énumérées en premier. Essayer de vous aider avec votre réponse afin qu'elle puisse obtenir des votes. (montrer les usages et expliquer comment cela fonctionne, etc.) L'autre élément est évidemment une analyse rapide pour aider à approfondir les connaissances de chacun . Désolé, si cela semblait un peu agressif. Mais une autre suggestion est de lui faire accepter les #couleurs hexadécimales. Désolé si cela ressemblait à ... "approbation" ... Je l'ai vu comme un examen par les pairs. Si vous ne voulez pas que quelqu'un analyse votre code ou fasse des commentaires, je m'excuse.
Pimp Trizkit

0

Votre approche est ok :) Je simplifie un peu votre version la plus courte (pour le contrôle de la saturation, regardez ici )

(col,amt)=> (+('0x'+col)+amt*0x010101).toString(16).padStart(6,0)

Et version avec vérification du # et des gammes de couleurs


0

J'ai aussi fait un paquet simple. J'ai utilisé la convexité de IR ^ 3, bien sûr, les valeurs RVB sont en IN ^ 3 qui n'est pas convexe donc ce n'est pas vraiment parfait

Pour assombrir j'ai utilisé ce qui suit

for (let i = 0; i < rgb.length; i++) {
   rgb[i] = Math.floor(rgb[i] - ratio * rgb[i]);
}

Et pour alléger

for (let i = 0; i < rgb.length; i++) {
   rgb[i] = Math.ceil(rgb[i] + ratio * (255 - rgb[i]));
}

Voici le package https://github.com/MarchWorks/colortone

Démo https://colortone.now.sh/

avec la façon dont je fais les choses si vous passez un rapport de -1, vous vous retrouverez avec du noir, blanc si le rapport est 1. Passer 0 comme le rapport ne changera pas la couleur


0

J'en avais besoin en C #, cela peut aider les développeurs .net

public static string LightenDarkenColor(string color, int amount)
    {
        int colorHex = int.Parse(color, System.Globalization.NumberStyles.HexNumber);
        string output = (((colorHex & 0x0000FF) + amount) | ((((colorHex >> 0x8) & 0x00FF) + amount) << 0x8) | (((colorHex >> 0xF) + amount) << 0xF)).ToString("x6");
        return output;
    }

Vous avez converti la fonction "non fonctionnelle" qui ne traite pas des zéros non significatifs, et peut aller au-dessus de FF dans les sommes, = modifier la composante couleur ci-dessus ...
B. Allez

Lorsque j'ai essayé la fonction, elle n'a pas fonctionné en raison de valeurs non hexadécimales (16 = 0xF) et (8 = 0x8) et donne une couleur à 8 positions, mais maintenant elle fonctionne très bien
Nassim

avez-vous essayé d'augmenter à partir de FF? (disons à partir de 0xFFFFFF + 0x000004): votre code dépasse cette valeur maximale (disons à 0x1000003), au lieu de ne pas augmenter, et surtout de définir les 2 composants de couleur supérieurs à 00, ce qui est le plus grand changement qu'ils pourraient faire ...
B. Aller

vous avez raison, merci pour la remarque, sauf une entrée de limites entre fff et 000 ça marchera très bien.
Nassim
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.