web-dev-qa-db-fra.com

Comment générer des couleurs plus claires / plus foncées avec PHP?

J'ai une valeur hexadécimale d'une couleur, par exemple #202010.

Comment générer une nouvelle couleur plus claire ou plus foncée donnée en pourcentage (c.-à-d. 20% plus sombre) en PHP?

46
eni

Ajuster la couleur en pourcentage, comme dans l'exemple donné par Frxstrem, n'est pas idéal.

Si votre couleur est noire (0,0,0 en RVB), vous multipliez par zéro, ce qui ne produira aucun changement. Si votre couleur est gris foncé (par exemple 2,2,2 en RVB), vous devrez éclaircir de 50% pour passer à (3,3,3). D'un autre côté, si vous avez une couleur RVB de (100,100,100), l'ajustement de 50% vous fera passer à (150,150,150), ce qui est un changement beaucoup plus important en comparaison.

Une bien meilleure solution serait d'ajuster par étape/nombre (0-255) au lieu de pourcentage, par exemple comme ceci (code PHP):

Edit 2014-01-06: Nettoyé un peu le code.

function adjustBrightness($hex, $steps) {
    // Steps should be between -255 and 255. Negative = darker, positive = lighter
    $steps = max(-255, min(255, $steps));

    // Normalize into a six character long hex string
    $hex = str_replace('#', '', $hex);
    if (strlen($hex) == 3) {
        $hex = str_repeat(substr($hex,0,1), 2).str_repeat(substr($hex,1,1), 2).str_repeat(substr($hex,2,1), 2);
    }

    // Split into three parts: R, G and B
    $color_parts = str_split($hex, 2);
    $return = '#';

    foreach ($color_parts as $color) {
        $color   = hexdec($color); // Convert to decimal
        $color   = max(0,min(255,$color + $steps)); // Adjust color
        $return .= str_pad(dechex($color), 2, '0', STR_PAD_LEFT); // Make two char hex code
    }

    return $return;
}
119
Torkil Johnsen

Les réponses sont fausses.

L'utilisation du modèle RVB est une erreur conceptuelle.

Vous devez transformer la couleur de RVB (ou forme hexadécimale) en HSL.

C'est la teinte, la saturation, la légèreté.

Une fois que vous l'avez converti de RVB en HSL, pour éclaircir la couleur, vous ajustez simplement la valeur L (luminosité) de 10%. Ensuite, une fois que vous avez terminé, vous convertissez de HSL en RVB et vous avez terminé.

Voila!

RVB à HSV en PHP

22
Rod

Voici un exemple:

<?php
$color = '#aabbcc'; // The color we'll use

Extraire les couleurs. Je préférerais utiliser des expressions régulières, bien qu'il existe probablement d'autres moyens plus efficaces.

if(!preg_match('/^#?([0-9a-f]{2})([0-9a-f]{2})([0-9a-f]{2})$/i', $color, $parts))
  die("Not a value color");

Maintenant, nous avons du rouge dans $parts[1], vert dans $parts[2] et bleu en $parts[3]. Maintenant, convertissons-les d'hexadécimal en entiers:

$out = ""; // Prepare to fill with the results
for($i = 1; $i <= 3; $i++) {
  $parts[$i] = hexdec($parts[$i]);

Ensuite, nous les diminuerons de 20%:

  $parts[$i] = round($parts[$i] * 80/100); // 80/100 = 80%, i.e. 20% darker
  // Increase or decrease it to fit your needs

Maintenant, nous allons les reconvertir en hexadécimal et les ajouter à notre chaîne de sortie

  $out .= str_pad(dechex($parts[$i]), 2, '0', STR_PAD_LEFT);
}

Ensuite, ajoutez simplement un "#" au début de la chaîne, et c'est tout!

22
Frxstrem

La réponse de Torkil Johnsen est basée sur un pas fixe qui ne manipule pas seulement la luminosité mais modifie également légèrement la teinte. La méthode de Frxstrem a aussi des défauts, comme l'a noté Torkil Johnsen.

J'ai pris cette approche à partir d'un commentaire Github et amélioré le code. Cela fonctionne parfaitement dans tous les cas.

/**
 * Increases or decreases the brightness of a color by a percentage of the current brightness.
 *
 * @param   string  $hexCode        Supported formats: `#FFF`, `#FFFFFF`, `FFF`, `FFFFFF`
 * @param   float   $adjustPercent  A number between -1 and 1. E.g. 0.3 = 30% lighter; -0.4 = 40% darker.
 *
 * @return  string
 */
