web-dev-qa-db-ja.com

PHPで明るい色/暗い色を生成するにはどうすればよいですか?

#202010など、ある色の16進値があります。

パーセントで指定された明るい色または暗い色の新しい色を生成する方法(すなわち、20%暗い) PHPで?

46
eni

Frxstremの例のように、パーセントで色を調整することは理想的ではありません。

色が黒(RGBでは0,0,0)の場合、ゼロを掛けることになり、まったく変化しません。色が濃い灰色(たとえば、RGBの2,2,2)の場合、(3,3,3)まで移動するには50%明るくする必要があります。一方、RGBカラーが(100,100,100)の場合、50%の調整により(150,150,150)に移動します。これは、比較するとはるかに大きな変化です。

より良い解決策は、たとえば次のように(PHPコード)、パーセントではなくステップ/番号(0〜255)で調整することです。

編集2014-01-06:コードを少し整理しました。

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

答えは間違っています。

RGBモデルの使用は概念的なエラーです。

RGB(または16進形式)からHSLに色を変換する必要があります。

それは色相、彩度、明度です。

RGBからHSLに変換したら、色を明るくするために、L値(明度)を10%調整するだけです。その後、完了したらHSLからRGBに変換し直します。

出来上がり!

PHPでRGBからHSV

22
Rod

以下に例を示します。

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

色を抽出します。おそらく他のより効率的な方法もありますが、正規表現を使用することを好みます。

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

$parts[1]に赤、$parts[2]に緑、$parts[3]に青があります。それでは、それらを16進数から整数に変換しましょう。

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

次に、それらを20%減らします。

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

次に、16進数に戻し、出力文字列に追加します

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

次に、文字列の先頭に「#」を追加するだけです。

22
Frxstrem

Torkil Johnsenの答えは、明るさだけを操作するのではなく、色相をわずかに変更する固定ステップに基づいています。 Frxstremの方法には、Tokil Johnsenが指摘したように欠陥もあります。

Githubコメント からこのアプローチを採用し、コードを改善しました。どんな場合でも完璧に機能します。

/**
 * 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);
}

結果の例を次に示します。

example

11
maliayas

私はこれに興味がありましたが、私の質問は色にopacityを追加するにはどうすればいいですか?

色を薄くするのではなく、色を薄くしたかったのです。私はこれを見つけました: http://www.gidnetwork.com/b-135.html そして、それは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( [email protected]_match($pattern, $foreground)  or  [email protected]_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 は、HSLへの変換、明度コンポーネントの変更、およびRGBへの変換を可能にします。

2
Slawa

単純な実装が必要で、値が特に50%の明度(またはしきい値)を超えることをあまり気にしない場合は、明るい色に私のソリューションを使用できます。

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

アイデアは、パレットの上部にランダムな色を生成することです。 「1.5」の値を変更することで、結果が多少暗くなるように調整できます。

  • 大きいほどパレットが暗い色に拡大します
  • 小さいほど明るい色になります

ランダム関数の開始点を「0x000000」に設定し、終了制限を分割することで、暗い色でも同じことができます。

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

私はこれが正確ではないことを知っていますが、私にとってはうまくいきます。

1
phoenix