function adjustBrightness($hexCode, $adjustPercent) {
    $hexCode = ltrim($hexCode, '#');

    if (strlen($hexCode) == 3) {
        $hexCode = $hexCode[0] . $hexCode[0] . $hexCode[1] . $hexCode[1] . $hexCode[2] . $hexCode[2];
    }

    $hexCode = array_map('hexdec', str_split($hexCode, 2));

    foreach ($hexCode as & $color) {
        $adjustableLimit = $adjustPercent < 0 ? $color : 255 - $color;
        $adjustAmount = ceil($adjustableLimit * $adjustPercent);

        $color = str_pad(dechex($color + $adjustAmount), 2, '0', STR_PAD_LEFT);
    }

    return '#' . implode($hexCode);
}

Voici un exemple de résultat:

example

11
maliayas

Cela m'intéressait, mais ma question était comment ajouter une opacité à une couleur?

Je voulais une couleur qui s'estompe, pas plus claire. j'ai trouvé ceci: http://www.gidnetwork.com/b-135.html et cela a fonctionné très bien - du code posté depuis le site d'origine pour les lecteurs SO.

function color_blend_by_opacity( $foreground, $opacity, $background=null )
{
    static $colors_rgb=array(); // stores colour values already passed through the hexdec() functions below.
    $foreground = str_replace('#','',$foreground);
    if( is_null($background) )
        $background = 'FFFFFF'; // default background.

    $pattern = '~^[a-f0-9]{6,6}$~i'; // accept only valid hexadecimal colour values.
    if( !@preg_match($pattern, $foreground)  or  !@preg_match($pattern, $background) )
    {
        trigger_error( "Invalid hexadecimal colour value(s) found", E_USER_WARNING );
        return false;
    }

    $opacity = intval( $opacity ); // validate opacity data/number.
    if( $opacity>100  || $opacity<0 )
    {
        trigger_error( "Opacity percentage error, valid numbers are between 0 - 100", E_USER_WARNING );
        return false;
    }

    if( $opacity==100 )    // $transparency == 0
        return strtoupper( $foreground );
    if( $opacity==0 )    // $transparency == 100
        return strtoupper( $background );
    // calculate $transparency value.
    $transparency = 100-$opacity;

    if( !isset($colors_rgb[$foreground]) )
    { // do this only ONCE per script, for each unique colour.
        $f = array(  'r'=>hexdec($foreground[0].$foreground[1]),
                     'g'=>hexdec($foreground[2].$foreground[3]),
                     'b'=>hexdec($foreground[4].$foreground[5])    );
        $colors_rgb[$foreground] = $f;
    }
    else
    { // if this function is used 100 times in a script, this block is run 99 times.  Efficient.
        $f = $colors_rgb[$foreground];
    }

    if( !isset($colors_rgb[$background]) )
    { // do this only ONCE per script, for each unique colour.
        $b = array(  'r'=>hexdec($background[0].$background[1]),
                     'g'=>hexdec($background[2].$background[3]),
                     'b'=>hexdec($background[4].$background[5])    );
        $colors_rgb[$background] = $b;
    }
    else
    { // if this FUNCTION is used 100 times in a SCRIPT, this block will run 99 times.  Efficient.
        $b = $colors_rgb[$background];
    }

    $add = array(    'r'=>( $b['r']-$f['r'] ) / 100,
                     'g'=>( $b['g']-$f['g'] ) / 100,
                     'b'=>( $b['b']-$f['b'] ) / 100    );

    $f['r'] += intval( $add['r'] * $transparency );
    $f['g'] += intval( $add['g'] * $transparency );
    $f['b'] += intval( $add['b'] * $transparency );

    return sprintf( '%02X%02X%02X', $f['r'], $f['g'], $f['b'] );
}
4
pgee70

https://github.com/mikeemoo/ColorJizz-PHP permet de convertir en HSL, de changer le composant de luminosité et de reconvertir en RGB.

2
Slawa

Si vous souhaitez une implémentation simple et que vous vous souciez peu des valeurs spécifiquement supérieures à 50% de légèreté (ou quel que soit votre seuil), vous pouvez utiliser ma solution pour des couleurs plus claires:

$color = sprintf('#%06X', mt_Rand(0xFFFFFF / 1.5, 0xFFFFFF));

L'idée est de générer une couleur aléatoire dans la partie supérieure de la palette. Vous pouvez ajuster les résultats pour qu'ils soient plus ou moins sombres en modifiant la valeur "1,5":

  • plus grand étendra la palette dans des couleurs plus sombres
  • plus petit le réduira à des couleurs plus claires

Vous pouvez faire de même pour les couleurs plus sombres en définissant le point de départ de la fonction aléatoire sur "0x000000" et en divisant la limite de fin:

$color = sprintf('#%06X', mt_Rand(0x000000, 0xFFFFFF / 1.5));

Je sais que ce n'est pas précis mais ça marche pour moi.

1
phoenix