├── src
├── exceptions
│ ├── general_error.php
│ ├── invalid_color.php
│ ├── invalid_value.php
│ ├── invalid_argument.php
│ ├── invalid_config.php
│ └── value_out_of_range.php
├── convert
│ ├── hex.php
│ ├── cmyk.php
│ ├── hsl.php
│ ├── hsb.php
│ └── rgb.php
├── interfaces
│ └── converter.php
├── data
│ ├── cache.php
│ ├── color
│ │ ├── type.php
│ │ ├── space
│ │ │ ├── rgb.php
│ │ │ ├── hsl.php
│ │ │ ├── hsb.php
│ │ │ └── cmyk.php
│ │ └── x11.php
│ ├── type.php
│ ├── store.old.php
│ └── store.php
├── check.php
├── validate.php
├── hsl.php
├── modify.php
├── main_peripheral.php
├── css.php
├── error.php
├── traits
│ └── converter.php
├── generate.php
├── regulate.php
└── yiq_scheme.php
├── .gitignore
├── testing
├── tests
│ ├── 11_CSSTest.php
│ ├── 12_CloneTest.php
│ ├── 10_MainTest.php
│ ├── 07_CacheTest.php
│ ├── 04_CheckTest.php
│ ├── 00_ErrorTest.php
│ ├── 08_HSLTest.php
│ ├── 09_ColorTest.php
│ ├── 02_ConverterTest.php
│ ├── 03_GeneratorTest.php
│ └── 05_SchemeTest.php
└── bootstrap.php
├── .editorconfig
├── phpunit-travis.xml
├── .travis.yml
├── .codeclimate.yml
├── phpunit.xml
├── phpunit-scrutinizer.xml
├── autoload.php
├── LICENSE
├── tput.exe.stackdump
├── php5
├── cache.php
├── check.php
├── error.php
├── modify.php
├── css.php
├── hsl.php
├── main_peripheral.php
├── generate.php
├── regulate.php
├── color.php
├── convert.php
└── yiq_scheme.php
├── composer.json
├── tasks.todo
├── .scrutinizer.yml
├── README.md
└── meta
└── sample.php
/src/exceptions/general_error.php:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | testing/tests
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: php
2 | before_script:
3 | - wget https://scrutinizer-ci.com/ocular.phar
4 | - composer install -n
5 | script:
6 | - ./vendor/phpunit/phpunit/phpunit -c phpunit-travis.xml
7 | after_script:
8 | - php ocular.phar code-coverage:upload --format=php-clover coverage.clover
9 | - php vendor/bin/codacycoverage clover coverage.clover
10 | - ./vendor/bin/test-reporter --coverage-report coverage.clover
11 | php:
12 | - 5.6
13 | - 7.0
14 |
--------------------------------------------------------------------------------
/.codeclimate.yml:
--------------------------------------------------------------------------------
1 | engines:
2 | duplication:
3 | enabled: true
4 | config:
5 | languages:
6 | - php
7 | fixme:
8 | enabled: true
9 | phan:
10 | enabled: true
11 | config:
12 | file_extensions: "php"
13 | fixme:
14 | enabled: true
15 | markdownlint:
16 | enabled: true
17 | ratings:
18 | paths:
19 | - "**.php"
20 | - "**.md"
21 | exclude_paths:
22 | - "meta/"
23 | - "testing/"
24 | - "php5/"
25 | - "autload.php"
26 |
--------------------------------------------------------------------------------
/phpunit.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | testing/tests
5 |
6 |
7 |
8 |
9 | src
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/phpunit-scrutinizer.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | testing/tests
5 |
6 |
7 |
8 |
9 | src
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/testing/tests/10_MainTest.php:
--------------------------------------------------------------------------------
1 | vars['conversions']['FF0000'];
16 | $main = new main($color['rgb']);
17 | $this->assertEquals($color['rgb'] + ['a' => 100], $main->rgb());
18 | $this->assertEquals($color['hsl'] + ['a' => 100], $main->hsl());
19 | $this->assertEquals($color['hsb'] + ['a' => 100], $main->hsb());
20 | $this->assertEquals($color['cmyk'] + ['a' => 100], $main->cmyk());
21 | $this->assertEquals($color['hex'], $main->hex());
22 | $this->assertEquals($color['hex'], $main->web_safe());
23 | $this->assertEquals('#'.$color['hex'], $main->css());
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/src/convert/hex.php:
--------------------------------------------------------------------------------
1 | hexdec(substr($hex, 0, 2)),
14 | 'g' => hexdec(substr($hex, 2, 2)),
15 | 'b' => hexdec(substr($hex, 4, 2))
16 | ];
17 | }
18 |
19 | public static function to_hex($input) :string {
20 | return static::_validate_hex_input($input);
21 | }
22 |
23 | public static function to_cmyk($input) :array {
24 | return rgb::to_cmyk(static::to_rgb($input));
25 | }
26 |
27 | public static function to_hsl($input) :array {
28 | return rgb::to_hsl(static::to_rgb($input));
29 | }
30 |
31 | public static function to_hsb($input) :array {
32 | return rgb::to_hsb(static::to_rgb($input));
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/testing/tests/07_CacheTest.php:
--------------------------------------------------------------------------------
1 | set('test', 'id', $rand);
19 | $this->assertEquals($rand, $cache->get('test', 'id'));
20 | }
21 |
22 | /**
23 | * @test
24 | */
25 | public function Is_Active() {
26 | $cache = new cache;
27 | $cache->active = FALSE;
28 | $rand = rand();
29 |
30 | $cache->set('test', 'id', $rand);
31 | $this->assertEquals(NULL, $cache->get('test', 'id'));
32 | }
33 |
34 | /**
35 | * @test
36 | */
37 | public function Reset() {
38 | $cache = new cache;
39 | $rand = rand();
40 |
41 | $cache->set('test', 'id', $rand);
42 | $this->assertEquals($rand, $cache->get('test', 'id'));
43 | $cache->reset();
44 | $this->assertEquals(NULL, $cache->get('test', 'id'));
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/testing/tests/04_CheckTest.php:
--------------------------------------------------------------------------------
1 | assertTrue(check::is_dark(0, 0, 0));
17 | // White
18 | $this->assertFalse(check::is_dark(255, 255, 255));
19 | // Gray (mathematical dark)
20 | $this->assertTrue(check::is_dark(127, 127, 127));
21 | // Gray (mathematical light)
22 | $this->assertFalse(check::is_dark(128, 128, 128));
23 | }
24 |
25 | /**
26 | * @test
27 | */
28 | public function RGB_Contrast() {
29 | $possible_contrasts = [11,30,41,59,70,89,100];
30 | foreach ($this->vars['conversions'] as $hex1 => $color1) {
31 | foreach ($this->vars['conversions'] as $hex2 => $color2) {
32 | if ($hex1 == $hex2) {
33 | $this->assertEquals(0, check::rgb_contrast($color1['rgb'], $color2['rgb']));
34 | } else {
35 | $this->assertTrue(in_array(round(check::rgb_contrast($color1['rgb'], $color2['rgb'])), $possible_contrasts));
36 | }
37 | }
38 | }
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/autoload.php:
--------------------------------------------------------------------------------
1 | 0,
17 | 'm' => 0,
18 | 'y' => 0,
19 | 'k' => 0
20 | );
21 |
22 | public static function to_rgb($input) :array {
23 | $cmyk = static::_validate_array_input($input);
24 | $cmyk['c'] /= 100;
25 | $cmyk['m'] /= 100;
26 | $cmyk['y'] /= 100;
27 | $cmyk['k'] /= 100;
28 | $r = 1 - min(1, $cmyk['c'] * (1 - $cmyk['k']) + $cmyk['k']);
29 | $g = 1 - min(1, $cmyk['m'] * (1 - $cmyk['k']) + $cmyk['k']);
30 | $b = 1 - min(1, $cmyk['y'] * (1 - $cmyk['k']) + $cmyk['k']);
31 | return [
32 | 'r' => round($r * 255),
33 | 'g' => round($g * 255),
34 | 'b' => round($b * 255)
35 | ];
36 | }
37 |
38 | public static function to_hex($input) :string {
39 | return rgb::to_hex(static::to_rgb($input));
40 | }
41 |
42 | public static function to_cmyk($input) :array {
43 | return static::_validate_array_input($input);
44 | }
45 |
46 | public static function to_hsl($input) :array {
47 | return rgb::to_hsl(static::to_rgb($input));
48 | }
49 |
50 | public static function to_hsb($input) :array {
51 | return rgb::to_hsb(static::to_rgb($input));
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/php5/cache.php:
--------------------------------------------------------------------------------
1 | reset();
30 | $this->active = TRUE;
31 | }
32 |
33 | /**
34 | * Reset the entire cache
35 | *
36 | * @return void
37 | */
38 | public function reset() {
39 | $this->data = array();
40 | }
41 |
42 | /**
43 | * Store a value in the cache
44 | *
45 | * @param string $func The function trying to store data (should be __FUNCTION__)
46 | * @param string $id The storage ID
47 | * @param mixed $value The value to store
48 | */
49 | public function set($func, $id, $value) {
50 | if ($this->active) {
51 | $this->data[$func] = array($id => $value);
52 | }
53 | }
54 |
55 | /**
56 | * Get a value from the cache
57 | *
58 | * @param string $func The function trying to get data (should be __FUNCTION__)
59 | * @param string $id The storage ID
60 | * @return mixed The value stored or NULL
61 | */
62 | public function get($func, $id) {
63 | if ($this->active && isset($this->data[$func][$id])) {
64 | return $this->data[$func][$id];
65 | }
66 | }
67 | }
68 |
--------------------------------------------------------------------------------
/composer.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "projectcleverweb/color",
3 | "description": "This is a stand-alone PHP 7 (and PHP 5!) library for working with RGB, HSL, HSB/HSV, Hexadecimal, and CMYK colors. Create schemes, modify specific color properties, easily convert between color spaces, create gradients, and make color suggestions quickly and easily.",
4 | "version": "0.0.0-dev",
5 | "keywords": [
6 | "color",
7 | "hsl",
8 | "cmyk",
9 | "scheme",
10 | "hex",
11 | "hexadecimal",
12 | "theme",
13 | "rgb",
14 | "hsb",
15 | "hue",
16 | "light",
17 | "brightness",
18 | "saturation",
19 | "manipulation",
20 | "red",
21 | "blue",
22 | "green",
23 | "class",
24 | "object",
25 | "pantone",
26 | "ral",
27 | "complementary",
28 | "triad",
29 | "tetrad",
30 | "analogous",
31 | "accented",
32 | "split",
33 | "compound",
34 | "monochromatic",
35 | "shades",
36 | "shade",
37 | "custom",
38 | "chroma"
39 | ],
40 | "homepage": "https://github.com/ProjectCleverWeb/PHP-Color",
41 | "type": "library",
42 | "license": "MIT",
43 | "authors": [
44 | {
45 | "name": "Nicholas Jordon",
46 | "email": "projectcleverweb@gmail.com",
47 | "homepage": "https://github.com/ProjectCleverWeb"
48 | }
49 | ],
50 | "require": {
51 | "php": ">=5.3"
52 | },
53 | "require-dev": {
54 | "phpunit/phpunit": "~5.5.5",
55 | "codeclimate/php-test-reporter": "dev-master",
56 | "codacy/coverage": "dev-master"
57 | },
58 | "autoload": {
59 | "files": ["autoload.php"]
60 | }
61 | }
62 |
--------------------------------------------------------------------------------
/src/data/cache.php:
--------------------------------------------------------------------------------
1 | reset();
30 | $this->active = TRUE;
31 | }
32 |
33 | /**
34 | * Reset the entire cache
35 | *
36 | * @return void
37 | */
38 | public function reset() {
39 | $this->data = [];
40 | }
41 |
42 | /**
43 | * Store a value in the cache
44 | *
45 | * @param string $func The function trying to store data (should be __FUNCTION__)
46 | * @param string $id The storage ID
47 | * @param mixed $value The value to store
48 | */
49 | public function set(string $func, string $id, $value) {
50 | if ($this->active) {
51 | $this->data[$func] = [$id => $value];
52 | }
53 | }
54 |
55 | /**
56 | * Get a value from the cache
57 | *
58 | * @param string $func The function trying to get data (should be __FUNCTION__)
59 | * @param string $id The storage ID
60 | * @return mixed The value stored or NULL
61 | */
62 | public function get(string $func, string $id) {
63 | if ($this->active && isset($this->data[$func][$id])) {
64 | return $this->data[$func][$id];
65 | }
66 | }
67 | }
68 |
--------------------------------------------------------------------------------
/testing/tests/00_ErrorTest.php:
--------------------------------------------------------------------------------
1 | 0,
16 | 's' => 0,
17 | 'l' => 0
18 | );
19 |
20 | public static function to_rgb($input) :array {
21 | $hsl = static::_validate_array_input($input);
22 | $hsl['s'] /= 100;
23 | $hsl['l'] /= 100;
24 | $c = (1 - abs((2 * $hsl['l']) - 1)) * $hsl['s'];
25 | $x = $c * (1 - abs(fmod(($hsl['h'] / 60), 2) - 1));
26 | $m = $hsl['l'] - ($c / 2);
27 | $r = $c;
28 | $g = 0;
29 | $b = $x;
30 |
31 | if ($hsl['h'] < 180) {
32 | static::_hslrgb_low($r, $g, $b, $c, $x, $hsl['h']);
33 | } elseif ($hsl['h'] < 300) {
34 | static::_hslrgb_high($r, $g, $b, $c, $x, $hsl['h']);
35 | }
36 |
37 | return [
38 | 'r' => (int) round(($r + $m) * 255),
39 | 'g' => (int) round(($g + $m) * 255),
40 | 'b' => (int) round(($b + $m) * 255)
41 | ];
42 | }
43 |
44 | public static function to_hex($input) :string {
45 | return rgb::to_hex(static::to_rgb($input));
46 | }
47 |
48 | public static function to_cmyk($input) :array {
49 | return rgb::to_cmyk(static::to_rgb($input));
50 | }
51 |
52 | public static function to_hsl($input) :array {
53 | return static::_validate_array_input($input);
54 | }
55 |
56 | public static function to_hsb($input) :array {
57 | return rgb::to_hsb(static::to_rgb($input));
58 | }
59 | }
60 |
--------------------------------------------------------------------------------
/src/convert/hsb.php:
--------------------------------------------------------------------------------
1 | 0,
16 | 's' => 0,
17 | 'b' => 0
18 | );
19 |
20 | public static function to_rgb($input) :array {
21 | $hsb = static::_validate_array_input($input);
22 | if ($hsb['b'] == 0) {
23 | return ['r' => 0, 'g' => 0, 'b' => 0];
24 | }
25 | $hsb['h'] /= 60;
26 | $hsb['s'] /= 100;
27 | $hsb['b'] /= 100;
28 | $i = floor($hsb['h']);
29 | $f = $hsb['h'] - $i;
30 | $p = $hsb['b'] * (1 - $hsb['s']);
31 | $q = $hsb['b'] * (1 - ($hsb['s'] * $f));
32 | $t = $hsb['b'] * (1 - ($hsb['s'] * (1 - $f)));
33 | $calc = [[$hsb['b'], $t, $p],[$q, $hsb['b'], $p],[$p, $hsb['b'], $t],[$p, $q, $hsb['b']],[$t, $p, $hsb['b']],[$hsb['b'], $p, $q]];
34 | return ['r' => $calc[$i][0] * 255, 'g' => $calc[$i][1] * 255, 'b' => $calc[$i][2] * 255];
35 | }
36 |
37 | public static function to_hex($input) :string {
38 | return rgb::to_hex(static::to_rgb($input));
39 | }
40 |
41 | public static function to_cmyk($input) :array {
42 | return rgb::to_cmyk(static::to_rgb($input));
43 | }
44 |
45 | public static function to_hsl($input) :array {
46 | return rgb::to_hsl(static::to_rgb($input));
47 | }
48 |
49 | public static function to_hsb($input) :array {
50 | return static::_validate_array_input($input);
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/src/data/color/type.php:
--------------------------------------------------------------------------------
1 | 'rgb',
47 | 'hls' => 'hsl',
48 | 'bhs' => 'hsb',
49 | 'ckmy' => 'cmyk'
50 | ];
51 | if (isset($types[$type])) {
52 | return $types[$type];
53 | }
54 | return 'error';
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/php5/check.php:
--------------------------------------------------------------------------------
1 | = $check_score returns FALSE, otherwise TRUE
22 | */
23 | public static function is_dark($r = 0, $g = 0, $b = 0, $check_score = 128) {
24 | if (generate::yiq_score($r, $g, $b) >= $check_score) {
25 | return FALSE;
26 | }
27 | return TRUE;
28 | }
29 |
30 | /**
31 | * Measures the visual contrast of 2 RGB colors.
32 | *
33 | * NOTE: most colors do not have a 100% contrasting opposite, but all colors
34 | * do have a contrasting opposite that is at least 50%.
35 | *
36 | * @param array $rgb1 The first color, array where offsets 'r', 'g', & 'b' contain their respective values.
37 | * @param array $rgb2 The second color, array where offsets 'r', 'g', & 'b' contain their respective values.
38 | * @return float The visual contrast as a percentage (e.g. 12.345)
39 | */
40 | public static function rgb_contrast($rgb1, $rgb2) {
41 | $r = (max($rgb1['r'], $rgb2['r']) - min($rgb1['r'], $rgb2['r'])) * 299;
42 | $g = (max($rgb1['g'], $rgb2['g']) - min($rgb1['g'], $rgb2['g'])) * 587;
43 | $b = (max($rgb1['b'], $rgb2['b']) - min($rgb1['b'], $rgb2['b'])) * 114;
44 | // Sum => Average => Convert to percentage
45 | return ($r + $g + $b) / 1000 / 2.55;
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/src/check.php:
--------------------------------------------------------------------------------
1 | = $check_score returns FALSE, otherwise TRUE
22 | */
23 | public static function is_dark(int $r = 0, int $g = 0, int $b = 0, int $check_score = 128) :bool {
24 | if (generate::yiq_score($r, $g, $b) >= $check_score) {
25 | return FALSE;
26 | }
27 | return TRUE;
28 | }
29 |
30 | /**
31 | * Measures the visual contrast of 2 RGB colors.
32 | *
33 | * NOTE: most colors do not have a 100% contrasting opposite, but all colors
34 | * do have a contrasting opposite that is at least 50%.
35 | *
36 | * @param array $rgb1 The first color, array where offsets 'r', 'g', & 'b' contain their respective values.
37 | * @param array $rgb2 The second color, array where offsets 'r', 'g', & 'b' contain their respective values.
38 | * @return float The visual contrast as a percentage (e.g. 12.345)
39 | */
40 | public static function rgb_contrast($rgb1, $rgb2) {
41 | $r = (max($rgb1['r'], $rgb2['r']) - min($rgb1['r'], $rgb2['r'])) * 299;
42 | $g = (max($rgb1['g'], $rgb2['g']) - min($rgb1['g'], $rgb2['g'])) * 587;
43 | $b = (max($rgb1['b'], $rgb2['b']) - min($rgb1['b'], $rgb2['b'])) * 114;
44 | // Sum => Average => Convert to percentage
45 | return ($r + $g + $b) / 1000 / 2.55;
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/src/data/color/space/rgb.php:
--------------------------------------------------------------------------------
1 | array(
34 | 'name' => 'Red',
35 | 'min' => 0,
36 | 'max' => 255,
37 | 'default' => 0,
38 | 'allow_negative' => FALSE,
39 | 'allow_float' => FALSE,
40 | 'overflow_method' => 'limit'
41 | ),
42 | 'g' => array(
43 | 'name' => 'Green',
44 | 'min' => 0,
45 | 'max' => 255,
46 | 'default' => 0,
47 | 'allow_negative' => FALSE,
48 | 'allow_float' => FALSE,
49 | 'overflow_method' => 'limit'
50 | ),
51 | 'b' => array(
52 | 'name' => 'Blue',
53 | 'min' => 0,
54 | 'max' => 255,
55 | 'default' => 0,
56 | 'allow_negative' => FALSE,
57 | 'allow_float' => FALSE,
58 | 'overflow_method' => 'limit'
59 | ),
60 | );
61 | }
62 |
--------------------------------------------------------------------------------
/src/data/color/space/hsl.php:
--------------------------------------------------------------------------------
1 | array(
34 | 'name' => 'Hue',
35 | 'min' => 0,
36 | 'max' => 359,
37 | 'default' => 0,
38 | 'allow_negative' => TRUE,
39 | 'allow_float' => FALSE,
40 | 'overflow_method' => 'loop'
41 | ),
42 | 's' => array(
43 | 'name' => 'Saturation',
44 | 'min' => 0,
45 | 'max' => 100,
46 | 'default' => 0,
47 | 'allow_negative' => FALSE,
48 | 'allow_float' => FALSE,
49 | 'overflow_method' => 'limit'
50 | ),
51 | 'l' => array(
52 | 'name' => 'Light',
53 | 'min' => 0,
54 | 'max' => 100,
55 | 'default' => 0,
56 | 'allow_negative' => FALSE,
57 | 'allow_float' => FALSE,
58 | 'overflow_method' => 'limit'
59 | ),
60 | );
61 | }
62 |
--------------------------------------------------------------------------------
/src/data/color/space/hsb.php:
--------------------------------------------------------------------------------
1 | array(
34 | 'name' => 'Hue',
35 | 'min' => 0,
36 | 'max' => 359,
37 | 'default' => 0,
38 | 'allow_negative' => TRUE,
39 | 'allow_float' => FALSE,
40 | 'overflow_method' => 'loop'
41 | ),
42 | 's' => array(
43 | 'name' => 'Saturation',
44 | 'min' => 0,
45 | 'max' => 100,
46 | 'default' => 0,
47 | 'allow_negative' => FALSE,
48 | 'allow_float' => FALSE,
49 | 'overflow_method' => 'limit'
50 | ),
51 | 'b' => array(
52 | 'name' => 'Brightness',
53 | 'min' => 0,
54 | 'max' => 100,
55 | 'default' => 0,
56 | 'allow_negative' => FALSE,
57 | 'allow_float' => FALSE,
58 | 'overflow_method' => 'limit'
59 | ),
60 | );
61 | }
62 |
--------------------------------------------------------------------------------
/src/data/type.php:
--------------------------------------------------------------------------------
1 | 'rgb',
47 | 'hls' => 'hsl',
48 | 'bhs' => 'hsb',
49 | 'ckmy' => 'cmyk'
50 | ];
51 | if (isset($types[$type])) {
52 | return $types[$type];
53 | }
54 | return 'error';
55 | }
56 |
57 | public static function _object($color) :string {
58 | if (is_object($color) && is_a($color, __NAMESPACE__.'\\store')) {
59 | return 'object';
60 | }
61 | return 'error';
62 | }
63 | }
64 |
--------------------------------------------------------------------------------
/php5/error.php:
--------------------------------------------------------------------------------
1 | 0,
17 | 'g' => 0,
18 | 'b' => 0,
19 | ]);
20 | $this->assertTrue(isset($hsl['h']));
21 | $this->assertTrue(isset($hsl['s']));
22 | $this->assertTrue(isset($hsl['l']));
23 | }
24 |
25 | /**
26 | * @test
27 | */
28 | public function Array_Access() {
29 | $hsl = new hsl([
30 | 'r' => 255,
31 | 'g' => 0,
32 | 'b' => 0,
33 | ]);
34 | $this->assertTrue(isset($hsl['h']));
35 | $this->assertEquals(50, $hsl['l']);
36 | $hsl['l'] = 100;
37 | $this->assertEquals(100, $hsl['l']);
38 | unset($hsl['l']);
39 | $this->assertEquals(0, $hsl['l']);
40 | unset($hsl['x']); // invalid unset
41 | }
42 |
43 | /**
44 | * @test
45 | */
46 | public function Invoke() {
47 | $hsl = new hsl([
48 | 'r' => 255,
49 | 'g' => 0,
50 | 'b' => 0,
51 | ]);
52 | $this->assertEquals([
53 | 'h' => 0,
54 | 's' => 100,
55 | 'l' => 50
56 | ], $hsl());
57 | }
58 |
59 |
60 | /**
61 | * @test
62 | * @expectedException Exception
63 | * @expectedExceptionMessage The offset "x" does not exist in projectcleverweb\color\hsl
64 | */
65 | public function Invalid_Get() {
66 | error::set('active', TRUE);
67 | $hsl = new hsl([
68 | 'r' => 255,
69 | 'g' => 0,
70 | 'b' => 0,
71 | ]);
72 | $hsl['x'];
73 | }
74 |
75 | /**
76 | * @test
77 | * @expectedException Exception
78 | * @expectedExceptionMessage The offset "x" cannot be set in projectcleverweb\color\hsl
79 | */
80 | public function Invalid_Set() {
81 | error::set('active', TRUE);
82 | $hsl = new hsl([
83 | 'r' => 255,
84 | 'g' => 0,
85 | 'b' => 0,
86 | ]);
87 | $hsl['x'] = 100;
88 | }
89 | }
90 |
--------------------------------------------------------------------------------
/src/data/color/space/cmyk.php:
--------------------------------------------------------------------------------
1 | array(
34 | 'name' => 'Cyan',
35 | 'min' => 0,
36 | 'max' => 100,
37 | 'default' => 100,
38 | 'allow_negative' => FALSE,
39 | 'allow_float' => FALSE,
40 | 'overflow_method' => 'limit'
41 | ),
42 | 'm' => array(
43 | 'name' => 'Magenta',
44 | 'min' => 0,
45 | 'max' => 100,
46 | 'default' => 100,
47 | 'allow_negative' => FALSE,
48 | 'allow_float' => FALSE,
49 | 'overflow_method' => 'limit'
50 | ),
51 | 'y' => array(
52 | 'name' => 'Yellow',
53 | 'min' => 0,
54 | 'max' => 100,
55 | 'default' => 100,
56 | 'allow_negative' => FALSE,
57 | 'allow_float' => FALSE,
58 | 'overflow_method' => 'limit'
59 | ),
60 | 'k' => array(
61 | 'name' => 'Black',
62 | 'min' => 0,
63 | 'max' => 100,
64 | 'default' => 100,
65 | 'allow_negative' => FALSE,
66 | 'allow_float' => FALSE,
67 | 'overflow_method' => 'limit'
68 | )
69 | );
70 | }
71 |
--------------------------------------------------------------------------------
/php5/modify.php:
--------------------------------------------------------------------------------
1 | rgb);
19 | $scope = strtolower($scope);
20 | $adjustment = max(min($adjustment, 255), 0 - 255); // Force valid range
21 | $adjustment = static::_convert_to_exact($adjustment, 255, $as_percentage);
22 | $current[$scope] = static::_convert_to_abs($current[$scope], $adjustment, $set_absolute, 0, 255);
23 | return static::regenerate_rgb($color, $current);
24 | }
25 |
26 | public static function hsl($color, $scope, $adjustment, $as_percentage, $set_absolute) {
27 | $current = array_combine(array('hue', 'saturation', 'light'), $color->hsl());
28 | $scope = strtolower($scope);
29 | $max = 100;
30 | if ($scope == 'hue') {
31 | $max = 359;
32 | }
33 | $adjustment = max(min($adjustment, $max), 0 - $max); // Force valid range
34 | $adjustment = static::_convert_to_exact($adjustment, $max, $as_percentage);
35 | $current[$scope] = static::_convert_to_abs($current[$scope], $adjustment, $set_absolute, 0, $max);
36 | return static::regenerate_hsl($color, $current);
37 | }
38 |
39 | protected static function _convert_to_exact($adjustment, $max, $as_percentage) {
40 | if ($as_percentage) {
41 | return ($adjustment / 100) * abs($max);
42 | }
43 | return $adjustment;
44 | }
45 |
46 | protected static function _convert_to_abs($current, $adjustment, $set_absolute, $min = 0, $max = PHP_INT_MAX) {
47 | if ($set_absolute) {
48 | return abs($adjustment);
49 | }
50 | return max(min($current + $adjustment, $max), $min);
51 | }
52 |
53 | protected static function regenerate_rgb($color, $update) {
54 | $color->import_rgb(array(
55 | 'r' => $update['red'],
56 | 'g' => $update['green'],
57 | 'b' => $update['blue']
58 | ));
59 | }
60 |
61 | protected static function regenerate_hsl($color, $update) {
62 | $color->import_hsl(array(
63 | 'h' => $update['hue'],
64 | 's' => $update['saturation'],
65 | 'l' => $update['light']
66 | ));
67 | }
68 | }
69 |
--------------------------------------------------------------------------------
/php5/css.php:
--------------------------------------------------------------------------------
1 | alpha() == 100 && !static::$force_alpha) {
29 | return static::hex($color->rgb['r'], $color->rgb['g'], $color->rgb['b']);
30 | }
31 | return static::rgb($color->rgb['r'], $color->rgb['g'], $color->rgb['b'], $color->alpha());
32 | }
33 |
34 | /**
35 | * Force $color to be an instance of color
36 | *
37 | * @param mixed &$color The color
38 | * @return void
39 | */
40 | protected static function _color_instance(&$color) {
41 | if (!is_a($color, __CLASS__)) {
42 | $color = new color($color);
43 | }
44 | }
45 |
46 | /**
47 | * Convert and RGB value to a CSS hex string
48 | *
49 | * @param float $r The red value
50 | * @param float $g The green value
51 | * @param float $b The blue value
52 | * @return string The CSS string
53 | */
54 | public static function hex($r, $g, $b) {
55 | return '#'.convert::rgb_to_hex($r, $g, $b);
56 | }
57 |
58 | /**
59 | * Convert and RGB value to a CSS rgb or rgba string
60 | *
61 | * @param float $r The red value
62 | * @param float $g The green value
63 | * @param float $b The blue value
64 | * @return string The CSS string
65 | */
66 | public static function rgb($r, $g, $b, $a = 1.0) {
67 | if ($a == 1.0 && !static::$force_alpha) {
68 | return sprintf('rgb(%s,%s,%s)', $r, $g, $b);
69 | }
70 | return sprintf('rgba(%s,%s,%s,%s)', $r, $g, $b, $a / 100);
71 | }
72 |
73 | /**
74 | * Convert and HSL value to a CSS hsl or hsla string
75 | *
76 | * @param float $h The hue value
77 | * @param float $s The saturation value
78 | * @param float $l The light value
79 | * @return string The CSS string
80 | */
81 | public static function hsl($h, $s, $l, $a = 1.0) {
82 | if ($a == 1.0 && !static::$force_alpha) {
83 | return sprintf('hsl(%s,%s%%,%s%%)', $h, $s, $l);
84 | }
85 | return sprintf('hsla(%s,%s%%,%s%%,%s)', $h, $s, $l, $a / 100);
86 | }
87 | }
88 |
--------------------------------------------------------------------------------
/src/validate.php:
--------------------------------------------------------------------------------
1 | = $min && $value <= $max);
81 | }
82 |
83 | public static function in_between(float $value, float $min, float $max) :bool {
84 | return ($value > $min && $value < $max);
85 | }
86 | }
87 |
--------------------------------------------------------------------------------
/src/convert/rgb.php:
--------------------------------------------------------------------------------
1 | 0,
16 | 'g' => 0,
17 | 'b' => 0
18 | );
19 |
20 | public static function to_rgb($input) :array {
21 | return static::_validate_array_input($input);
22 | }
23 |
24 | public static function to_hex($input) :string {
25 | $rgb = static::_validate_array_input($input);
26 | return strtoupper(
27 | str_pad(dechex($rgb['r']), 2, '0', STR_PAD_LEFT)
28 | .str_pad(dechex($rgb['g']), 2, '0', STR_PAD_LEFT)
29 | .str_pad(dechex($rgb['b']), 2, '0', STR_PAD_LEFT)
30 | );
31 | }
32 |
33 | public static function to_cmyk($input) :array {
34 | $rgb = static::_validate_array_input($input);
35 | $rgbp = array(
36 | 'r' => $rgb['r'] / 255 * 100,
37 | 'g' => $rgb['g'] / 255 * 100,
38 | 'b' => $rgb['b'] / 255 * 100
39 | );
40 | $k = 100 - max($rgbp);
41 | return [
42 | 'c' => ((100 - $rgbp['r'] - $k) / (100 - $k)) * 100,
43 | 'm' => ((100 - $rgbp['g'] - $k) / (100 - $k)) * 100,
44 | 'y' => ((100 - $rgbp['b'] - $k) / (100 - $k)) * 100,
45 | 'k' => $k
46 | ];
47 | }
48 |
49 | public static function to_hsl($input) :array {
50 | $rgb = static::_validate_array_input($input);
51 | $r = $rgb['r'] / 255;
52 | $g = $rgb['g'] / 255;
53 | $b = $rgb['b'] / 255;
54 | $min = min($r, $g, $b);
55 | $max = max($r, $g, $b);
56 | $delta = $max - $min;
57 | $h = 0;
58 | $s = 0;
59 | $l = ($max + $min) / 2;
60 |
61 | if ($max != $min) {
62 | $s = $delta / ($max + $min);
63 | if ($l >= 0.5) {
64 | $s = $delta / (2 - $max - $min);
65 | }
66 | static::_rgbhsl_hue($h, $r, $g, $b, $max, $delta);
67 | }
68 |
69 | return [
70 | 'h' => $h * 360,
71 | 's' => $s * 100,
72 | 'l' => $l * 100
73 | ];
74 | }
75 |
76 | public static function to_hsb($input) :array {
77 | $rgb = static::_validate_array_input($input);
78 | $r = $rgb['r'] / 255;
79 | $g = $rgb['g'] / 255;
80 | $b = $rgb['b'] / 255;
81 |
82 | $max = max($r, $g, $b);
83 | $min = min($r, $g, $b);
84 | $v = $max;
85 | $d = $max - $min;
86 | $s = \projectcleverweb\color\regulate::div($d, $max);
87 | $h = 0; // achromatic
88 | if ($max != $min) {
89 | static::_rgbhsl_hue($h, $r, $g, $b, $max, $d);
90 | }
91 |
92 | $h = $h * 360;
93 | $s = $s * 100;
94 | $v = $v * 100;
95 |
96 | return ['h' => $h, 's' => $s, 'b' => $v];
97 | }
98 | }
99 |
--------------------------------------------------------------------------------
/php5/hsl.php:
--------------------------------------------------------------------------------
1 | accuracy = $accuracy;
37 | $this->hsl = convert::rgb_to_hsl($rgb_array['r'], $rgb_array['g'], $rgb_array['b'], $this->accuracy);
38 | }
39 |
40 | /**
41 | * Shortcut for return the HSL array
42 | *
43 | * @return array The HSL array
44 | */
45 | public function __invoke() {
46 | return $this->hsl;
47 | }
48 |
49 | /**
50 | * Check if offset exists in data array
51 | *
52 | * @param string $offset The offset to check
53 | * @return bool TRUE if the offset exist, FALSE otherwise
54 | */
55 | public function offsetExists($offset) {
56 | return isset($this->hsl[$offset]);
57 | }
58 |
59 | /**
60 | * Get an offset if it exists
61 | *
62 | * @param string $offset The offset to get
63 | * @return mixed The value of the offset
64 | */
65 | public function offsetGet($offset) {
66 | if ($this->offsetExists($offset)) {
67 | return $this->hsl[$offset];
68 | }
69 | return error::call(sprintf(
70 | 'The offset "%s" does not exist in %s',
71 | (string) $offset,
72 | __CLASS__
73 | ));
74 | }
75 |
76 | /**
77 | * Set a value in the data array
78 | *
79 | * @param string $offset The offset to set
80 | * @param mixed $value The value to set it to
81 | * @return mixed The result
82 | */
83 | public function offsetSet($offset, $value) {
84 | if ($this->offsetExists($offset)) {
85 | return $this->hsl[$offset] = (float) $value;
86 | }
87 | return error::call(sprintf(
88 | 'The offset "%s" cannot be set in %s',
89 | (string) $offset,
90 | __CLASS__
91 | ));
92 | }
93 |
94 | /**
95 | * Reset an offset to 0
96 | *
97 | * @param string $offset The offset to unset
98 | * @return mixed The result
99 | */
100 | public function offsetUnset($offset) {
101 | if ($this->offsetExists($offset)) {
102 | return $this->hsl[$offset] = 0.0;
103 | }
104 | }
105 | }
106 |
--------------------------------------------------------------------------------
/src/hsl.php:
--------------------------------------------------------------------------------
1 | accuracy = $accuracy;
37 | $this->hsl = convert\rgb::to_hsl($rgb_array);
38 | }
39 |
40 | /**
41 | * Shortcut for return the HSL array
42 | *
43 | * @return array The HSL array
44 | */
45 | public function __invoke() {
46 | return $this->hsl;
47 | }
48 |
49 | /**
50 | * Check if offset exists in data array
51 | *
52 | * @param string $offset The offset to check
53 | * @return bool TRUE if the offset exist, FALSE otherwise
54 | */
55 | public function offsetExists($offset) :bool {
56 | return isset($this->hsl[$offset]);
57 | }
58 |
59 | /**
60 | * Get an offset if it exists
61 | *
62 | * @param string $offset The offset to get
63 | * @return mixed The value of the offset
64 | */
65 | public function offsetGet($offset) {
66 | if ($this->offsetExists($offset)) {
67 | return $this->hsl[$offset];
68 | }
69 | return error::trigger(error::INVALID_ARGUMENT, sprintf(
70 | 'The offset "%s" does not exist in %s',
71 | (string) $offset,
72 | __CLASS__
73 | ));
74 | }
75 |
76 | /**
77 | * Set a value in the data array
78 | *
79 | * @param string $offset The offset to set
80 | * @param mixed $value The value to set it to
81 | * @return mixed The result
82 | */
83 | public function offsetSet($offset, $value) {
84 | if ($this->offsetExists($offset)) {
85 | return $this->hsl[$offset] = (float) $value;
86 | }
87 | return error::trigger(error::INVALID_ARGUMENT, sprintf(
88 | 'The offset "%s" cannot be set in %s',
89 | (string) $offset,
90 | __CLASS__
91 | ));
92 | }
93 |
94 | /**
95 | * Reset an offset to 0
96 | *
97 | * @param string $offset The offset to unset
98 | * @return mixed The result
99 | */
100 | public function offsetUnset($offset) {
101 | if ($this->offsetExists($offset)) {
102 | return $this->hsl[$offset] = 0.0;
103 | }
104 | }
105 | }
106 |
--------------------------------------------------------------------------------
/src/modify.php:
--------------------------------------------------------------------------------
1 | rgb);
19 | $scope = strtolower($scope);
20 | $adjustment = max(min($adjustment, 255), 0 - 255); // Force valid range
21 | $adjustment = static::_convert_to_exact($adjustment, 255, $as_percentage);
22 | $current[$scope] = static::_convert_to_abs($current[$scope], $adjustment, $set_absolute, 0, 255);
23 | return static::regenerate_rgb($color, $current, $scope);
24 | }
25 |
26 | public static function hsl(color $color, string $scope, float $adjustment, bool $as_percentage, bool $set_absolute) {
27 | $current = array_combine(['hue', 'saturation', 'light'], $color->hsl());
28 | $scope = strtolower($scope);
29 | $max = 100;
30 | if ($scope == 'hue') {
31 | $max = 359;
32 | }
33 | $adjustment = max(min($adjustment, $max), 0 - $max); // Force valid range
34 | $adjustment = static::_convert_to_exact($adjustment, $max, $as_percentage);
35 | $current[$scope] = static::_convert_to_abs($current[$scope], $adjustment, $set_absolute, 0, $max);
36 | return static::regenerate_hsl($color, $current, $scope);
37 | }
38 |
39 | protected static function _convert_to_exact(float $adjustment, float $max, bool $as_percentage) {
40 | if ($as_percentage) {
41 | return ($adjustment / 100) * abs($max);
42 | }
43 | return $adjustment;
44 | }
45 |
46 | protected static function _convert_to_abs(float $current, float $adjustment, bool $set_absolute, float $min = 0, float $max = PHP_INT_MAX) {
47 | if ($set_absolute) {
48 | return abs($adjustment);
49 | }
50 | return max(min($current + $adjustment, $max), $min);
51 | }
52 |
53 | protected static function regenerate_rgb(color $color, array $update, string $return_offset = '') {
54 | $color->import_rgb([
55 | 'r' => $update['red'],
56 | 'g' => $update['green'],
57 | 'b' => $update['blue']
58 | ]);
59 | if (isset($update[$return_offset])) {
60 | return $update[$return_offset];
61 | }
62 | }
63 |
64 | protected static function regenerate_hsl(color $color, array $update, string $return_offset = '') {
65 | $color->import_hsl([
66 | 'h' => $update['hue'],
67 | 's' => $update['saturation'],
68 | 'l' => $update['light']
69 | ]);
70 | if (isset($update[$return_offset])) {
71 | return $update[$return_offset];
72 | }
73 | }
74 | }
75 |
--------------------------------------------------------------------------------
/tasks.todo:
--------------------------------------------------------------------------------
1 | General:
2 | ☐ Add git flow
3 | ☐ Add contact form
4 | Class Specific:
5 | ☐ Add main::difference() for comparing 2 different colors
6 | ☐ css/main should support importing css rgb/hsl percentage values
7 | Bugs:
8 | Minor:
9 | Documentation:
10 | ☐ Add code docs to class 'modify'
11 | ☐ Add readme.md for github license tag
12 | Testing:
13 | ☐ Add test for class 'main'
14 | ☐ Add randomized testing for scheme generation
15 | ☐ Test against float vs int function arguments
16 | ☐ Test for cloning issues
17 |
18 | ___________________
19 | Archive:
20 | ✔ Modify main attribute methods return either existing or resulting value @done (16-10-21 14:54) @project(General)
21 | ✔ Make main::alpha() a modification method @done (16-10-21 14:54) @project(General)
22 | ✔ Add PHP 5 support @done (16-10-21 14:54) @project(General)
23 | ✔ Add test for class 'color' @done (16-09-30 10:09) @project(Testing)
24 | ✔ Validate scope in modify::rgb() and modify::hsl @done (16-09-29 16:53) @project(Class Specific)
25 | ✔ Add test for class 'scheme' @done (16-09-24 13:35) @project(Testing)
26 | ✔ Add test for class 'regulate' @done (16-09-24 13:35) @project(Testing)
27 | ✔ Add test for class 'hsl' @done (16-09-24 13:35) @project(Testing)
28 | ✔ Add test for class 'error' @done (16-09-24 13:35) @project(Testing)
29 | ✔ Add code docs to class 'hsl' @done (16-09-24 13:35) @project(Documentation)
30 | ✔ Add code docs to class 'generate' @done (16-09-24 13:35) @project(Documentation)
31 | ✔ add main::rgb_rand() and main::hsl_rand() @done (16-09-24 13:34) @project(Class Specific)
32 | ✔ Create README file @done (16-09-24 13:34) @project(Documentation)
33 | ✔ Add code docs to class 'main' @done (16-09-24 13:34) @project(Documentation)
34 | ✔ Add cache class @done (16-09-24 13:33) @project(General)
35 | ✔ Add ability to generate all colors within the selected color range, with steps settable @done (16-09-24 13:33) @project(General)
36 | ✔ replace main::*_scheme() with main::scheme($name, $return_type = 'hex') @done (16-08-09 17:19) @project(Class Specific)
37 | ✔ Abstract main class serialize methods @done (16-08-09 17:19) @project(Class Specific)
38 | ✔ Add mixing function @done (16-08-08 11:34) @project(General)
39 | ✔ Add hsb support @done (16-08-08 11:32) @project(General)
40 | ✔ Add JSON serialization support @done (16-08-01 18:34) @project(General)
41 | ✔ Fix scheme::is_dark() docs (return is void) @done (16-07-22 15:45) @project(Minor)
42 | ✔ Fix color::_get_array_type() docs ($color should be type array) @done (16-07-22 15:44) @project(Minor)
43 | ✔ scheme::is_dark() should force $is_dark to be boolean @done (16-07-22 15:43) @project(Bugs)
44 | ✔ Add test for class 'check' @done (16-07-22 14:29) @project(Testing)
45 | ✔ Alias main::*_scheme() to 'scheme' class @done (16-07-21 18:18) @project(Class Specific)
46 | ✔ Implement alpha channel support @done (16-07-21 16:14) @project(General)
47 | ✔ Implement exporting as CSS values @done (16-07-20 18:03) @project(General)
48 | ✔ Add meta folder for generating samples @done (16-07-20 16:17) @project(General)
49 |
--------------------------------------------------------------------------------
/testing/tests/09_ColorTest.php:
--------------------------------------------------------------------------------
1 | vars['conversions']['FF0000'];
16 | foreach ($color as $type => $val) {
17 | $this->assertEquals($type, color::get_type($val));
18 | }
19 | $this->assertEquals('error', color::get_type(new \stdClass));
20 | $this->assertEquals('error', color::get_type(['invalid array']));
21 | }
22 |
23 | /**
24 | * @test
25 | */
26 | public function Import() {
27 | foreach ($this->vars['conversions'] as $color) {
28 | foreach ($color as $type => $val) {
29 | $import = new color($val);
30 | $this->assertEquals($color['rgb'], $import->rgb);
31 | }
32 | }
33 | }
34 |
35 | /**
36 | * @test
37 | */
38 | public function Import_Color() {
39 | foreach ($this->vars['conversions'] as $color) {
40 | foreach ($color as $type => $val) {
41 | $color1 = new color($val);
42 | $color2 = new color($color1);
43 | $this->assertEquals($color['rgb'], $color1->rgb);
44 | $this->assertEquals($color['rgb'], $color1->rgb);
45 | $this->assertTrue($color1 !== $color2);
46 | }
47 | }
48 | }
49 |
50 | /**
51 | * @test
52 | * @expectedException Exception
53 | * @expectedExceptionMessage The color supplied to projectcleverweb\color\color's constructor was not valid
54 | */
55 | public function Import_Error() {
56 | $color = new color(new \stdClass);
57 | $this->assertEquals(0, $color->rgb['r']);
58 | $this->assertEquals(0, $color->rgb['g']);
59 | $this->assertEquals(0, $color->rgb['b']);
60 | error::set('active', TRUE);
61 | $color = new color(new \stdClass);
62 | }
63 |
64 | /**
65 | * @test
66 | */
67 | public function Alpha() {
68 | $color = $this->vars['conversions']['FF0000'];
69 | $obj = new color($color['rgb'] + ['a' => 50.0]);
70 | $this->assertEquals(50.0, $obj->alpha());
71 | $this->assertEquals(90.0, $obj->alpha(90));
72 | $this->assertEquals(90.0, $obj->alpha());
73 | }
74 |
75 | /**
76 | * @test
77 | */
78 | public function As_HSL() {
79 | $color = new color($this->vars['conversions']['FF0000']['rgb']);
80 | $hsl = $color->hsl();
81 | $this->assertEquals(0, $hsl['h']);
82 | $this->assertEquals(100, $hsl['s']);
83 | $this->assertEquals(50, $hsl['l']);
84 | }
85 |
86 | /**
87 | * @test
88 | */
89 | public function Serialize() {
90 | $color = new color($this->vars['conversions']['FF0000']['rgb']);
91 | $serialized = serialize($color);
92 | $this->assertEquals('C:28:"projectcleverweb\color\color":29:{{"r":255,"g":0,"b":0,"a":100}}', $serialized);
93 | $this->assertEquals($color, unserialize($serialized));
94 | }
95 |
96 | /**
97 | * @test
98 | */
99 | public function JSON_Serialize() {
100 | $color = new color($this->vars['conversions']['FF0000']['rgb']);
101 | $json = json_encode($color);
102 | $this->assertEquals('{"r":255,"g":0,"b":0,"a":100}', $json);
103 | }
104 | }
105 |
--------------------------------------------------------------------------------
/php5/main_peripheral.php:
--------------------------------------------------------------------------------
1 | color = clone $this->color;
20 | $this->cache = clone $this->cache;
21 | }
22 |
23 | /**
24 | * Custom serialize function
25 | *
26 | * @return string This instance serialized as an RGB string
27 | */
28 | public function serialize() {
29 | return $this->color->serialize();
30 | }
31 |
32 | /**
33 | * Custom unserialize function
34 | *
35 | * @param string $serialized This instance serialized as an RGB string
36 | * @return void
37 | */
38 | public function unserialize($serialized) {
39 | $unserialized = (array) json_decode((string) $serialized);
40 | regulate::rgb_array($unserialized);
41 | $this->set($unserialized, 'rgb');
42 | }
43 |
44 | /**
45 | * Custom JSON serialize function
46 | *
47 | * @return string This instance serialized as an JSON RGB string
48 | */
49 | public function jsonSerialize() {
50 | return $this->color->jsonSerialize();
51 | }
52 |
53 | protected function get_scheme($scheme_name, $return_type = 'hex', $scheme_class) {
54 | if (!is_null($cached = $this->cache->get(get_class($scheme_class).'_'.$scheme_name.'_'.$return_type, $this->hex()))) {
55 | return $cached;
56 | }
57 | $result = static::_scheme($scheme_name, array($scheme_class, strtolower($return_type)), $this->hsl(3));
58 | $this->cache->set(get_class($scheme_class).'_'.$scheme_name.'_'.$return_type, $this->hex(), $result);
59 | return $result;
60 | }
61 |
62 | /**
63 | * Handles scheme generator callbacks
64 | *
65 | * @param string $scheme_name The name of the scheme algorithm to use
66 | * @param string $callback The return type callback
67 | * @param array $hsl The base color as an HSL array
68 | * @return array The resulting scheme in the proper format, OR an empty array on failure.
69 | */
70 | protected static function _scheme($scheme_name, $callback, $hsl) {
71 | if (is_callable($callback)) {
72 | return call_user_func($callback, $hsl['h'], $hsl['s'], $hsl['l'], $scheme_name);
73 | }
74 | error::call(sprintf(
75 | 'The $callback "%s" is not a valid callback',
76 | print_r($callback, 1),
77 | __CLASS__,
78 | __FUNCTION__
79 | ));
80 | return array();
81 | }
82 |
83 | /**
84 | * Set whether or not caching should be active.
85 | *
86 | * @param bool $active If TRUE caching is turned on, otherwise cashing is turned off.
87 | * @return void
88 | */
89 | public function cache($active = TRUE) {
90 | $this->cache->active = $active;
91 | }
92 |
93 | /**
94 | * Reset the cache for this instance
95 | *
96 | * @return void
97 | */
98 | public function reset_cache() {
99 | $this->cache->reset();
100 | }
101 | }
102 |
--------------------------------------------------------------------------------
/src/main_peripheral.php:
--------------------------------------------------------------------------------
1 | color = clone $this->color;
20 | $this->cache = clone $this->cache;
21 | }
22 |
23 | /**
24 | * Custom serialize function
25 | *
26 | * @return string This instance serialized as an RGB string
27 | */
28 | public function serialize() :string {
29 | return $this->color->serialize();
30 | }
31 |
32 | /**
33 | * Custom unserialize function
34 | *
35 | * @param string $serialized This instance serialized as an RGB string
36 | * @return void
37 | */
38 | public function unserialize($serialized) {
39 | $unserialized = (array) json_decode((string) $serialized);
40 | regulate::rgb_array($unserialized);
41 | $this->set($unserialized, 'rgb');
42 | }
43 |
44 | /**
45 | * Custom JSON serialize function
46 | *
47 | * @return string This instance serialized as an JSON RGB string
48 | */
49 | public function jsonSerialize() :array {
50 | return $this->color->jsonSerialize();
51 | }
52 |
53 | protected function get_scheme(string $scheme_name, string $return_type = 'hex', $scheme_class) :array {
54 | if (!is_null($cached = $this->cache->get(get_class($scheme_class).'_'.$scheme_name.'_'.$return_type, $this->hex()))) {
55 | return $cached;
56 | }
57 | $result = static::_scheme($scheme_name, [$scheme_class, strtolower($return_type)], $this->hsl(3));
58 | $this->cache->set(get_class($scheme_class).'_'.$scheme_name.'_'.$return_type, $this->hex(), $result);
59 | return $result;
60 | }
61 |
62 | /**
63 | * Handles scheme generator callbacks
64 | *
65 | * @param string $scheme_name The name of the scheme algorithm to use
66 | * @param string $callback The return type callback
67 | * @param array $hsl The base color as an HSL array
68 | * @return array The resulting scheme in the proper format, OR an empty array on failure.
69 | */
70 | protected static function _scheme(string $scheme_name, array $callback, array $hsl) :array {
71 | if (is_callable($callback)) {
72 | return call_user_func($callback, $hsl['h'], $hsl['s'], $hsl['l'], $scheme_name);
73 | }
74 | error::trigger(error::INVALID_ARGUMENT, sprintf(
75 | 'The $callback "%s" is not a valid callback',
76 | print_r($callback, 1),
77 | __CLASS__,
78 | __FUNCTION__
79 | ));
80 | return [];
81 | }
82 |
83 | /**
84 | * Set whether or not caching should be active.
85 | *
86 | * @param bool $active If TRUE caching is turned on, otherwise cashing is turned off.
87 | * @return void
88 | */
89 | public function cache(bool $active = TRUE) {
90 | $this->cache->active = $active;
91 | }
92 |
93 | /**
94 | * Reset the cache for this instance
95 | *
96 | * @return void
97 | */
98 | public function reset_cache() {
99 | $this->cache->reset();
100 | }
101 | }
102 |
--------------------------------------------------------------------------------
/testing/bootstrap.php:
--------------------------------------------------------------------------------
1 | vars = [
28 | 'conversions' => [
29 | // The 8 basic colors of the RGB spectrum with their conversions
30 | '000000' => [
31 | 'int' => 0x000000,
32 | 'hex' => '000000',
33 | 'rgb' => ['r' => 0, 'g' => 0, 'b' => 0 ],
34 | 'hsl' => ['h' => 0, 's' => 0, 'l' => 0],
35 | 'hsb' => ['h' => 0, 's' => 0, 'b' => 0],
36 | 'cmyk' => ['c' => 0, 'm' => 0, 'y' => 0, 'k' => 100]
37 | ],
38 | 'FFFFFF' => [
39 | 'int' => 0xFFFFFF,
40 | 'hex' => 'FFFFFF',
41 | 'rgb' => ['r' => 255, 'g' => 255, 'b' => 255],
42 | 'hsl' => ['h' => 0, 's' => 0, 'l' => 100],
43 | 'hsb' => ['h' => 0, 's' => 0, 'b' => 100],
44 | 'cmyk' => ['c' => 0, 'm' => 0, 'y' => 0, 'k' => 0]
45 | ],
46 | 'FFFF00' => [
47 | 'int' => 0xFFFF00,
48 | 'hex' => 'FFFF00',
49 | 'rgb' => ['r' => 255, 'g' => 255, 'b' => 0 ],
50 | 'hsl' => ['h' => 60, 's' => 100, 'l' => 50],
51 | 'hsb' => ['h' => 60, 's' => 100, 'b' => 100],
52 | 'cmyk' => ['c' => 0, 'm' => 0, 'y' => 100, 'k' => 0]
53 | ],
54 | 'FF00FF' => [
55 | 'int' => 0xFF00FF,
56 | 'hex' => 'FF00FF',
57 | 'rgb' => ['r' => 255, 'g' => 0, 'b' => 255],
58 | 'hsl' => ['h' => 300, 's' => 100, 'l' => 50],
59 | 'hsb' => ['h' => 300, 's' => 100, 'b' => 100],
60 | 'cmyk' => ['c' => 0, 'm' => 100, 'y' => 0, 'k' => 0]
61 | ],
62 | 'FF0000' => [
63 | 'int' => 0xFF0000,
64 | 'hex' => 'FF0000',
65 | 'rgb' => ['r' => 255, 'g' => 0, 'b' => 0 ],
66 | 'hsl' => ['h' => 0, 's' => 100, 'l' => 50],
67 | 'hsb' => ['h' => 0, 's' => 100, 'b' => 100],
68 | 'cmyk' => ['c' => 0, 'm' => 100, 'y' => 100, 'k' => 0]
69 | ],
70 | '00FFFF' => [
71 | 'int' => 0x00FFFF,
72 | 'hex' => '00FFFF',
73 | 'rgb' => ['r' => 0, 'g' => 255, 'b' => 255],
74 | 'hsl' => ['h' => 180, 's' => 100, 'l' => 50],
75 | 'hsb' => ['h' => 180, 's' => 100, 'b' => 100],
76 | 'cmyk' => ['c' => 100, 'm' => 0, 'y' => 0, 'k' => 0]
77 | ],
78 | '00FF00' => [
79 | 'int' => 0x00FF00,
80 | 'hex' => '00FF00',
81 | 'rgb' => ['r' => 0, 'g' => 255, 'b' => 0 ],
82 | 'hsl' => ['h' => 120, 's' => 100, 'l' => 50],
83 | 'hsb' => ['h' => 120, 's' => 100, 'b' => 100],
84 | 'cmyk' => ['c' => 100, 'm' => 0, 'y' => 100, 'k' => 0]
85 | ],
86 | '0000FF' => [
87 | 'int' => 0x0000FF,
88 | 'hex' => '0000FF',
89 | 'rgb' => ['r' => 0, 'g' => 0, 'b' => 255],
90 | 'hsl' => ['h' => 240, 's' => 100, 'l' => 50],
91 | 'hsb' => ['h' => 240, 's' => 100, 'b' => 100],
92 | 'cmyk' => ['c' => 100, 'm' => 100, 'y' => 0, 'k' => 0]
93 | ]
94 | ]
95 | ];
96 | }
97 |
98 | /**
99 | *
100 | */
101 | public function tearDown() {
102 |
103 | }
104 | }
105 |
--------------------------------------------------------------------------------
/src/css.php:
--------------------------------------------------------------------------------
1 | &$val) {
33 | $val = (float) filter_var($val, FILTER_SANITIZE_NUMBER_FLOAT, FILTER_FLAG_ALLOW_THOUSAND | FILTER_FLAG_ALLOW_SCIENTIFIC | FILTER_FLAG_ALLOW_FRACTION);
34 | if ($key == 'a') {
35 | $val = $val * 100;
36 | }
37 | }
38 | return $color;
39 | }
40 |
41 | /**
42 | * Choose the best way to represent the color as a CSS value. Will use either
43 | * a hex or rgba value depending on the alpha value.
44 | *
45 | * @param mixed $color The color
46 | * @return string The CSS value
47 | */
48 | public static function best($color) {
49 | static::_color_instance($color);
50 | if ($color->alpha() == 100 && !static::$force_alpha) {
51 | return static::hex($color->rgb['r'], $color->rgb['g'], $color->rgb['b']);
52 | }
53 | return static::rgb($color->rgb['r'], $color->rgb['g'], $color->rgb['b'], $color->alpha());
54 | }
55 |
56 | /**
57 | * Force $color to be an instance of color
58 | *
59 | * @param mixed &$color The color
60 | * @return void
61 | */
62 | protected static function _color_instance(&$color) {
63 | if (!is_a($color, __CLASS__)) {
64 | $color = new color($color);
65 | }
66 | }
67 |
68 | /**
69 | * Convert and RGB value to a CSS hex string
70 | *
71 | * @param float $r The red value
72 | * @param float $g The green value
73 | * @param float $b The blue value
74 | * @return string The CSS string
75 | */
76 | public static function hex(float $r, float $g, float $b) {
77 | return '#'.convert::rgb_to_hex($r, $g, $b);
78 | }
79 |
80 | /**
81 | * Convert and RGB value to a CSS rgb or rgba string
82 | *
83 | * @param float $r The red value
84 | * @param float $g The green value
85 | * @param float $b The blue value
86 | * @return string The CSS string
87 | */
88 | public static function rgb(float $r, float $g, float $b, float $a = 1.0) {
89 | if ($a == 1.0 && !static::$force_alpha) {
90 | return sprintf('rgb(%s,%s,%s)', $r, $g, $b);
91 | }
92 | return sprintf('rgba(%s,%s,%s,%s)', $r, $g, $b, $a / 100);
93 | }
94 |
95 | /**
96 | * Convert and HSL value to a CSS hsl or hsla string
97 | *
98 | * @param float $h The hue value
99 | * @param float $s The saturation value
100 | * @param float $l The light value
101 | * @return string The CSS string
102 | */
103 | public static function hsl(float $h, float $s, float $l, float $a = 1.0) {
104 | if ($a == 1.0 && !static::$force_alpha) {
105 | return sprintf('hsl(%s,%s%%,%s%%)', $h, $s, $l);
106 | }
107 | return sprintf('hsla(%s,%s%%,%s%%,%s)', $h, $s, $l, $a / 100);
108 | }
109 | }
110 |
--------------------------------------------------------------------------------
/src/error.php:
--------------------------------------------------------------------------------
1 | 'GENERAL',
45 | self::INVALID_CONFIG => 'INVALID_CONFIG',
46 | self::INVALID_VALUE => 'INVALID_VALUE',
47 | self::INVALID_ARGUMENT => 'INVALID_ARGUMENT',
48 | self::INVALID_COLOR => 'INVALID_COLOR',
49 | self::OUT_OF_RANGE => 'OUT_OF_RANGE',
50 | );
51 |
52 | /**
53 | * Maps each constant to a descriptive exception class
54 | *
55 | * @var array
56 | */
57 | protected static $exception_map = array(
58 | self::GENERAL_ERROR => __NAMESPACE__.'\\exceptions\\general_error',
59 | self::INVALID_CONFIG => __NAMESPACE__.'\\exceptions\\invalid_config',
60 | self::INVALID_VALUE => __NAMESPACE__.'\\exceptions\\invalid_value',
61 | self::INVALID_ARGUMENT => __NAMESPACE__.'\\exceptions\\invalid_argument',
62 | self::INVALID_COLOR => __NAMESPACE__.'\\exceptions\\invalid_color',
63 | self::OUT_OF_RANGE => __NAMESPACE__.'\\exceptions\\out_of_range',
64 | );
65 |
66 | /**
67 | * Allows the modifying of configuration vars for this class.
68 | *
69 | * @param string $var The variable to modify
70 | * @param bool $value The value to set the variable to
71 | */
72 | public static function set(string $var, bool $value) {
73 | if (isset(self::$$var)) {
74 | static::$$var = $value;
75 | }
76 | }
77 |
78 | /**
79 | * This function chooses the method to report the error if static::$active is
80 | * equal to TRUE.
81 | *
82 | * @param int $code The error code constant that was passed
83 | * @param string $message The message describing the error
84 | * @return void
85 | */
86 | public static function trigger(int $code, string $message) {
87 | if (!static::$active) {
88 | return;
89 | } elseif(static::$use_exceptions) {
90 | static::exception($message, $code);
91 | }
92 | static::standard($message, $code);
93 | }
94 |
95 | /**
96 | * Throws an exception with $message
97 | *
98 | * @param string $message The message describing the error
99 | * @return void
100 | */
101 | protected static function exception(string $message, int $code = 0) {
102 | if (!isset(static::$exception_map[$code])) {
103 | throw new exceptions\general_error('Unknown error type for error: '.$message, $code);
104 | $code = 0;
105 | }
106 | throw new static::$exception_map[$code]($message, $code);
107 | }
108 |
109 | /**
110 | * Triggers a E_USER_WARNING error with $message
111 | *
112 | * @param string $message The message describing the error
113 | * @return void
114 | */
115 | protected static function standard(string $message, int $code = 0) {
116 | if (!isset(static::$type_map[$code])) {
117 | trigger_error('Unknown error type for error: '.$message);
118 | $code = 0;
119 | }
120 | return trigger_error(sprintf('[%s] %s', static::$type_map[$code], $message), E_USER_WARNING);
121 | }
122 | }
123 |
--------------------------------------------------------------------------------
/testing/tests/02_ConverterTest.php:
--------------------------------------------------------------------------------
1 | vars['conversions'] as $hex => $conv) {
16 | $this->assertEquals(convert::hex_to_rgb($hex), $conv['rgb']);
17 | }
18 | }
19 |
20 | /**
21 | * @test
22 | */
23 | public function RGB_To_HEX() {
24 | foreach ($this->vars['conversions'] as $hex => $conv) {
25 | $this->assertEquals(convert::rgb_to_hex($conv['rgb']['r'], $conv['rgb']['g'], $conv['rgb']['b']), $hex);
26 | }
27 | }
28 |
29 | /**
30 | * @test
31 | */
32 | public function RGB_To_CMYK() {
33 | foreach ($this->vars['conversions'] as $conv) {
34 | $this->assertEquals(convert::rgb_to_cmyk($conv['rgb']['r'], $conv['rgb']['g'], $conv['rgb']['b']), $conv['cmyk']);
35 | }
36 | }
37 |
38 | /**
39 | * @test
40 | */
41 | public function CMYK_To_RGB() {
42 | foreach ($this->vars['conversions'] as $conv) {
43 | $this->assertEquals(convert::cmyk_to_rgb($conv['cmyk']['c'], $conv['cmyk']['m'], $conv['cmyk']['y'], $conv['cmyk']['k']), $conv['rgb']);
44 | }
45 | }
46 |
47 | /**
48 | * @test
49 | */
50 | public function RGB_To_HSL() {
51 | foreach ($this->vars['conversions'] as $conv) {
52 | $this->assertEquals(convert::rgb_to_hsl($conv['rgb']['r'], $conv['rgb']['g'], $conv['rgb']['b']), $conv['hsl']);
53 | }
54 | }
55 |
56 | /**
57 | * @test
58 | */
59 | public function HSL_To_RGB() {
60 | foreach ($this->vars['conversions'] as $conv) {
61 | $this->assertEquals(convert::hsl_to_rgb($conv['hsl']['h'], $conv['hsl']['s'], $conv['hsl']['l']), $conv['rgb']);
62 | }
63 | }
64 |
65 | /**
66 | * @test
67 | */
68 | public function RGB_To_HSB() {
69 | foreach ($this->vars['conversions'] as $conv) {
70 | $this->assertEquals(convert::rgb_to_hsb($conv['rgb']['r'], $conv['rgb']['g'], $conv['rgb']['b']), $conv['hsb']);
71 | }
72 | }
73 |
74 | /**
75 | * @test
76 | */
77 | public function HSB_To_RGB() {
78 | foreach ($this->vars['conversions'] as $conv) {
79 | $this->assertEquals(convert::hsb_to_rgb($conv['hsb']['h'], $conv['hsb']['s'], $conv['hsb']['b']), $conv['rgb']);
80 | }
81 | }
82 |
83 | /**
84 | * Testing for mathematical drifts when converting between color spaces.
85 | *
86 | * NOTE: This is not a full color space test, it only skims the RGB color
87 | * space for differences.
88 | *
89 | * @ignored_test
90 | */
91 | public function RGB_HSL_Interlace_Color_Drift() {
92 | foreach (range(0 ,51) as $b) {
93 | foreach (range(0 ,51) as $g) {
94 | foreach (range(0 ,51) as $r) {
95 | $rgb1 = ['r' => $r * 5, 'g' => $g * 5, 'b' => $b * 5];
96 | $hsl1 = convert::rgb_to_hsl($rgb1['r'], $rgb1['g'],$rgb1['b']);
97 | $rgb2 = convert::hsl_to_rgb($hsl1['h'], $hsl1['s'],$hsl1['l']);
98 | $hsl2 = convert::rgb_to_hsl($rgb2['r'], $rgb2['g'],$rgb2['b']);
99 | if (!empty(array_diff_assoc($rgb1, $rgb2)) || !empty(array_diff_assoc($hsl1, $hsl2))) {
100 | $this->assertEmpty(array_diff_assoc($rgb1, $rgb2), sprintf(
101 | 'RGB color drift detected: rgb1(%s, %s, %s) != rgb2(%s, %s, %s)',
102 | $rgb1['r'],
103 | $rgb1['g'],
104 | $rgb1['b'],
105 | $rgb2['r'],
106 | $rgb2['g'],
107 | $rgb2['b']
108 | ));
109 | $this->assertEmpty(array_diff_assoc($hsl1, $hsl2), sprintf(
110 | 'HSL color drift detected: hsl1(%s, %s, %s) != hsl2(%s, %s, %s)',
111 | $hsl1['r'],
112 | $hsl1['g'],
113 | $hsl1['b'],
114 | $hsl2['r'],
115 | $hsl2['g'],
116 | $hsl2['b']
117 | ));
118 | } else {
119 | $this->assertEmpty(array_diff_assoc($rgb1, $rgb2));
120 | $this->assertEmpty(array_diff_assoc($hsl1, $hsl2));
121 | }
122 | }
123 | }
124 | }
125 | }
126 | }
127 |
--------------------------------------------------------------------------------
/.scrutinizer.yml:
--------------------------------------------------------------------------------
1 | build:
2 | tests:
3 | override:
4 | -
5 | command: 'phpunit -c phpunit-scrutinizer.xml'
6 | environment:
7 | php:
8 | version: 7.0.8
9 | tools:
10 | external_code_coverage:
11 | timeout: 600
12 | filter:
13 | paths: [src/*]
14 | checks:
15 | php:
16 | verify_property_names: true
17 | verify_argument_usable_as_reference: true
18 | verify_access_scope_valid: true
19 | variable_existence: true
20 | use_self_instead_of_fqcn: true
21 | use_statement_alias_conflict: true
22 | uppercase_constants: true
23 | uppercase_basic_constants: true
24 | unused_variables: true
25 | unused_properties: true
26 | unused_parameters: true
27 | unused_methods: true
28 | unreachable_code: true
29 | too_many_arguments: true
30 | spacing_of_function_arguments: true
31 | spacing_around_non_conditional_operators: true
32 | spacing_around_conditional_operators: true
33 | space_after_cast: true
34 | single_namespace_per_use: true
35 | security_vulnerabilities: true
36 | return_doc_comments: true
37 | return_doc_comment_if_not_inferrable: true
38 | require_scope_for_properties: true
39 | require_scope_for_methods: true
40 | require_php_tag_first: true
41 | require_braces_around_control_structures: true
42 | remove_trailing_whitespace: true
43 | remove_php_closing_tag: true
44 | property_assignments: true
45 | prefer_while_loop_over_for_loop: true
46 | prefer_unix_line_ending: true
47 | precedence_mistakes: true
48 | precedence_in_conditions: true
49 | php5_style_constructor: true
50 | parameter_non_unique: true
51 | parameter_doc_comments: true
52 | param_doc_comment_if_not_inferrable: true
53 | overriding_private_members: true
54 | optional_parameters_at_the_end: true
55 | non_commented_empty_catch_block: true
56 | no_trailing_whitespace: true
57 | no_space_inside_cast_operator: true
58 | no_space_between_concatenation_operator: true
59 | no_space_before_semicolon: true
60 | no_space_around_object_operator: true
61 | no_short_open_tag: true
62 | no_non_implemented_abstract_methods: true
63 | no_goto: true
64 | no_eval: true
65 | no_empty_statements: true
66 | no_else_if_statements: true
67 | no_debug_code: true
68 | missing_arguments: true
69 | method_calls_on_non_object: true
70 | lowercase_php_keywords: true
71 | instanceof_class_exists: true
72 | function_body_start_on_same_line: true
73 | foreach_usable_as_reference: true
74 | foreach_traversable: true
75 | fix_use_statements:
76 | remove_unused: true
77 | preserve_multiple: false
78 | preserve_blanklines: false
79 | order_alphabetically: true
80 | fix_php_opening_tag: true
81 | fix_doc_comments: true
82 | ensure_lower_case_builtin_functions: true
83 | encourage_single_quotes: true
84 | encourage_postdec_operator: true
85 | deprecated_code_usage: true
86 | deadlock_detection_in_loops: true
87 | code_rating: true
88 | closure_use_not_conflicting: true
89 | catch_class_exists: true
90 | avoid_usage_of_logical_operators: true
91 | avoid_unnecessary_concatenation: true
92 | avoid_todo_comments: true
93 | avoid_space_indentation: true
94 | avoid_multiple_statements_on_same_line: true
95 | avoid_fixme_comments: true
96 | avoid_corrupting_byteorder_marks: true
97 | assignment_of_null_return: true
98 | argument_type_checks: true
99 | align_assignments: true
100 | newline_at_end_of_file: true
101 | more_specific_types_in_doc_comments: true
102 | avoid_perl_style_comments: true
103 |
104 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # PHP Color [](https://njordon.mit-license.org/@2016) [](https://travis-ci.org/ProjectCleverWeb/PHP-Color) [](https://scrutinizer-ci.com/g/ProjectCleverWeb/PHP-Color/) [](https://scrutinizer-ci.com/g/ProjectCleverWeb/PHP-Color/) [](https://codeclimate.com/github/ProjectCleverWeb/PHP-Color)
2 |
3 | This is a PHP 7 library for working with RGB, HSL, and Hexadecimal colors. Create schemes, modify specific color properties, export CMYK, and make color suggestions quickly and easily with this stand-alone library.
4 |
5 | Demo: [jsfiddle.net/t3LL4q14](http://jsfiddle.net/t3LL4q14/embedded/result/)
6 |
7 | ### Download:
8 |
9 | [](https://github.com/ProjectCleverWeb/PHP-Color/releases)
10 |
11 | Copyright © 2016 Nicholas Jordon — All Rights Reserved
12 |
13 | ## Features
14 |
15 | * Convert any color between the RGB, HSL, HSB, Hexadecimal, and CMYK color spectrums.
16 | * Dynamically generate 10 different color scheme algorithims for any color. (That's over 165,000,000 possible schemes)
17 | * Check whether a color appears visually dark or light. (uses [YIQ](https://en.wikipedia.org/wiki/YIQ) weights for better accuraccy)
18 | * Easily modify a color's hue, saturation, light, red, green, blue, and alpha (transparcency) values.
19 | * Generate CSS values on the fly
20 | * Find the contrast between 2 colors.
21 | * Dynamically generate random colors, including for specific color ranges.
22 | * All errors are recoverable, and errors can be triggered as exceptions (default), using `trigger_error()`, or can be turned off for all instances.
23 |
24 | ## Installation & Usage
25 |
26 | See the [Official Wiki on Github](https://github.com/ProjectCleverWeb/PHP-Color/wiki) for all documentation.
27 |
28 | ## Contributing
29 |
30 | **Contributing *via* Suggestions:**
31 | The best way to submit a suggestion is to open an issue on Github and prefix the
32 | title with `[Suggestion]`. Alternatively, you can email your suggestions to
33 | projectcleverweb(at)gmail(dot)com.
34 |
35 | **Contributing *via* Reporting Problems:**
36 | All problems must be reported via Github's
37 | [issue tracker](https://github.com/ProjectCleverWeb/PHP-Color/issues).
38 |
39 | **Contributing *via* Code:**
40 |
41 | 1. Fork the repo on Github: [github.com/ProjectCleverWeb/PHP-Color](https://github.com/ProjectCleverWeb/PHP-Color)
42 | 2. Make your changes.
43 | 3. Send a pull request to have your changes reviewed.
44 |
45 | ## License
46 |
47 | The PHP-Color documentation & source code (hereafter referred to as "Library") by Nicholas Summers (hereafter referred to as "Author") is licensed
48 | under the Creative Commons Attribution-NonCommercial-NoDerivatives 4.0 International License with the below "Additional Terms" superseding it.
49 | To view a copy of the Creative Commons license, visit [creativecommons.org/licenses/by-nc-nd/4.0](https://creativecommons.org/licenses/by-nc-nd/4.0/). From now on "License" refers to this combination of licensing.
50 |
51 | **Additional Terms:**
52 |
53 | 1. Any person or non-profit entity or may use this Library for personal or professional use as long as the Library as well as any of its parts are not sold in any fashion, and users are not forced to pay to use it in any way.
54 | 2. Anyone may use this Library for purely internal use as long as the Library as well as any of its parts are available without payment and are not publicly accessible.
55 | 3. Anyone seeking to sell this Library or use this Library in a commercial environment MUST first obtain a OEM license from the Author.
56 | 4. Anyone in direct violation of this License is liable for a minimum of $50,000 in damages, plus an additional $10 per user, and agrees to refund any charge or fees collected as a result of violating this License.
57 | 5. By downloading or using this Library you agree to all the License terms.
58 |
--------------------------------------------------------------------------------
/src/traits/converter.php:
--------------------------------------------------------------------------------
1 | vars['conversions'];
16 | $this->assertEquals(generate::rgb_contrast($conv['000000']['rgb']['r'], $conv['000000']['rgb']['g'], $conv['000000']['rgb']['b']), $conv['FFFFFF']['rgb']);
17 | }
18 |
19 | /**
20 | * @test
21 | */
22 | public function RGB_Invert() {
23 | $conv = $this->vars['conversions'];
24 | $this->assertEquals(generate::rgb_invert($conv['000000']['rgb']['r'], $conv['000000']['rgb']['g'], $conv['000000']['rgb']['b']), $conv['FFFFFF']['rgb']);
25 | }
26 |
27 | /**
28 | * @test
29 | */
30 | public function YIQ_Score() {
31 | $this->assertEquals(generate::yiq_score(255, 255, 255), 255);
32 | $this->assertEquals(generate::yiq_score(0, 0, 0), 0);
33 | }
34 |
35 | /**
36 | * @test
37 | */
38 | public function RGB_Random() {
39 | foreach (range(1, 1000) as $i) {
40 | $rgb = generate::rgb_rand();
41 | $this->assertTrue($rgb['r'] >= 0 && $rgb['r'] <= 255);
42 | $this->assertTrue($rgb['g'] >= 0 && $rgb['g'] <= 255);
43 | $this->assertTrue($rgb['b'] >= 0 && $rgb['b'] <= 255);
44 | }
45 | }
46 |
47 | /**
48 | * @test
49 | */
50 | public function HSL_Random() {
51 | foreach (range(1, 1000) as $i) {
52 | $hsl = generate::hsl_rand();
53 | $this->assertTrue($hsl['h'] >= 0 && $hsl['h'] <= 359);
54 | $this->assertTrue($hsl['s'] >= 0 && $hsl['s'] <= 100);
55 | $this->assertTrue($hsl['l'] >= 0 && $hsl['l'] <= 100);
56 | }
57 | }
58 |
59 | /**
60 | * @test
61 | */
62 | public function Blend() {
63 | $rgb1 = $this->vars['conversions']['FFFFFF']['rgb'] + ['a' => 100];
64 | $rgb2 = $this->vars['conversions']['000000']['rgb'] + ['a' => 100];
65 | $rgb3 = generate::blend($rgb1['r'], $rgb1['g'], $rgb1['b'], $rgb1['a'], $rgb2['r'], $rgb2['g'], $rgb2['b'], $rgb2['a']);
66 | $this->assertEquals(['r' => 128, 'g' => 128, 'b' => 128, 'a' => 100], $rgb3);
67 |
68 | $rgb1 = $this->vars['conversions']['FFFFFF']['rgb'] + ['a' => 100];
69 | $rgb2 = $this->vars['conversions']['000000']['rgb'] + ['a' => 50];
70 | $rgb3 = generate::blend($rgb1['r'], $rgb1['g'], $rgb1['b'], $rgb1['a'], $rgb2['r'], $rgb2['g'], $rgb2['b'], $rgb2['a'], 25);
71 | $this->assertEquals(['r' => 191, 'g' => 191, 'b' => 191, 'a' => 87.5], $rgb3);
72 | }
73 |
74 | /**
75 | * @test
76 | */
77 | public function Web_Safe() {
78 | foreach (range(1, 1000) as $i) {
79 | $rgb = generate::rgb_rand();
80 | $web = generate::web_safe($rgb['r'], $rgb['g'], $rgb['b']);
81 | foreach (convert::hex_to_rgb($web) as $val) {
82 | $this->assertTrue(is_int($val / 0x33));
83 | }
84 | }
85 | }
86 |
87 | /**
88 | * @test
89 | */
90 | public function Hue_To_YQI() {
91 | $this->assertEquals(0, generate::hue_to_yiq(0));
92 | $this->assertEquals(63.135593220338983, generate::hue_to_yiq(25));
93 | $this->assertEquals(149, generate::hue_to_yiq(59));
94 | $this->assertEquals(150, generate::hue_to_yiq(60));
95 | $this->assertEquals(445.46218487394958, generate::hue_to_yiq(120));
96 | $this->assertEquals(736, generate::hue_to_yiq(179));
97 | $this->assertEquals(737, generate::hue_to_yiq(180));
98 | $this->assertEquals(755.99159663865544, generate::hue_to_yiq(200));
99 | $this->assertEquals(850, generate::hue_to_yiq(299));
100 | $this->assertEquals(851, generate::hue_to_yiq(300));
101 | $this->assertEquals(926.76271186440681, generate::hue_to_yiq(330));
102 | $this->assertEquals(1000, generate::hue_to_yiq(359));
103 | }
104 |
105 | /**
106 | * @test
107 | */
108 | public function YQI_To_Hue() {
109 | $this->assertEquals(0, generate::yiq_to_hue(0));
110 | $this->assertEquals(39.597315436241608, generate::yiq_to_hue(100));
111 | $this->assertEquals(59, generate::yiq_to_hue(149));
112 | $this->assertEquals(60, generate::yiq_to_hue(150));
113 | $this->assertEquals(120.92150170648463, generate::yiq_to_hue(450));
114 | $this->assertEquals(179, generate::yiq_to_hue(736));
115 | $this->assertEquals(180, generate::yiq_to_hue(737));
116 | $this->assertEquals(235.81415929203541, generate::yiq_to_hue(790));
117 | $this->assertEquals(299, generate::yiq_to_hue(850));
118 | $this->assertEquals(300, generate::yiq_to_hue(851));
119 | $this->assertEquals(331.28187919463085, generate::yiq_to_hue(930));
120 | $this->assertEquals(359, generate::yiq_to_hue(1000));
121 | }
122 |
123 | /**
124 | * @test
125 | */
126 | public function Gradient() {
127 | // count down
128 | $test1 = generate::gradient_range(2, 0, 0, 0, 0, 0);
129 | $this->assertEquals([
130 | ['r' => 2, 'g' => 0, 'b' => 0],
131 | ['r' => 1, 'g' => 0, 'b' => 0],
132 | ['r' => 0, 'g' => 0, 'b' => 0]
133 | ], $test1);
134 | // count up
135 | $test2 = generate::gradient_range(0, 0, 0, 2, 0, 0);
136 | $this->assertEquals([
137 | ['r' => 0, 'g' => 0, 'b' => 0],
138 | ['r' => 1, 'g' => 0, 'b' => 0],
139 | ['r' => 2, 'g' => 0, 'b' => 0]
140 | ], $test2);
141 | // count up and down
142 | $test3 = generate::gradient_range(5, 0, 3, 0, 5, 3);
143 | $this->assertEquals([
144 | ['r' => 5, 'g' => 0, 'b' => 3],
145 | ['r' => 4, 'g' => 1, 'b' => 3],
146 | ['r' => 3, 'g' => 2, 'b' => 3],
147 | ['r' => 2, 'g' => 3, 'b' => 3],
148 | ['r' => 1, 'g' => 4, 'b' => 3],
149 | ['r' => 0, 'g' => 5, 'b' => 3]
150 | ], $test3);
151 | // 1 color
152 | $test4 = generate::gradient_range(5, 5, 5, 5, 5, 5);
153 | $this->assertEquals([
154 | ['r' => 5, 'g' => 5, 'b' => 5]
155 | ], $test4);
156 | // stretch
157 | $test5 = generate::gradient_range(5, 0, 3, 0, 5, 3, 12);
158 | $this->assertEquals([
159 | ['r' => 5, 'g' => 0, 'b' => 3],
160 | ['r' => 5, 'g' => 0, 'b' => 3],
161 | ['r' => 4, 'g' => 1, 'b' => 3],
162 | ['r' => 4, 'g' => 1, 'b' => 3],
163 | ['r' => 3, 'g' => 2, 'b' => 3],
164 | ['r' => 3, 'g' => 2, 'b' => 3],
165 | ['r' => 2, 'g' => 3, 'b' => 3],
166 | ['r' => 2, 'g' => 3, 'b' => 3],
167 | ['r' => 1, 'g' => 4, 'b' => 3],
168 | ['r' => 1, 'g' => 4, 'b' => 3],
169 | ['r' => 0, 'g' => 5, 'b' => 3],
170 | ['r' => 0, 'g' => 5, 'b' => 3]
171 | ], $test5);
172 | // stretch 1 color
173 | $test4 = generate::gradient_range(5, 5, 5, 5, 5, 5, 5);
174 | $this->assertEquals([
175 | ['r' => 5, 'g' => 5, 'b' => 5],
176 | ['r' => 5, 'g' => 5, 'b' => 5],
177 | ['r' => 5, 'g' => 5, 'b' => 5],
178 | ['r' => 5, 'g' => 5, 'b' => 5],
179 | ['r' => 5, 'g' => 5, 'b' => 5]
180 | ], $test4);
181 | }
182 | }
183 |
--------------------------------------------------------------------------------
/php5/generate.php:
--------------------------------------------------------------------------------
1 | ($r < 128) ? 255 : 0,
24 | 'g' => ($g < 128) ? 255 : 0,
25 | 'b' => ($b < 128) ? 255 : 0
26 | );
27 | }
28 |
29 | /**
30 | * Generate the mathematical opposite color for any RGB color
31 | *
32 | * @param int $r The red value
33 | * @param int $g The green value
34 | * @param int $b The blue value
35 | * @return array The mathematical opposite color as an RGB array
36 | */
37 | public static function rgb_invert($r = 0, $g = 0, $b = 0) {
38 | return array(
39 | 'r' => 255 - $r,
40 | 'g' => 255 - $g,
41 | 'b' => 255 - $b
42 | );
43 | }
44 |
45 | /**
46 | * Generate the YIQ score for an RGB color
47 | *
48 | * @param int $r The red value
49 | * @param int $g The green value
50 | * @param int $b The blue value
51 | * @return float The YIQ score
52 | */
53 | public static function yiq_score($r = 0, $g = 0, $b = 0) {
54 | return (($r * 299) + ($g * 587) + ($b * 114)) / 1000;
55 | }
56 |
57 | /**
58 | * Generate a random RGB color
59 | *
60 | * @param int $min_r The min red to allow
61 | * @param int $max_r The max red to allow
62 | * @param int $min_g The min green to allow
63 | * @param int $max_g The max green to allow
64 | * @param int $min_b The min blue to allow
65 | * @param int $max_b The max blue to allow
66 | * @return array The resulting color as a RGB array
67 | */
68 | public static function rgb_rand($min_r = 0, $max_r = 255, $min_g = 0, $max_g = 255, $min_b = 0, $max_b = 255) {
69 | return array(
70 | 'r' => rand(abs((int) $min_r) % 256, abs((int) $max_r) % 256),
71 | 'g' => rand(abs((int) $min_g) % 256, abs((int) $max_g) % 256),
72 | 'b' => rand(abs((int) $min_b) % 256, abs((int) $max_b) % 256)
73 | );
74 | }
75 |
76 | /**
77 | * Generate a random HSL color
78 | *
79 | * @param int $min_r The min hue to allow
80 | * @param int $max_r The max hue to allow
81 | * @param int $min_g The min saturation to allow
82 | * @param int $max_g The max saturation to allow
83 | * @param int $min_b The min light to allow
84 | * @param int $max_b The max light to allow
85 | * @return array The resulting color as a HSL array
86 | */
87 | public static function hsl_rand($min_h = 0, $max_h = 359, $min_s = 0, $max_s = 100, $min_l = 0, $max_l = 100) {
88 | return array(
89 | 'h' => rand(abs((int) $min_h) % 360, abs((int) $max_h) % 360),
90 | 's' => rand(abs((int) $min_s) % 101, abs((int) $max_s) % 101),
91 | 'l' => rand(abs((int) $min_l) % 101, abs((int) $max_l) % 101)
92 | );
93 | }
94 |
95 | /**
96 | * Blend 2 RGB colors
97 | *
98 | * @param float $r1 The red value from color 1
99 | * @param float $g1 The green value from color 1
100 | * @param float $b1 The blue value from color 1
101 | * @param float $a1 The alpha value from color 1
102 | * @param float $r2 The red value from color 2
103 | * @param float $g2 The green value from color 2
104 | * @param float $b2 The blue value from color 2
105 | * @param float $a2 The alpha value from color 2
106 | * @param float $amount The percentage of color 2 to mix in (defaults to 50 for even blending)
107 | * @return array The resulting color as a RGB array
108 | */
109 | public static function blend($r1, $g1, $b1, $a1, $r2, $g2, $b2, $a2, $amount = 50.0) {
110 | $x1 = regulate::div(100 - $amount, 100);
111 | $x2 = regulate::div($amount, 100);
112 | return array(
113 | 'r' => round(($r1 * $x1) + ($r2 * $x2), 0),
114 | 'g' => round(($g1 * $x1) + ($g2 * $x2), 0),
115 | 'b' => round(($b1 * $x1) + ($b2 * $x2), 0),
116 | 'a' => ($a1 * $x1) + ($a2 * $x2)
117 | );
118 | }
119 |
120 | /**
121 | * Generate a gradient range between 2 RGB colors
122 | *
123 | * @param int $r1 The red value from color 1
124 | * @param int $g1 The green value from color 1
125 | * @param int $b1 The blue value from color 1
126 | * @param int $r2 The red value from color 2
127 | * @param int $g2 The green value from color 2
128 | * @param int $b2 The blue value from color 2
129 | * @param int $steps The size of array to produce, 0 will dynamically
130 | * @return array [TODO]
131 | */
132 | public static function gradient_range($r1 = 0, $g1 = 0, $b1 = 0, $r2 = 0, $g2 = 0, $b2 = 0, $steps = 0) {
133 | $diff = array(
134 | 'r' => $r1 - $r2,
135 | 'g' => $g1 - $g2,
136 | 'b' => $b1 - $b2
137 | );
138 | $div = max(abs($r1 - $r2), abs($g1 - $g2), abs($b1 - $b2));
139 | if ($steps != 0) {
140 | $div = abs($steps) - 1;
141 | }
142 | $result = [];
143 | foreach (range(0 , $div) as $i) {
144 | $result[] = array(
145 | 'r' => $r1 + round(regulate::div(-$diff['r'], $div) * $i),
146 | 'g' => $g1 + round(regulate::div(-$diff['g'], $div) * $i),
147 | 'b' => $b1 + round(regulate::div(-$diff['b'], $div) * $i)
148 | );
149 | }
150 | return $result;
151 | }
152 |
153 | /**
154 | * Round a RGB input to a 'websafe' color hex
155 | *
156 | * @param int $r The red value
157 | * @param int $g The green value
158 | * @param int $b The blue value
159 | * @return string The resulting color as a hex string
160 | */
161 | public static function web_safe($r = 0, $g = 0, $b = 0) {
162 | return convert::rgb_to_hex(
163 | round($r / 0x33) * 0x33,
164 | round($g / 0x33) * 0x33,
165 | round($b / 0x33) * 0x33
166 | );
167 | }
168 |
169 | /**
170 | * Converts a hue to the "Y" spectrum
171 | *
172 | * @param float $hue The hue to convert
173 | * @return float The resulting Y
174 | */
175 | public static function hue_to_yiq($hue) {
176 | if ($hue < 60) {
177 | return $hue * 2.5254237288136;
178 | } elseif ($hue < 180) {
179 | return 150 + ($hue - 60) * 4.9243697478992;
180 | } elseif ($hue < 300) {
181 | return 737 + ($hue - 180) * 0.94957983193277;
182 | }
183 | return 851 + ($hue - 300) * 2.5254237288136;
184 | }
185 |
186 | /**
187 | * Converts a "Y" to the hue spectrum
188 | *
189 | * @param float $yiq The "Y" to convert
190 | * @return float The resulting hue
191 | */
192 | public static function yiq_to_hue($yiq) {
193 | if ($yiq < 150) {
194 | return $yiq * 0.39597315436242;
195 | } elseif ($yiq < 737) {
196 | return 60 + ($yiq - 150) * 0.20307167235495;
197 | } elseif ($yiq < 851) {
198 | return 180 + ($yiq - 737) * 1.0530973451327;
199 | }
200 | return 300 + ($yiq - 851) * 0.39597315436242;
201 | }
202 | }
203 |
--------------------------------------------------------------------------------
/src/generate.php:
--------------------------------------------------------------------------------
1 | ($r < 128) ? 255 : 0,
24 | 'g' => ($g < 128) ? 255 : 0,
25 | 'b' => ($b < 128) ? 255 : 0
26 | ];
27 | }
28 |
29 | /**
30 | * Generate the mathematical opposite color for any RGB color
31 | *
32 | * @param int $r The red value
33 | * @param int $g The green value
34 | * @param int $b The blue value
35 | * @return array The mathematical opposite color as an RGB array
36 | */
37 | public static function rgb_invert(int $r = 0, int $g = 0, int $b = 0) :array {
38 | return [
39 | 'r' => 255 - $r,
40 | 'g' => 255 - $g,
41 | 'b' => 255 - $b
42 | ];
43 | }
44 |
45 | /**
46 | * Generate the YIQ score for an RGB color
47 | *
48 | * @param int $r The red value
49 | * @param int $g The green value
50 | * @param int $b The blue value
51 | * @return float The YIQ score
52 | */
53 | public static function yiq_score(int $r = 0, int $g = 0, int $b = 0) :float {
54 | return (($r * 299) + ($g * 587) + ($b * 114)) / 1000;
55 | }
56 |
57 | /**
58 | * Generate a random RGB color
59 | *
60 | * @param int $min_r The min red to allow
61 | * @param int $max_r The max red to allow
62 | * @param int $min_g The min green to allow
63 | * @param int $max_g The max green to allow
64 | * @param int $min_b The min blue to allow
65 | * @param int $max_b The max blue to allow
66 | * @return array The resulting color as a RGB array
67 | */
68 | public static function rgb_rand(int $min_r = 0, int $max_r = 255, int $min_g = 0, int $max_g = 255, int $min_b = 0, int $max_b = 255) :array {
69 | return [
70 | 'r' => rand(abs((int) $min_r) % 256, abs((int) $max_r) % 256),
71 | 'g' => rand(abs((int) $min_g) % 256, abs((int) $max_g) % 256),
72 | 'b' => rand(abs((int) $min_b) % 256, abs((int) $max_b) % 256)
73 | ];
74 | }
75 |
76 | /**
77 | * Generate a random HSL color
78 | *
79 | * @param int $min_r The min hue to allow
80 | * @param int $max_r The max hue to allow
81 | * @param int $min_g The min saturation to allow
82 | * @param int $max_g The max saturation to allow
83 | * @param int $min_b The min light to allow
84 | * @param int $max_b The max light to allow
85 | * @return array The resulting color as a HSL array
86 | */
87 | public static function hsl_rand(int $min_h = 0, int $max_h = 359, int $min_s = 0, int $max_s = 100, int $min_l = 0, int $max_l = 100) :array {
88 | return [
89 | 'h' => rand(abs((int) $min_h) % 360, abs((int) $max_h) % 360),
90 | 's' => rand(abs((int) $min_s) % 101, abs((int) $max_s) % 101),
91 | 'l' => rand(abs((int) $min_l) % 101, abs((int) $max_l) % 101)
92 | ];
93 | }
94 |
95 | /**
96 | * Blend 2 RGB colors
97 | *
98 | * @param float $r1 The red value from color 1
99 | * @param float $g1 The green value from color 1
100 | * @param float $b1 The blue value from color 1
101 | * @param float $a1 The alpha value from color 1
102 | * @param float $r2 The red value from color 2
103 | * @param float $g2 The green value from color 2
104 | * @param float $b2 The blue value from color 2
105 | * @param float $a2 The alpha value from color 2
106 | * @param float $amount The percentage of color 2 to mix in (defaults to 50 for even blending)
107 | * @return array The resulting color as a RGB array
108 | */
109 | public static function blend(float $r1, float $g1, float $b1, float $a1, float $r2, float $g2, float $b2, float $a2, float $amount = 50.0) :array {
110 | $x1 = regulate::div(100 - $amount, 100);
111 | $x2 = regulate::div($amount, 100);
112 | return [
113 | 'r' => round(($r1 * $x1) + ($r2 * $x2), 0),
114 | 'g' => round(($g1 * $x1) + ($g2 * $x2), 0),
115 | 'b' => round(($b1 * $x1) + ($b2 * $x2), 0),
116 | 'a' => ($a1 * $x1) + ($a2 * $x2)
117 | ];
118 | }
119 |
120 | /**
121 | * Generate a gradient range between 2 RGB colors
122 | *
123 | * @param int $r1 The red value from color 1
124 | * @param int $g1 The green value from color 1
125 | * @param int $b1 The blue value from color 1
126 | * @param int $r2 The red value from color 2
127 | * @param int $g2 The green value from color 2
128 | * @param int $b2 The blue value from color 2
129 | * @param int $steps The size of array to produce, 0 will dynamically
130 | * @return array [TODO]
131 | */
132 | public static function gradient_range(int $r1 = 0, int $g1 = 0, int $b1 = 0, int $r2 = 0, int $g2 = 0, int $b2 = 0, int $steps = 0) :array {
133 | $diff = [
134 | 'r' => $r1 - $r2,
135 | 'g' => $g1 - $g2,
136 | 'b' => $b1 - $b2
137 | ];
138 | $div = max(abs($r1 - $r2), abs($g1 - $g2), abs($b1 - $b2));
139 | if ($steps != 0) {
140 | $div = abs($steps) - 1;
141 | }
142 | $result = [];
143 | foreach (range(0 , $div) as $i) {
144 | $result[] = [
145 | 'r' => $r1 + round(regulate::div(-$diff['r'], $div) * $i),
146 | 'g' => $g1 + round(regulate::div(-$diff['g'], $div) * $i),
147 | 'b' => $b1 + round(regulate::div(-$diff['b'], $div) * $i)
148 | ];
149 | }
150 | return $result;
151 | }
152 |
153 | /**
154 | * Round a RGB input to a 'websafe' color hex
155 | *
156 | * @param int $r The red value
157 | * @param int $g The green value
158 | * @param int $b The blue value
159 | * @return string The resulting color as a hex string
160 | */
161 | public static function web_safe(int $r = 0, int $g = 0, int $b = 0) :string {
162 | return convert\rgb::to_hex(
163 | round($r / 0x33) * 0x33,
164 | round($g / 0x33) * 0x33,
165 | round($b / 0x33) * 0x33
166 | );
167 | }
168 |
169 | /**
170 | * Converts a hue to the "Y" spectrum
171 | *
172 | * @param float $hue The hue to convert
173 | * @return float The resulting Y
174 | */
175 | public static function hue_to_yiq(float $hue) :float {
176 | if ($hue < 60) {
177 | return $hue * 2.5254237288136;
178 | } elseif ($hue < 180) {
179 | return 150 + ($hue - 60) * 4.9243697478992;
180 | } elseif ($hue < 300) {
181 | return 737 + ($hue - 180) * 0.94957983193277;
182 | }
183 | return 851 + ($hue - 300) * 2.5254237288136;
184 | }
185 |
186 | /**
187 | * Converts a "Y" to the hue spectrum
188 | *
189 | * @param float $yiq The "Y" to convert
190 | * @return float The resulting hue
191 | */
192 | public static function yiq_to_hue(float $yiq) :float {
193 | if ($yiq < 150) {
194 | return $yiq * 0.39597315436242;
195 | } elseif ($yiq < 737) {
196 | return 60 + ($yiq - 150) * 0.20307167235495;
197 | } elseif ($yiq < 851) {
198 | return 180 + ($yiq - 737) * 1.0530973451327;
199 | }
200 | return 300 + ($yiq - 851) * 0.39597315436242;
201 | }
202 | }
203 |
--------------------------------------------------------------------------------
/php5/regulate.php:
--------------------------------------------------------------------------------
1 | 000000)
166 | *
167 | * @param string &$hex_str The hex string to modify
168 | * @return void
169 | */
170 | public static function _expand_shorthand(&$hex_str) {
171 | if (strlen($hex_str) === 3) {
172 | $r = $hex_str[0];
173 | $g = $hex_str[1];
174 | $b = $hex_str[2];
175 | $hex_str = $r.$r.$g.$g.$b.$b;
176 | }
177 | }
178 |
179 | /**
180 | * Verify that the hex string is actually a hex string. If not force it to
181 | * '000000'
182 | *
183 | * @param string &$hex_str The hex string to modify
184 | * @return void
185 | */
186 | public static function _validate_hex_str(&$hex_str) {
187 | if (is_string($hex_str) && preg_match('/\A#?(?:[0-9a-f]{3}|[0-9a-f]{6})\Z/i', $hex_str)) {
188 | return;
189 | }
190 | error::call(sprintf(
191 | 'The input of %s::%s() was not a valid hex string, forcing value to 000000',
192 | __CLASS__,
193 | __FUNCTION__
194 | ));
195 | $hex_str = '000000';
196 | }
197 |
198 | /**
199 | * Force an array to have specific lower-case keys. If the array is an indexed
200 | * array and the keys are provided, convert it to an associative array.
201 | *
202 | * @param array &$array The array to be modified
203 | * @return void
204 | */
205 | public static function standardize_array(&$array, $keys = array()) {
206 | if (!empty($keys) && array_keys($array) === range(0, count($array) - 1) && count($array) == count($keys)) {
207 | $array = array_combine($keys, $array);
208 | } else {
209 | $array = array_change_key_case($array) + array_fill_keys($keys, 0);
210 | }
211 | }
212 |
213 | /**
214 | * Absolute and divide any number so it fits between 0 and $max
215 | *
216 | * @param float $number The original number
217 | * @param float $max The maximum value $number should be
218 | * @return float The resulting number as a float
219 | */
220 | public static function max($number, $max) {
221 | $max = abs($max);
222 | if ($number > $max) {
223 | $number -= floor($number / ($max + 1)) * ($max + 1);
224 | }
225 | return $number;
226 | }
227 |
228 | /**
229 | * Simple dividing method to handle division by 0
230 | *
231 | * @param float $number The number to divide
232 | * @param float $divisor The number to divide by
233 | * @return float The result
234 | */
235 | public static function div($number, $divisor) {
236 | if ($divisor == 0) {
237 | return 0;
238 | }
239 | return $number / $divisor;
240 | }
241 | }
242 |
--------------------------------------------------------------------------------
/src/regulate.php:
--------------------------------------------------------------------------------
1 | 000000)
166 | *
167 | * @param string &$hex_str The hex string to modify
168 | * @return void
169 | */
170 | public static function _expand_shorthand(string &$hex_str) {
171 | if (strlen($hex_str) === 3) {
172 | $r = $hex_str[0];
173 | $g = $hex_str[1];
174 | $b = $hex_str[2];
175 | $hex_str = $r.$r.$g.$g.$b.$b;
176 | }
177 | }
178 |
179 | /**
180 | * Verify that the hex string is actually a hex string. If not force it to
181 | * '000000'
182 | *
183 | * @param string &$hex_str The hex string to modify
184 | * @return void
185 | */
186 | public static function _validate_hex_str(string &$hex_str, bool $check_only = FALSE) :bool {
187 | if (preg_match('/\A#?(?:[0-9a-f]{3}|[0-9a-f]{6})\Z/i', $hex_str)) {
188 | return TRUE;
189 | }
190 | if (!$check_only) {
191 | error::trigger(error::INVALID_ARGUMENT, sprintf(
192 | 'The input of %s::%s() was not a valid hex string, forcing value to 000000',
193 | __CLASS__,
194 | __FUNCTION__
195 | ));
196 | $hex_str = '000000';
197 | }
198 | return FALSE;
199 | }
200 |
201 | /**
202 | * Force an array to have specific lower-case keys. If the array is an indexed
203 | * array and the keys are provided, convert it to an associative array.
204 | *
205 | * @param array &$array The array to be modified
206 | * @return void
207 | */
208 | public static function standardize_array(array &$array, array $keys = []) {
209 | if (!empty($keys) && array_keys($array) === range(0, count($array) - 1) && count($array) == count($keys)) {
210 | $array = array_combine($keys, $array);
211 | } else {
212 | $array = array_change_key_case($array) + array_fill_keys($keys, 0);
213 | }
214 | }
215 |
216 | /**
217 | * Absolute and divide any number so it fits between 0 and $max
218 | *
219 | * @param float $number The original number
220 | * @param float $max The maximum value $number should be
221 | * @return float The resulting number as a float
222 | */
223 | public static function max(float $number, float $max) :float {
224 | $max = abs($max);
225 | if ($number > $max) {
226 | $number -= floor($number / ($max + 1)) * ($max + 1);
227 | }
228 | return $number;
229 | }
230 |
231 | /**
232 | * Simple dividing method to handle division by 0
233 | *
234 | * @param float $number The number to divide
235 | * @param float $divisor The number to divide by
236 | * @return float The result
237 | */
238 | public static function div(float $number, float $divisor) :float {
239 | if ($divisor == 0) {
240 | return 0;
241 | }
242 | return $number / $divisor;
243 | }
244 | }
245 |
--------------------------------------------------------------------------------
/php5/color.php:
--------------------------------------------------------------------------------
1 | hsl;
63 | return $temp();
64 | }
65 |
66 | /**
67 | * Serializes this object.
68 | *
69 | * @return string The serialized object
70 | */
71 | public function serialize() {
72 | return json_encode($this->rgb + array('a' => $this->alpha));
73 | }
74 |
75 | /**
76 | * Unserializes this object.
77 | *
78 | * @param string $serialized The object as a serialized string
79 | * @return void
80 | */
81 | public function unserialize($serialized) {
82 | $unserialized = (array) json_decode((string) $serialized);
83 | regulate::rgb_array($unserialized);
84 | $this->import_rgb($unserialized);
85 | }
86 |
87 | /**
88 | * Serializes this object into JSON.
89 | *
90 | * @return string The serialized object
91 | */
92 | public function jsonSerialize() {
93 | return $this->rgb + array('a' => $this->alpha);
94 | }
95 |
96 | /**
97 | * Determine the type of color being used.
98 | *
99 | * @param mized $color The color in question
100 | * @return string The color type as a string, returns 'error' if $color is invalid
101 | */
102 | public static function get_type($color) {
103 | if (is_array($color)) {
104 | return static::_get_array_type($color);
105 | } elseif (is_string($color)) {
106 | return 'hex';
107 | } elseif (is_int($color)) {
108 | return 'int';
109 | }
110 | return 'error';
111 | }
112 |
113 | /**
114 | * Determine the type of color being used if it is an array.
115 | *
116 | * @param array $color The color in question
117 | * @return string The color type as a string, returns 'error' if $color is invalid
118 | */
119 | protected static function _get_array_type($color) {
120 | $color = array_change_key_case($color);
121 | unset($color['a']); // ignore alpha channel
122 | ksort($color);
123 | $type = implode('', array_keys($color));
124 | $types = array(
125 | 'bgr' => 'rgb',
126 | 'hls' => 'hsl',
127 | 'bhs' => 'hsb',
128 | 'ckmy' => 'cmyk'
129 | );
130 | if (isset($types[$type])) {
131 | return $types[$type];
132 | }
133 | return 'error';
134 | }
135 |
136 | /**
137 | * Get (and set) the alpha channel
138 | *
139 | * @param mixed $new_alpha If numeric, the alpha channel is set to this value
140 | * @return float The current alpha value
141 | */
142 | public function alpha($new_alpha = NULL) {
143 | if (is_numeric($new_alpha)) {
144 | $this->alpha = (float) $new_alpha;
145 | }
146 | return $this->alpha;
147 | }
148 |
149 | /**
150 | * Handles general errors when importing, and forces the input to be valid.
151 | *
152 | * @return void
153 | */
154 | protected function import_error() {
155 | error::call(sprintf(
156 | 'The color supplied to %s\'s constructor was not valid',
157 | __CLASS__
158 | ));
159 | $this->import_rgb(array(0, 0, 0));
160 | }
161 |
162 | /**
163 | * Import the alpha channel from a color array, or create one if it doesn't exist
164 | *
165 | * @param array $color The color array to check
166 | * @return void
167 | */
168 | protected function import_alpha($color) {
169 | if (isset($color['a'])) {
170 | $this->alpha = (float) $color['a'];
171 | } else {
172 | $this->alpha = 100.0;
173 | }
174 | }
175 |
176 | /**
177 | * Handles importing of another instance of color
178 | *
179 | * @return void
180 | */
181 | protected function import_color($color) {
182 | $this->rgb = $color->rgb;
183 | $this->hex = $color->hex;
184 | $this->hsl = clone $color->hsl;
185 | $this->alpha = $color->alpha;
186 | }
187 |
188 | /**
189 | * Imports a RGB array.
190 | *
191 | * @param array $color Array with offsets 'r', 'g', 'b'
192 | * @return void
193 | */
194 | public function import_rgb($color) {
195 | regulate::rgb_array($color);
196 | $this->rgb = array_intersect_key($color, array('r' => 0, 'g' => 0, 'b' => 0));
197 | $this->hex = convert::rgb_to_hex($this->rgb['r'], $this->rgb['g'], $this->rgb['b']);
198 | $this->hsl = new hsl($this->rgb);
199 | $this->import_alpha($color);
200 | }
201 |
202 | /**
203 | * Imports a hsl array.
204 | *
205 | * @param array $color Array with offsets 'h', 's', 'l'
206 | * @return void
207 | */
208 | public function import_hsl($color) {
209 | regulate::hsl_array($color);
210 | $this->rgb = convert::hsl_to_rgb($color['h'], $color['s'], $color['l']);
211 | $this->hsl = new hsl($this->rgb);
212 | $this->hex = convert::rgb_to_hex($this->rgb['r'], $this->rgb['g'], $this->rgb['b']);
213 | $this->import_alpha($color);
214 | }
215 |
216 | /**
217 | * Imports a hsb array.
218 | *
219 | * @param array $color Array with offsets 'h', 's', 'b'
220 | * @return void
221 | */
222 | public function import_hsb($color) {
223 | regulate::hsb_array($color);
224 | $this->rgb = convert::hsb_to_rgb($color['h'], $color['s'], $color['b']);
225 | $this->hsl = new hsl($this->rgb);
226 | $this->hex = convert::rgb_to_hex($this->rgb['r'], $this->rgb['g'], $this->rgb['b']);
227 | $this->import_alpha($color);
228 | }
229 |
230 | /**
231 | * Converts a hexadecimal string into an RGB array and imports it.
232 | *
233 | * @param string $color Hexadecimal string
234 | * @return void
235 | */
236 | public function import_hex($color) {
237 | regulate::hex($color);
238 | $this->import_rgb(convert::hex_to_rgb($color));
239 | }
240 |
241 | /**
242 | * Converts an integer to a hexadecimal string and imports it.
243 | *
244 | * @param int $color An integer
245 | * @return void
246 | */
247 | public function import_int($color) {
248 | regulate::hex_int($color);
249 | $this->import_hex(str_pad(base_convert($color, 10, 16), 6, '0', STR_PAD_LEFT));
250 | }
251 |
252 | /**
253 | * Imports a CMYK array
254 | *
255 | * @param array $color Array with offsets 'c', 'm', 'y', 'k'
256 | * @return void
257 | */
258 | public function import_cmyk($color) {
259 | regulate::cmyk_array($color);
260 | $this->import_rgb(convert::cmyk_to_rgb($color['c'], $color['m'], $color['y'], $color['k']));
261 | $this->import_alpha($color);
262 | }
263 | }
264 |
--------------------------------------------------------------------------------
/src/data/store.old.php:
--------------------------------------------------------------------------------
1 | hsl)();
72 | }
73 |
74 | /**
75 | * Serializes this object.
76 | *
77 | * @return string The serialized object
78 | */
79 | public function serialize() :string {
80 | return json_encode($this->rgb + ['a' => $this->alpha]);
81 | }
82 |
83 | /**
84 | * Unserializes this object.
85 | *
86 | * @param string $serialized The object as a serialized string
87 | * @return void
88 | */
89 | public function unserialize($serialized) {
90 | $unserialized = (array) json_decode((string) $serialized);
91 | regulate::rgb_array($unserialized);
92 | $this->import_rgb($unserialized);
93 | }
94 |
95 | /**
96 | * Serializes this object into JSON.
97 | *
98 | * @return string The serialized object
99 | */
100 | public function jsonSerialize() :array {
101 | return $this->rgb + ['a' => $this->alpha];
102 | }
103 |
104 | /**
105 | * Determine the type of color being used.
106 | *
107 | * @param mized $color The color in question
108 | * @return string The color type as a string, returns 'error' if $color is invalid
109 | */
110 | public static function get_type($color) :string {
111 | if (is_array($color)) {
112 | return static::_get_array_type($color);
113 | } elseif (is_string($color)) {
114 | // return static::_get_str_type($color);
115 | return 'str';
116 | } elseif (is_int($color)) {
117 | return 'int';
118 | }
119 | return 'error';
120 | }
121 |
122 | protected function _get_str_type(string $color) {
123 | $color = strtolower(str_replace(array(' ', "\t", "\n", "\r", "\0", "\x0B"), '', $color));
124 | if (regulate::_validate_hex_str($color, TRUE)) {
125 | return 'hex';
126 | } elseif (css::get($color, FALSE)) {
127 | return 'css';
128 | } elseif (x11::get($color)) {
129 | return 'x11';
130 | }
131 | return 'error';
132 | }
133 |
134 | /**
135 | * Determine the type of color being used if it is an array.
136 | *
137 | * @param array $color The color in question
138 | * @return string The color type as a string, returns 'error' if $color is invalid
139 | */
140 | protected static function _get_array_type(array $color) :string {
141 | $color = array_change_key_case($color);
142 | unset($color['a']); // ignore alpha channel
143 | ksort($color);
144 | $type = implode('', array_keys($color));
145 | $types = [
146 | 'bgr' => 'rgb',
147 | 'hls' => 'hsl',
148 | 'bhs' => 'hsb',
149 | 'ckmy' => 'cmyk'
150 | ];
151 | if (isset($types[$type])) {
152 | return $types[$type];
153 | }
154 | return 'error';
155 | }
156 |
157 | /**
158 | * Get (and set) the alpha channel
159 | *
160 | * @param mixed $new_alpha If numeric, the alpha channel is set to this value
161 | * @return float The current alpha value
162 | */
163 | public function alpha($new_alpha = NULL) :float {
164 | if (is_numeric($new_alpha)) {
165 | $this->alpha = (float) $new_alpha;
166 | }
167 | return $this->alpha;
168 | }
169 |
170 | /**
171 | * Handles general errors when importing, and forces the input to be valid.
172 | *
173 | * @return void
174 | */
175 | protected function import_error() {
176 | error::trigger(error::INVALID_COLOR, sprintf(
177 | 'The color supplied to %s\'s constructor was not valid',
178 | __CLASS__
179 | ));
180 | $this->import_rgb([0, 0, 0]);
181 | }
182 |
183 | /**
184 | * Import the alpha channel from a color array, or create one if it doesn't exist
185 | *
186 | * @param array $color The color array to check
187 | * @return void
188 | */
189 | protected function import_alpha(array $color) {
190 | if (isset($color['a'])) {
191 | $this->alpha = regulate::max((float) $color['a'], 100);
192 | } else {
193 | $this->alpha = 100.0;
194 | }
195 | }
196 |
197 | /**
198 | * Handles importing of another instance of color
199 | *
200 | * @return void
201 | */
202 | protected function import_color(data $color) {
203 | $this->rgb = $color->rgb;
204 | $this->hex = $color->hex;
205 | $this->hsl = clone $color->hsl;
206 | $this->alpha = $color->alpha;
207 | }
208 |
209 | /**
210 | * Imports a RGB array.
211 | *
212 | * @param array $color Array with offsets 'r', 'g', 'b'
213 | * @return void
214 | */
215 | public function import_rgb(array $color) {
216 | regulate::rgb_array($color);
217 | $this->rgb = array_intersect_key($color, ['r' => 0, 'g' => 0, 'b' => 0]);
218 | $this->hex = convert\rgb::to_hex($this->rgb);
219 | $this->hsl = new hsl($this->rgb);
220 | $this->import_alpha($color);
221 | }
222 |
223 | /**
224 | * Imports a hsl array.
225 | *
226 | * @param array $color Array with offsets 'h', 's', 'l'
227 | * @return void
228 | */
229 | public function import_hsl(array $color) {
230 | regulate::hsl_array($color);
231 | $this->rgb = convert\hsl::to_rgb($color);
232 | $this->hsl = new hsl($this->rgb); // [todo] This should taken from input
233 | $this->hex = convert\rgb::to_hex($this->rgb);
234 | $this->import_alpha($color);
235 | }
236 |
237 | /**
238 | * Imports a hsb array.
239 | *
240 | * @param array $color Array with offsets 'h', 's', 'b'
241 | * @return void
242 | */
243 | public function import_hsb(array $color) {
244 | regulate::hsb_array($color);
245 | $this->rgb = convert\hsb::to_rgb($color);
246 | $this->hsl = new hsl($this->rgb);
247 | $this->hex = convert\rgb::to_hex($this->rgb);
248 | $this->import_alpha($color);
249 | }
250 |
251 | /**
252 | * Converts a hexadecimal string into an RGB array and imports it.
253 | *
254 | * @param string $color Hexadecimal string
255 | * @return void
256 | */
257 | public function import_hex(string $color) {
258 | regulate::hex($color);
259 | $this->import_rgb(convert\hex::to_rgb($color));
260 | }
261 |
262 | public function import_str(string $color) {
263 | $color = strtolower(str_replace(array(' ', "\t", "\n", "\r", "\0", "\x0B"), '', $color));
264 | if (regulate::_validate_hex_str($color, TRUE)) {
265 | $this->import_hex($color);
266 | return;
267 | } elseif (preg_match('/\A(rgb|hsl)a?\((\d+),(\d+),(\d+)(?:,(\d|\d\.\d?|\.\d+))?\)\Z/i', $color, $match)) {
268 | $this->import_regex($match);
269 | return;
270 | } elseif ($x11 = x11::get($color)) {
271 | $this->import_rgb($x11);
272 | return;
273 | }
274 | $this->import_error();
275 | }
276 |
277 | public function import_regex(array $match) {
278 | $alpha = 100;
279 | if (isset($match[5])) {
280 | $alpha = (float) $match[5] * 100;
281 | }
282 | $color = array_combine(str_split($match[1].'a'), [$match[2], $match[3], $match[4], $alpha]);
283 | call_user_func([__CLASS__, 'import_'.$match[1]], $color);
284 | }
285 |
286 | /**
287 | * Converts an integer to a hexadecimal string and imports it.
288 | *
289 | * @param int $color An integer
290 | * @return void
291 | */
292 | public function import_int(int $color) {
293 | regulate::hex_int($color);
294 | $this->import_hex(str_pad(base_convert($color, 10, 16), 6, '0', STR_PAD_LEFT));
295 | }
296 |
297 | /**
298 | * Imports a CMYK array
299 | *
300 | * @param array $color Array with offsets 'c', 'm', 'y', 'k'
301 | * @return void
302 | */
303 | public function import_cmyk(array $color) {
304 | regulate::cmyk_array($color);
305 | $this->import_rgb(convert\cmyk::to_rgb($color['c'], $color['m'], $color['y'], $color['k']));
306 | $this->import_alpha($color);
307 | }
308 | }
309 |
--------------------------------------------------------------------------------
/php5/convert.php:
--------------------------------------------------------------------------------
1 | hexdec(substr($hex, 0, 2)),
27 | 'g' => hexdec(substr($hex, 2, 2)),
28 | 'b' => hexdec(substr($hex, 4, 2))
29 | );
30 | }
31 |
32 | /**
33 | * Convert a RBA array to a hex string
34 | *
35 | * @param int $r The red value (0 - 255)
36 | * @param int $g The green value (0 - 255)
37 | * @param int $b The blue value (0 - 255)
38 | * @return string The resulting hex string
39 | */
40 | public static function rgb_to_hex($r = 0, $g = 0, $b = 0) {
41 | return strtoupper(
42 | str_pad(dechex($r), 2, '0', STR_PAD_LEFT)
43 | .str_pad(dechex($g), 2, '0', STR_PAD_LEFT)
44 | .str_pad(dechex($b), 2, '0', STR_PAD_LEFT)
45 | );
46 | }
47 |
48 | /**
49 | * Convert a RBA array to a CMYK array
50 | *
51 | * @param float $r The red value (0 - 255)
52 | * @param float $g The green value (0 - 255)
53 | * @param float $b The blue value (0 - 255)
54 | * @return array The resulting CMYK array
55 | */
56 | public static function rgb_to_cmyk($r = 0.0, $g = 0.0, $b = 0.0) {
57 | $c = (255 - $r) / 255 * 100;
58 | $m = (255 - $g) / 255 * 100;
59 | $y = (255 - $b) / 255 * 100;
60 | $k = min(array($c,$m,$y));
61 | $c -= $k;
62 | $m -= $k;
63 | $y -= $k;
64 | return array(
65 | 'c' => round($c),
66 | 'm' => round($m),
67 | 'y' => round($y),
68 | 'k' => round($k)
69 | );
70 | }
71 |
72 | /**
73 | * Convert a CMYK array to a RGB array
74 | *
75 | * @param float $c The cyan value (0 - 100)
76 | * @param float $m The magenta value (0 - 100)
77 | * @param float $y The yellow value (0 - 100)
78 | * @param float $k The key (black) value (0 - 100)
79 | * @return array The resulting RGB array
80 | */
81 | public static function cmyk_to_rgb($c = 0.0, $m = 0.0, $y = 0.0, $k = 0.0) {
82 | $c /= 100;
83 | $m /= 100;
84 | $y /= 100;
85 | $k /= 100;
86 | $r = 1 - min(1, $c * (1 - $k) + $k);
87 | $g = 1 - min(1, $m * (1 - $k) + $k);
88 | $b = 1 - min(1, $y * (1 - $k) + $k);
89 | return array(
90 | 'r' => round($r * 255),
91 | 'g' => round($g * 255),
92 | 'b' => round($b * 255)
93 | );
94 | }
95 |
96 | /**
97 | * Convert a RGB array to a HSL array
98 | *
99 | * @param float $r The red value (0 - 255)
100 | * @param float $g The green value (0 - 255)
101 | * @param float $b The blue value (0 - 255)
102 | * @return array The resulting HSL array
103 | */
104 | public static function rgb_to_hsl($r = 0, $g = 0, $b = 0, $accuracy = 2) {
105 | $r /= 255;
106 | $g /= 255;
107 | $b /= 255;
108 | $min = min($r, $g, $b);
109 | $max = max($r, $g, $b);
110 | $delta = $max - $min;
111 | $h = 0;
112 | $s = 0;
113 | $l = ($max + $min) / 2;
114 |
115 | if ($max != $min) {
116 | $s = $delta / ($max + $min);
117 | if ($l >= 0.5) {
118 | $s = $delta / (2 - $max - $min);
119 | }
120 | static::_rgbhsl_hue($h, $r, $g, $b, $max, $delta);
121 | }
122 |
123 | return array(
124 | 'h' => round($h * 360, $accuracy),
125 | 's' => round($s * 100, $accuracy),
126 | 'l' => round($l * 100, $accuracy)
127 | );
128 | }
129 |
130 | /**
131 | * Color delta algorithm
132 | *
133 | * @param float $rgb The R, G, or B value
134 | * @param float $max The max RGB value
135 | * @param float $delta The delta value ($max - $min)
136 | * @return float The color delta
137 | */
138 | protected static function _rgbhsl_delta_rgb($rgb, $max, $delta) {
139 | return ((($max - $rgb) / 6) + ($delta / 2)) / $delta;
140 | }
141 |
142 | /**
143 | * Calculate the hue as a percentage from RGB
144 | *
145 | * @param float &$h The variable to modify as hue
146 | * @param float $r The red value as a percentage
147 | * @param float $g The green value as a percentage
148 | * @param float $b The blue value as a percentage
149 | * @param float $max The max RGB value
150 | * @param float $delta The delta value ($max - $min)
151 | * @return void
152 | */
153 | protected static function _rgbhsl_hue(&$h, $r, $g, $b, $max, $delta) {
154 | $delta_r = static::_rgbhsl_delta_rgb($r, $max, $delta);
155 | $delta_g = static::_rgbhsl_delta_rgb($g, $max, $delta);
156 | $delta_b = static::_rgbhsl_delta_rgb($b, $max, $delta);
157 |
158 | $h = (2 / 3) + $delta_g - $delta_r;
159 | if ($r == $max) {
160 | $h = $delta_b - $delta_g;
161 | } elseif ($g == $max) {
162 | $h = (1 / 3) + $delta_r - $delta_b;
163 | }
164 | if ($h < 0) {
165 | $h++;
166 | }
167 | }
168 |
169 | /**
170 | * Convert a HSL array to a RGB array
171 | *
172 | * @param float $h The hue value (0 - 360)
173 | * @param float $s The saturation value (0 - 100)
174 | * @param float $l The light value (0 - 100)
175 | * @return array The resulting RGB array
176 | */
177 | public static function hsl_to_rgb($h = 0.0, $s = 0.0, $l = 0.0) {
178 | $s /= 100;
179 | $l /= 100;
180 | $c = (1 - abs((2 * $l) - 1)) * $s;
181 | $x = $c * (1 - abs(fmod(($h / 60), 2) - 1));
182 | $m = $l - ($c / 2);
183 | $r = $c;
184 | $g = 0;
185 | $b = $x;
186 |
187 | if ($h < 180) {
188 | self::_hslrgb_low($r, $g, $b, $c, $x, $h);
189 | } elseif ($h < 300) {
190 | self::_hslrgb_high($r, $g, $b, $c, $x, $h);
191 | }
192 |
193 | return array(
194 | 'r' => (int) round(($r + $m) * 255),
195 | 'g' => (int) round(($g + $m) * 255),
196 | 'b' => (int) round(($b + $m) * 255)
197 | );
198 | }
199 |
200 | /**
201 | * Handle low hue values
202 | *
203 | * @param float &$r The red value to modify
204 | * @param float &$g The green value to modify
205 | * @param float &$b The blue value to modify
206 | * @param float $c Potential R, G, or B value
207 | * @param float $x Potential R, G, or B value
208 | * @param float $h The hue
209 | * @return void
210 | */
211 | private static function _hslrgb_low(&$r, &$g, &$b, $c, $x, $h) {
212 | if ($h < 60) {
213 | $r = $c;
214 | $g = $x;
215 | $b = 0;
216 | } elseif ($h < 120) {
217 | $r = $x;
218 | $g = $c;
219 | $b = 0;
220 | } else {
221 | $r = 0;
222 | $g = $c;
223 | $b = $x;
224 | }
225 | }
226 |
227 | /**
228 | * Handle high hue values
229 | *
230 | * @param float &$r The red value to modify
231 | * @param float &$g The green value to modify
232 | * @param float &$b The blue value to modify
233 | * @param float $c Potential R, G, or B value
234 | * @param float $x Potential R, G, or B value
235 | * @param float $h The hue
236 | * @return void
237 | */
238 | private static function _hslrgb_high(&$r, &$g, &$b, $c, $x, $h) {
239 | if ($h < 240) {
240 | $r = 0;
241 | $g = $x;
242 | $b = $c;
243 | } else {
244 | $r = $x;
245 | $g = 0;
246 | $b = $c;
247 | }
248 | }
249 |
250 | /**
251 | * Convert a RGB array to a HSB array
252 | *
253 | * @param float $r The red value (0 - 255)
254 | * @param float $g The green value (0 - 255)
255 | * @param float $b The blue value (0 - 255)
256 | * @return array The resulting HSB array
257 | */
258 | public static function rgb_to_hsb($r = 0.0, $g = 0.0, $b = 0.0, $accuracy = 3) {
259 | $r /= 255;
260 | $g /= 255;
261 | $b /= 255;
262 |
263 | $max = max($r, $g, $b);
264 | $min = min($r, $g, $b);
265 | $v = $max;
266 | $d = $max - $min;
267 | $s = regulate::div($d, $max);
268 | $h = 0; // achromatic
269 | if ($max != $min) {
270 | static::_rgbhsl_hue($h, $r, $g, $b, $max, $d);
271 | }
272 |
273 | $h = round($h * 360, $accuracy);
274 | $s = round($s * 100, $accuracy);
275 | $v = round($v * 100, $accuracy);
276 |
277 | return array('h' => $h, 's' => $s, 'b' => $v);
278 | }
279 |
280 | /**
281 | * Convert a HSB array to a RGB array
282 | *
283 | * @param float $h The hue value (0 - 360)
284 | * @param float $s The saturation value (0 - 100)
285 | * @param float $b The brightness value (0 - 100)
286 | * @return array The resulting RGB array
287 | */
288 | public static function hsb_to_rgb($h = 0.0, $s = 0.0, $v = 0.0, $accuracy = 3) {
289 | if ($v == 0) {
290 | return array('r' => 0, 'g' => 0, 'b' => 0);
291 | }
292 | $s /= 100;
293 | $v /= 100;
294 | $h /= 60;
295 | $i = floor($h);
296 | $f = $h - $i;
297 | $p = $v * (1 - $s);
298 | $q = $v * (1 - ($s * $f));
299 | $t = $v * (1 - ($s * (1 - $f)));
300 | $calc = array(array($v, $t, $p), array($q, $v, $p), array($p, $v, $t), array($p, $q, $v), array($t, $p, $v), array($v, $p, $q));
301 | return array('r' => round($calc[$i][0] * 255, $accuracy), 'g' => round($calc[$i][1] * 255, $accuracy), 'b' => round($calc[$i][2] * 255, $accuracy));
302 | }
303 | }
304 |
--------------------------------------------------------------------------------
/src/data/store.php:
--------------------------------------------------------------------------------
1 | 0,
88 | 'g' => 0,
89 | 'b' => 0
90 | );
91 | }
92 | if (in_array($type, static::$valid_imports)) {
93 | call_user_func([__CLASS__, 'import_'.$type], $color);
94 | } else {
95 | $this->__set($type, $color);
96 | }
97 | }
98 |
99 | public function __get($key) {
100 | if (!in_array($key, static::$valid_color_spaces)) {
101 | error::trigger(error::INVALID_ARGUMENT, sprintf(
102 | 'Cannot get color space "%s"',
103 | $key
104 | ));
105 | return $this->__get($this->current_space);
106 | }
107 | if (!$this->__isset($key)) {
108 | $this->color_spaces[$key] = static::_get_convert($this->color_spaces, $this->current_space, $key);
109 | }
110 | return (array) $this->color_spaces[$key];
111 | }
112 |
113 | public function __set($key, $value) {
114 | if (in_array($key, static::$valid_color_spaces)) {
115 | $color_space = __NAMESPACE__.'\\color\\space\\'.$key;
116 | $this->color_spaces[$key] = new $color_space($value);
117 | $this->current_space = $key;
118 | return $this->__get($key);
119 | }
120 | error::trigger(error::INVALID_ARGUMENT, sprintf(
121 | 'Cannot set color space "%s"',
122 | __CLASS__
123 | ));
124 | }
125 |
126 | public function __isset($key) {
127 | return isset($this->color_spaces[$key]);
128 | }
129 |
130 | public function __unset($key) {
131 | if ($this->__isset($key) && count($this->color_spaces) > 1) {
132 | unset($this->color_spaces);
133 | } elseif ($this->__isset($key)) {
134 | $this->clear('rgb', array(
135 | 'r' => 0,
136 | 'g' => 0,
137 | 'b' => 0
138 | ));
139 | }
140 | }
141 |
142 | protected static function _get_convert(array $color_spaces, string $current, string $to) {
143 | if (isset($color_spaces[$current])) {
144 | $from = $current;
145 | } else {
146 | reset($color_spaces);
147 | $from = key($color_spaces);
148 | $this->current_space = $from; // Original space was unset
149 | }
150 | $convert = call_user_func(array('\\projectcleverweb\\color\\convert\\'.$from, 'to_'.$to), $color_spaces[$from]);
151 | $space = __NAMESPACE__.'\\color\\space\\'.$to;
152 | return new $space($convert);
153 | }
154 |
155 | public function clear_cache() {
156 |
157 | if (is_callable([__CLASS__, 'import_'.$type])) {
158 | call_user_func([__CLASS__, 'import_'.$type], $color);
159 | } else {
160 | error::trigger();
161 | }
162 | }
163 |
164 | protected function _clear() {
165 | $this->color_spaces = array();
166 | }
167 |
168 | protected function get_space() {
169 | return $this->current_space;
170 | }
171 |
172 | protected function set_space(string $color_space) :string {
173 | if (in_array(static::$valid_color_spaces)) {
174 | $this->current_space = $color_space;
175 | }
176 | return $this->current_space;
177 | }
178 |
179 | /**
180 | * Serializes this object.
181 | *
182 | * @return string The serialized object
183 | */
184 | public function serialize() :string {
185 | return json_encode($this->rgb + ['a' => $this->alpha]);
186 | }
187 |
188 | /**
189 | * Unserializes this object.
190 | *
191 | * @param string $serialized The object as a serialized string
192 | * @return void
193 | */
194 | public function unserialize($serialized) {
195 | $unserialized = (array) json_decode((string) $serialized);
196 | regulate::rgb_array($unserialized);
197 | $this->import_rgb($unserialized);
198 | }
199 |
200 | /**
201 | * Serializes this object into JSON.
202 | *
203 | * @return string The serialized object
204 | */
205 | public function jsonSerialize() :array {
206 | return $this->color_spaces + ['alpha' => $this->alpha];
207 | }
208 |
209 | /**
210 | * Handles general errors when importing, and forces the input to be valid.
211 | *
212 | * @return void
213 | */
214 | protected function import_error() {
215 | error::trigger(error::INVALID_COLOR, sprintf(
216 | 'The color supplied to %s\'s constructor was not valid',
217 | __CLASS__
218 | ));
219 | $this->import_rgb([0, 0, 0]);
220 | }
221 |
222 | /**
223 | * Import the alpha channel from a color array, or create one if it doesn't exist
224 | *
225 | * @param array $color The color array to check
226 | * @return void
227 | */
228 | protected function import_alpha(array $color) {
229 | if (isset($color['a'])) {
230 | $this->alpha = regulate::max((float) $color['a'], 100);
231 | } else {
232 | $this->alpha = 100.0;
233 | }
234 | }
235 |
236 | /**
237 | * Handles importing of another instance of color
238 | *
239 | * @return void
240 | */
241 | protected function import_object(store $color) {
242 | $this->_clear();
243 | foreach ($this->color_spaces as $space => $data) {
244 | $color_space = __NAMESPACE__.'\\space\\'.$space;
245 | $this->color_spaces[$space] = new $color_space($data);
246 | }
247 | $this->current_space = $color->get_space();
248 | $this->alpha = $color->alpha;
249 | }
250 |
251 | /**
252 | * Imports a RGB array.
253 | *
254 | * @param array $color Array with offsets 'r', 'g', 'b'
255 | * @return void
256 | */
257 | public function import_rgb(array $color) {
258 | $this->_clear();
259 | $this->color_spaces['rgb'] = new color\space\rgb($color);
260 | $this->import_alpha($color);
261 | }
262 |
263 | /**
264 | * Imports a hsl array.
265 | *
266 | * @param array $color Array with offsets 'h', 's', 'l'
267 | * @return void
268 | */
269 | public function import_hsl(array $color) {
270 | $this->_clear();
271 | $this->color_spaces['hsl'] = new color\space\hsl($color);
272 | $this->import_alpha($color);
273 | }
274 |
275 | /**
276 | * Imports a hsb array.
277 | *
278 | * @param array $color Array with offsets 'h', 's', 'b'
279 | * @return void
280 | */
281 | public function import_hsb(array $color) {
282 | $this->_clear();
283 | $this->color_spaces['hsb'] = new color\space\hsb($color);
284 | $this->import_alpha($color);
285 | }
286 |
287 | /**
288 | * Imports a CMYK array
289 | *
290 | * @param array $color Array with offsets 'c', 'm', 'y', 'k'
291 | * @return void
292 | */
293 | public function import_cmyk(array $color) {
294 | $this->_clear();
295 | $this->color_spaces['cmyk'] = new color\space\cmyk($color);
296 | $this->import_alpha($color);
297 | }
298 |
299 | /**
300 | * Converts a hexadecimal string into an RGB array and imports it.
301 | *
302 | * @param string $color Hexadecimal string
303 | * @return void
304 | */
305 | public function import_hex(string $color) {
306 | $this->import_rgb(convert\hex::to_rgb($color));
307 | }
308 |
309 | /**
310 | * Converts a hexadecimal string into an RGB array and imports it.
311 | *
312 | * @param string $color Hexadecimal string
313 | * @return void
314 | */
315 | public function import_css(string $color) {
316 | // result will either be an RGB or HSL array
317 | self::__construct(css::get($color));
318 | }
319 |
320 | /**
321 | * Converts an integer to a hexadecimal string and imports it.
322 | *
323 | * @param int $color An integer
324 | * @return void
325 | */
326 | public function import_int(int $color) {
327 | regulate::hex_int($color);
328 | $this->import_hex(str_pad(base_convert($color, 10, 16), 6, '0', STR_PAD_LEFT));
329 | }
330 | }
331 |
--------------------------------------------------------------------------------
/php5/yiq_scheme.php:
--------------------------------------------------------------------------------
1 | &$hsl) {
189 | if ($i == 0) {
190 | $org = $hsl['h'];
191 | continue;
192 | }
193 | $hsl['h'] = static::yiq_adjust($org, $hsl['h'] - $org);
194 | }
195 |
196 | return $scheme;
197 | }
198 | }
199 |
--------------------------------------------------------------------------------
/meta/sample.php:
--------------------------------------------------------------------------------
1 | 72, 's' => 20, 'l' => 20)),
22 | new main(array('h' => 108, 's' => 30, 'l' => 30)),
23 | new main(array('h' => 144, 's' => 40, 'l' => 40)),
24 | new main(array('h' => 180, 's' => 50, 'l' => 50)),
25 | new main(array('h' => 216, 's' => 60, 'l' => 60)),
26 | new main(array('h' => 252, 's' => 70, 'l' => 70)),
27 | new main(array('h' => 288, 's' => 80, 'l' => 80)),
28 | new main(array('h' => 324, 's' => 90, 'l' => 90))
29 | ];
30 |
31 |
32 | $colors = array_reverse($colors);
33 |
34 | // Scheme functions and their definitions
35 | $funcs = [
36 | 'shades' => '5 different shades of one color. (unaffected by YIQ)',
37 | 'monochromatic' => '5 complementary shades of one color. (unaffected by YIQ)',
38 | 'analogous' => 'These colors are all close to each other on a color wheel.',
39 | 'complementary' => '2 of these colors are a different shade of the base color. The other 2 are a weighted opposite of the base color.',
40 | 'triad' => 'These colors are all equally distanced from each other on a color wheel, 2 of which have an alternate shade.',
41 | 'weighted_triad' => 'These colors are all similarly distanced from each other on a color wheel, 2 of which have an alternate shade. These colors are all slightly closer to the base color than in a normal triad.',
42 | 'tetrad' => '3 of these colors are all equally distanced from each other on a color wheel, plus 1 alternated shade for the base color and the 1 color that is opposite of the base color.',
43 | 'weighted_tetrad' => '3 of these colors are all similarly distanced from each other on a color wheel, the base color has an alternate shade, and there is a weighted opposite color. These colors are all slightly closer to the base color than in a normal tetrad.',
44 | 'compound' => 'These colors use mathematical offsets that usually complement each other well, and can highlight the base color.',
45 | 'rectangular' => '4 of these colors form a rectangle on a color wheel, and 1 color is an alternate shade for the base color.'
46 | ];
47 | $fmt =
48 | '
'.PHP_EOL;
58 | $output = '';
59 | $output .= '
';
60 | foreach ($funcs as $name => $desc) {
61 | $output .= '
';
62 | $output .= sprintf(
63 | '',
64 | ucwords(str_replace('_', ' ', $name)),
65 | $desc
66 | );
67 | $output .= '
';
68 | }
69 | $output .= '
';
70 | foreach ($colors as $i => $color) {
71 | $rgb = $color->rgb();
72 | $hex = $color->hex();
73 | $hex_text = $color->is_dark() ? 'FFFFFF' : '000000';
74 | $hsl = $color->hsl();
75 | $hsb = $color->hsb();
76 | $cmyk = $color->cmyk();
77 | $background = sprintf(' style="background: #%s"', $color->is_dark() ? 'FFFFFF' : '282828');
78 | $header_bg = $color->is_dark() ? '' : ' inverted';
79 | $output .= sprintf(
80 | '
81 |
85 |
',
86 | $hex,
87 | $hex_text,
88 | implode(',', array_slice($rgb, 0, 3)),
89 | implode(',', array_slice($hsl, 0, 3)),
90 | implode(',', array_slice($hsb, 0, 3)),
91 | implode(',', array_slice($cmyk, 0, 4))
92 | );
93 | foreach ($funcs as $func => $desc) {
94 | $output .= '
';
95 |
96 | $scheme = $color->scheme($func, 'hsl');
97 | $yiq_scheme = $color->yiq_scheme($func, 'hsl');
98 | $schemes = array();
99 | foreach ($scheme as $key => $color_scheme) {
100 | $color_scheme = new main($color_scheme);
101 | $yiq_color_scheme = new main($yiq_scheme[$key]);
102 | $schemes['std'][$key] = array(
103 | 'rgb' => $color_scheme->rgb(),
104 | 'hex' => $color_scheme->hex(),
105 | 'text' => $color_scheme->is_dark() ? 'FFFFFF' : '000000'
106 | );
107 | $schemes['yiq'][$key] = array(
108 | 'rgb' => $yiq_color_scheme->rgb(),
109 | 'hex' => $yiq_color_scheme->hex(),
110 | 'text' => $yiq_color_scheme->is_dark() ? 'FFFFFF' : '000000'
111 | );
112 | unset($color_scheme, $yiq_color_scheme);
113 | }
114 |
115 | $adobe = sprintf(
116 | 'https://color.adobe.com/create/color-wheel/?base=2&rule=Custom&selected=2&name=%s&mode=hsv&rgbvalues=%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s&swatchOrder=0,1,2,3,4',
117 | urlencode(sprintf('Hex %s - %s', $hex, ucwords(str_replace('_', ' ', $func)))),
118 | $schemes['std'][1]['rgb']['r'] / 255,
119 | $schemes['std'][1]['rgb']['g'] / 255,
120 | $schemes['std'][1]['rgb']['b'] / 255,
121 | $schemes['std'][2]['rgb']['r'] / 255,
122 | $schemes['std'][2]['rgb']['g'] / 255,
123 | $schemes['std'][2]['rgb']['b'] / 255,
124 | $schemes['std'][0]['rgb']['r'] / 255,
125 | $schemes['std'][0]['rgb']['g'] / 255,
126 | $schemes['std'][0]['rgb']['b'] / 255,
127 | $schemes['std'][3]['rgb']['r'] / 255,
128 | $schemes['std'][3]['rgb']['g'] / 255,
129 | $schemes['std'][3]['rgb']['b'] / 255,
130 | $schemes['std'][4]['rgb']['r'] / 255,
131 | $schemes['std'][4]['rgb']['g'] / 255,
132 | $schemes['std'][4]['rgb']['b'] / 255
133 | );
134 | $yiq_adobe = sprintf(
135 | 'https://color.adobe.com/create/color-wheel/?base=2&rule=Custom&selected=2&name=%s&mode=hsv&rgbvalues=%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s&swatchOrder=0,1,2,3,4',
136 | urlencode(sprintf('Hex %s - %s', $hex, 'YIQ '.ucwords(str_replace('_', ' ', $func)))),
137 | $schemes['yiq'][1]['rgb']['r'] / 255,
138 | $schemes['yiq'][1]['rgb']['g'] / 255,
139 | $schemes['yiq'][1]['rgb']['b'] / 255,
140 | $schemes['yiq'][2]['rgb']['r'] / 255,
141 | $schemes['yiq'][2]['rgb']['g'] / 255,
142 | $schemes['yiq'][2]['rgb']['b'] / 255,
143 | $schemes['yiq'][0]['rgb']['r'] / 255,
144 | $schemes['yiq'][0]['rgb']['g'] / 255,
145 | $schemes['yiq'][0]['rgb']['b'] / 255,
146 | $schemes['yiq'][3]['rgb']['r'] / 255,
147 | $schemes['yiq'][3]['rgb']['g'] / 255,
148 | $schemes['yiq'][3]['rgb']['b'] / 255,
149 | $schemes['yiq'][4]['rgb']['r'] / 255,
150 | $schemes['yiq'][4]['rgb']['g'] / 255,
151 | $schemes['yiq'][4]['rgb']['b'] / 255
152 | );
153 |
154 | $output .= sprintf(
155 | '',
156 | ucwords(str_replace('_', ' ', $func)),
157 | $adobe,
158 | $yiq_adobe
159 | );
160 | $output .= sprintf(
161 | $fmt,
162 | $i, // %1$s
163 | $schemes['std'][0]['hex'], // %2$s
164 | $schemes['std'][0]['text'], // %3$s
165 | $schemes['std'][1]['hex'], // %4$s
166 | $schemes['std'][1]['text'], // %5$s
167 | $schemes['std'][2]['hex'], // %6$s
168 | $schemes['std'][2]['text'], // %7$s
169 | $schemes['std'][3]['hex'], // %8$s
170 | $schemes['std'][3]['text'], // %9$s
171 | $schemes['std'][4]['hex'], // %10$s
172 | $schemes['std'][4]['text'] // %11$s
173 | );
174 | if (!in_array($func, array('shades', 'monochromatic'))) {
175 | $output .= '
'.PHP_EOL;
176 | $output .= sprintf(
177 | $fmt,
178 | $i, // %1$s
179 | $schemes['yiq'][0]['hex'], // %2$s
180 | $schemes['yiq'][0]['text'], // %3$s
181 | $schemes['yiq'][1]['hex'], // %4$s
182 | $schemes['yiq'][1]['text'], // %5$s
183 | $schemes['yiq'][2]['hex'], // %6$s
184 | $schemes['yiq'][2]['text'], // %7$s
185 | $schemes['yiq'][3]['hex'], // %8$s
186 | $schemes['yiq'][3]['text'], // %9$s
187 | $schemes['yiq'][4]['hex'], // %10$s
188 | $schemes['yiq'][4]['text'] // %11$s
189 | );
190 | } else {
191 | $output .= '
'.PHP_EOL;
192 | }
193 | $output .= '
';
194 | }
195 | }
196 | $output .= '
';
197 |
198 | file_put_contents(__DIR__.'/sample.html', $output);
199 |
--------------------------------------------------------------------------------
/src/yiq_scheme.php:
--------------------------------------------------------------------------------
1 | &$hsl) {
189 | if ($i == 0) {
190 | $org = $hsl['h'];
191 | continue;
192 | }
193 | $hsl['h'] = static::yiq_adjust($org, $hsl['h'] - $org);
194 | }
195 |
196 | return $scheme;
197 | }
198 | }
199 |
--------------------------------------------------------------------------------
/src/data/color/x11.php:
--------------------------------------------------------------------------------
1 | array('r' => 240, 'g' => 248, 'b' => 255),
23 | 'antiquewhite' => array('r' => 250, 'g' => 235, 'b' => 215),
24 | 'aqua' => array('r' => 0, 'g' => 255, 'b' => 255),
25 | 'aquamarine' => array('r' => 127, 'g' => 255, 'b' => 212),
26 | 'azure' => array('r' => 240, 'g' => 255, 'b' => 255),
27 | 'beige' => array('r' => 245, 'g' => 245, 'b' => 220),
28 | 'bisque' => array('r' => 255, 'g' => 228, 'b' => 196),
29 | 'black' => array('r' => 0, 'g' => 0, 'b' => 0),
30 | 'blanchedalmond' => array('r' => 255, 'g' => 235, 'b' => 205),
31 | 'blue' => array('r' => 0, 'g' => 0, 'b' => 255),
32 | 'blueviolet' => array('r' => 138, 'g' => 43, 'b' => 226),
33 | 'brown' => array('r' => 165, 'g' => 42, 'b' => 42),
34 | 'burlywood' => array('r' => 222, 'g' => 184, 'b' => 135),
35 | 'cadetblue' => array('r' => 95, 'g' => 158, 'b' => 160),
36 | 'chartreuse' => array('r' => 127, 'g' => 255, 'b' => 0),
37 | 'chocolate' => array('r' => 210, 'g' => 105, 'b' => 30),
38 | 'coral' => array('r' => 255, 'g' => 127, 'b' => 80),
39 | 'cornflowerblue' => array('r' => 100, 'g' => 149, 'b' => 237),
40 | 'cornsilk' => array('r' => 255, 'g' => 248, 'b' => 220),
41 | 'crimson' => array('r' => 220, 'g' => 20, 'b' => 60),
42 | 'cyan' => array('r' => 0, 'g' => 255, 'b' => 255),
43 | 'darkblue' => array('r' => 0, 'g' => 0, 'b' => 139),
44 | 'darkcyan' => array('r' => 0, 'g' => 139, 'b' => 139),
45 | 'darkgoldenrod' => array('r' => 184, 'g' => 134, 'b' => 11),
46 | 'darkgray' => array('r' => 169, 'g' => 169, 'b' => 169),
47 | 'darkgreen' => array('r' => 0, 'g' => 100, 'b' => 0),
48 | 'darkgrey' => array('r' => 169, 'g' => 169, 'b' => 169),
49 | 'darkkhaki' => array('r' => 189, 'g' => 183, 'b' => 107),
50 | 'darkmagenta' => array('r' => 139, 'g' => 0, 'b' => 139),
51 | 'darkolivegreen' => array('r' => 85, 'g' => 107, 'b' => 47),
52 | 'darkorange' => array('r' => 255, 'g' => 140, 'b' => 0),
53 | 'darkorchid' => array('r' => 153, 'g' => 50, 'b' => 204),
54 | 'darkred' => array('r' => 139, 'g' => 0, 'b' => 0),
55 | 'darksalmon' => array('r' => 233, 'g' => 150, 'b' => 122),
56 | 'darkseagreen' => array('r' => 143, 'g' => 188, 'b' => 143),
57 | 'darkslateblue' => array('r' => 72, 'g' => 61, 'b' => 139),
58 | 'darkslategray' => array('r' => 47, 'g' => 79, 'b' => 79),
59 | 'darkslategrey' => array('r' => 47, 'g' => 79, 'b' => 79),
60 | 'darkturquoise' => array('r' => 0, 'g' => 206, 'b' => 209),
61 | 'darkviolet' => array('r' => 148, 'g' => 0, 'b' => 211),
62 | 'deeppink' => array('r' => 255, 'g' => 20, 'b' => 147),
63 | 'deepskyblue' => array('r' => 0, 'g' => 191, 'b' => 255),
64 | 'dimgray' => array('r' => 105, 'g' => 105, 'b' => 105),
65 | 'dimgrey' => array('r' => 105, 'g' => 105, 'b' => 105),
66 | 'dodgerblue' => array('r' => 30, 'g' => 144, 'b' => 255),
67 | 'firebrick' => array('r' => 178, 'g' => 34, 'b' => 34),
68 | 'floralwhite' => array('r' => 255, 'g' => 250, 'b' => 240),
69 | 'forestgreen' => array('r' => 34, 'g' => 139, 'b' => 34),
70 | 'fuchsia' => array('r' => 255, 'g' => 0, 'b' => 255),
71 | 'gainsboro' => array('r' => 220, 'g' => 220, 'b' => 220),
72 | 'ghostwhite' => array('r' => 248, 'g' => 248, 'b' => 255),
73 | 'gold' => array('r' => 255, 'g' => 215, 'b' => 0),
74 | 'goldenrod' => array('r' => 218, 'g' => 165, 'b' => 32),
75 | 'gray' => array('r' => 128, 'g' => 128, 'b' => 128),
76 | 'green' => array('r' => 0, 'g' => 128, 'b' => 0),
77 | 'greenyellow' => array('r' => 173, 'g' => 255, 'b' => 47),
78 | 'grey' => array('r' => 128, 'g' => 128, 'b' => 128),
79 | 'honeydew' => array('r' => 240, 'g' => 255, 'b' => 240),
80 | 'hotpink' => array('r' => 255, 'g' => 105, 'b' => 180),
81 | 'indianred' => array('r' => 205, 'g' => 92, 'b' => 92),
82 | 'indigo' => array('r' => 75, 'g' => 0, 'b' => 130),
83 | 'ivory' => array('r' => 255, 'g' => 255, 'b' => 240),
84 | 'khaki' => array('r' => 240, 'g' => 230, 'b' => 140),
85 | 'lavender' => array('r' => 230, 'g' => 230, 'b' => 250),
86 | 'lavenderblush' => array('r' => 255, 'g' => 240, 'b' => 245),
87 | 'lawngreen' => array('r' => 124, 'g' => 252, 'b' => 0),
88 | 'lemonchiffon' => array('r' => 255, 'g' => 250, 'b' => 205),
89 | 'lightblue' => array('r' => 173, 'g' => 216, 'b' => 230),
90 | 'lightcoral' => array('r' => 240, 'g' => 128, 'b' => 128),
91 | 'lightcyan' => array('r' => 224, 'g' => 255, 'b' => 255),
92 | 'lightgoldenrodyellow' => array('r' => 250, 'g' => 250, 'b' => 210),
93 | 'lightgray' => array('r' => 211, 'g' => 211, 'b' => 211),
94 | 'lightgreen' => array('r' => 144, 'g' => 238, 'b' => 144),
95 | 'lightgrey' => array('r' => 211, 'g' => 211, 'b' => 211),
96 | 'lightpink' => array('r' => 255, 'g' => 182, 'b' => 193),
97 | 'lightsalmon' => array('r' => 255, 'g' => 160, 'b' => 122),
98 | 'lightseagreen' => array('r' => 32, 'g' => 178, 'b' => 170),
99 | 'lightskyblue' => array('r' => 135, 'g' => 206, 'b' => 250),
100 | 'lightslategray' => array('r' => 119, 'g' => 136, 'b' => 153),
101 | 'lightslategrey' => array('r' => 119, 'g' => 136, 'b' => 153),
102 | 'lightsteelblue' => array('r' => 176, 'g' => 196, 'b' => 222),
103 | 'lightyellow' => array('r' => 255, 'g' => 255, 'b' => 224),
104 | 'lime' => array('r' => 0, 'g' => 255, 'b' => 0),
105 | 'limegreen' => array('r' => 50, 'g' => 205, 'b' => 50),
106 | 'linen' => array('r' => 250, 'g' => 240, 'b' => 230),
107 | 'magenta' => array('r' => 255, 'g' => 0, 'b' => 255),
108 | 'maroon' => array('r' => 128, 'g' => 0, 'b' => 0),
109 | 'mediumaquamarine' => array('r' => 102, 'g' => 205, 'b' => 170),
110 | 'mediumblue' => array('r' => 0, 'g' => 0, 'b' => 205),
111 | 'mediumorchid' => array('r' => 186, 'g' => 85, 'b' => 211),
112 | 'mediumpurple' => array('r' => 147, 'g' => 112, 'b' => 219),
113 | 'mediumseagreen' => array('r' => 60, 'g' => 179, 'b' => 113),
114 | 'mediumslateblue' => array('r' => 123, 'g' => 104, 'b' => 238),
115 | 'mediumspringgreen' => array('r' => 0, 'g' => 250, 'b' => 154),
116 | 'mediumturquoise' => array('r' => 72, 'g' => 209, 'b' => 204),
117 | 'mediumvioletred' => array('r' => 199, 'g' => 21, 'b' => 133),
118 | 'midnightblue' => array('r' => 25, 'g' => 25, 'b' => 112),
119 | 'mintcream' => array('r' => 245, 'g' => 255, 'b' => 250),
120 | 'mistyrose' => array('r' => 255, 'g' => 228, 'b' => 225),
121 | 'moccasin' => array('r' => 255, 'g' => 228, 'b' => 181),
122 | 'navajowhite' => array('r' => 255, 'g' => 222, 'b' => 173),
123 | 'navy' => array('r' => 0, 'g' => 0, 'b' => 128),
124 | 'oldlace' => array('r' => 253, 'g' => 245, 'b' => 230),
125 | 'olive' => array('r' => 128, 'g' => 128, 'b' => 0),
126 | 'olivedrab' => array('r' => 107, 'g' => 142, 'b' => 35),
127 | 'orange' => array('r' => 255, 'g' => 165, 'b' => 0),
128 | 'orangered' => array('r' => 255, 'g' => 69, 'b' => 0),
129 | 'orchid' => array('r' => 218, 'g' => 112, 'b' => 214),
130 | 'palegoldenrod' => array('r' => 238, 'g' => 232, 'b' => 170),
131 | 'palegreen' => array('r' => 152, 'g' => 251, 'b' => 152),
132 | 'paleturquoise' => array('r' => 175, 'g' => 238, 'b' => 238),
133 | 'palevioletred' => array('r' => 219, 'g' => 112, 'b' => 147),
134 | 'papayawhip' => array('r' => 255, 'g' => 239, 'b' => 213),
135 | 'peachpuff' => array('r' => 255, 'g' => 218, 'b' => 185),
136 | 'peru' => array('r' => 205, 'g' => 133, 'b' => 63),
137 | 'pink' => array('r' => 255, 'g' => 192, 'b' => 203),
138 | 'plum' => array('r' => 221, 'g' => 160, 'b' => 221),
139 | 'powderblue' => array('r' => 176, 'g' => 224, 'b' => 230),
140 | 'purple' => array('r' => 128, 'g' => 0, 'b' => 128),
141 | 'red' => array('r' => 255, 'g' => 0, 'b' => 0),
142 | 'rosybrown' => array('r' => 188, 'g' => 143, 'b' => 143),
143 | 'royalblue' => array('r' => 65, 'g' => 105, 'b' => 225),
144 | 'saddlebrown' => array('r' => 139, 'g' => 69, 'b' => 19),
145 | 'salmon' => array('r' => 250, 'g' => 128, 'b' => 114),
146 | 'sandybrown' => array('r' => 244, 'g' => 164, 'b' => 96),
147 | 'seagreen' => array('r' => 46, 'g' => 139, 'b' => 87),
148 | 'seashell' => array('r' => 255, 'g' => 245, 'b' => 238),
149 | 'sienna' => array('r' => 160, 'g' => 82, 'b' => 45),
150 | 'silver' => array('r' => 192, 'g' => 192, 'b' => 192),
151 | 'skyblue' => array('r' => 135, 'g' => 206, 'b' => 235),
152 | 'slateblue' => array('r' => 106, 'g' => 90, 'b' => 205),
153 | 'slategray' => array('r' => 112, 'g' => 128, 'b' => 144),
154 | 'slategrey' => array('r' => 112, 'g' => 128, 'b' => 144),
155 | 'snow' => array('r' => 255, 'g' => 250, 'b' => 250),
156 | 'springgreen' => array('r' => 0, 'g' => 255, 'b' => 127),
157 | 'steelblue' => array('r' => 70, 'g' => 130, 'b' => 180),
158 | 'tan' => array('r' => 210, 'g' => 180, 'b' => 140),
159 | 'teal' => array('r' => 0, 'g' => 128, 'b' => 128),
160 | 'thistle' => array('r' => 216, 'g' => 191, 'b' => 216),
161 | 'tomato' => array('r' => 255, 'g' => 99, 'b' => 71),
162 | 'turquoise' => array('r' => 64, 'g' => 224, 'b' => 208),
163 | 'violet' => array('r' => 238, 'g' => 130, 'b' => 238),
164 | 'wheat' => array('r' => 245, 'g' => 222, 'b' => 179),
165 | 'white' => array('r' => 255, 'g' => 255, 'b' => 255),
166 | 'whitesmoke' => array('r' => 245, 'g' => 245, 'b' => 245),
167 | 'yellow' => array('r' => 255, 'g' => 255, 'b' => 0),
168 | 'yellowgreen' => array('r' => 154, 'g' => 205, 'b' => 50)
169 | );
170 |
171 | /**
172 | * Gets a X11 color as RGB if it exists, otherwise returns FALSE.
173 | *
174 | * @param string $color The color name to search for
175 | * @return array|bool Returns a RGB color array if it exists, FALSE otherwise.
176 | */
177 | public static function get(string $color) {
178 | $color = strtolower(trim($color));
179 | if (isset(static::$map[$color])) {
180 | return static::$map[$color];
181 | }
182 | return FALSE;
183 | }
184 | }
185 |
--------------------------------------------------------------------------------
/testing/tests/05_SchemeTest.php:
--------------------------------------------------------------------------------
1 | vars['conversions'] as $hex => $conv) {
16 | $schemes = [
17 | scheme::analogous_set($conv['hsl']['h'], $conv['hsl']['s'], $conv['hsl']['l']),
18 | scheme::analogous_set($conv['hsl']['h'], $conv['hsl']['s'], $conv['hsl']['l'], TRUE),
19 | scheme::analogous_set($conv['hsl']['h'], $conv['hsl']['s'], $conv['hsl']['l'], FALSE)
20 | ];
21 | foreach ($schemes as $scheme) {
22 | $this->assertEquals(5, count($scheme));
23 | $this->assertEquals($scheme[0], $conv['hsl']);
24 | foreach ($scheme as $key => $color) {
25 | $this->assertEquals(['h', 's', 'l'], array_keys($color));
26 | $diff = $color;
27 | regulate::hsl_array($color);
28 | $this->assertEquals($diff, $color);
29 | }
30 | }
31 | }
32 | }
33 |
34 | /**
35 | * @test
36 | */
37 | public function Complementary_Set() {
38 | foreach ($this->vars['conversions'] as $hex => $conv) {
39 | $schemes = [
40 | scheme::complementary_set($conv['hsl']['h'], $conv['hsl']['s'], $conv['hsl']['l']),
41 | scheme::complementary_set($conv['hsl']['h'], $conv['hsl']['s'], $conv['hsl']['l'], TRUE),
42 | scheme::complementary_set($conv['hsl']['h'], $conv['hsl']['s'], $conv['hsl']['l'], FALSE)
43 | ];
44 | foreach ($schemes as $scheme) {
45 | $this->assertEquals(5, count($scheme));
46 | $this->assertEquals($scheme[0], $conv['hsl']);
47 | foreach ($scheme as $key => $color) {
48 | $this->assertEquals(['h', 's', 'l'], array_keys($color));
49 | $diff = $color;
50 | regulate::hsl_array($color);
51 | $this->assertEquals($diff, $color);
52 | }
53 | }
54 | }
55 | }
56 |
57 | /**
58 | * @test
59 | */
60 | public function Compound_Set() {
61 | foreach ($this->vars['conversions'] as $hex => $conv) {
62 | $schemes = [
63 | scheme::compound_set($conv['hsl']['h'], $conv['hsl']['s'], $conv['hsl']['l']),
64 | scheme::compound_set($conv['hsl']['h'], $conv['hsl']['s'], $conv['hsl']['l'], TRUE),
65 | scheme::compound_set($conv['hsl']['h'], $conv['hsl']['s'], $conv['hsl']['l'], FALSE)
66 | ];
67 | foreach ($schemes as $scheme) {
68 | $this->assertEquals(5, count($scheme));
69 | $this->assertEquals($scheme[0], $conv['hsl']);
70 | foreach ($scheme as $key => $color) {
71 | $this->assertEquals(['h', 's', 'l'], array_keys($color));
72 | $diff = $color;
73 | regulate::hsl_array($color);
74 | $this->assertEquals($diff, $color);
75 | }
76 | }
77 | }
78 | }
79 |
80 | /**
81 | * @test
82 | */
83 | public function Monochromatic_Set() {
84 | foreach ($this->vars['conversions'] as $hex => $conv) {
85 | $schemes = [
86 | scheme::monochromatic_set($conv['hsl']['h'], $conv['hsl']['s'], $conv['hsl']['l']),
87 | scheme::monochromatic_set($conv['hsl']['h'], $conv['hsl']['s'], $conv['hsl']['l'], TRUE),
88 | scheme::monochromatic_set($conv['hsl']['h'], $conv['hsl']['s'], $conv['hsl']['l'], FALSE)
89 | ];
90 | foreach ($schemes as $scheme) {
91 | $this->assertEquals(5, count($scheme));
92 | $this->assertEquals($scheme[0], $conv['hsl']);
93 | foreach ($scheme as $key => $color) {
94 | $this->assertEquals(['h', 's', 'l'], array_keys($color));
95 | $diff = $color;
96 | regulate::hsl_array($color);
97 | $this->assertEquals($diff, $color);
98 | }
99 | }
100 | }
101 | }
102 |
103 | /**
104 | * @test
105 | */
106 | public function Shades_Set() {
107 | foreach ($this->vars['conversions'] as $hex => $conv) {
108 | $schemes = [
109 | scheme::shades_set($conv['hsl']['h'], $conv['hsl']['s'], $conv['hsl']['l']),
110 | scheme::shades_set($conv['hsl']['h'], $conv['hsl']['s'], $conv['hsl']['l'], TRUE),
111 | scheme::shades_set($conv['hsl']['h'], $conv['hsl']['s'], $conv['hsl']['l'], FALSE)
112 | ];
113 | foreach ($schemes as $scheme) {
114 | $this->assertEquals(5, count($scheme));
115 | $this->assertEquals($scheme[0], $conv['hsl']);
116 | foreach ($scheme as $key => $color) {
117 | $this->assertEquals(['h', 's', 'l'], array_keys($color));
118 | $diff = $color;
119 | regulate::hsl_array($color);
120 | $this->assertEquals($diff, $color);
121 | }
122 | }
123 | }
124 | }
125 |
126 | /**
127 | * @test
128 | */
129 | public function Tetrad_Set() {
130 | foreach ($this->vars['conversions'] as $hex => $conv) {
131 | $schemes = [
132 | scheme::tetrad_set($conv['hsl']['h'], $conv['hsl']['s'], $conv['hsl']['l']),
133 | scheme::tetrad_set($conv['hsl']['h'], $conv['hsl']['s'], $conv['hsl']['l'], TRUE),
134 | scheme::tetrad_set($conv['hsl']['h'], $conv['hsl']['s'], $conv['hsl']['l'], FALSE)
135 | ];
136 | foreach ($schemes as $scheme) {
137 | $this->assertEquals(5, count($scheme));
138 | $this->assertEquals($scheme[0], $conv['hsl']);
139 | foreach ($scheme as $key => $color) {
140 | $this->assertEquals(['h', 's', 'l'], array_keys($color));
141 | $diff = $color;
142 | regulate::hsl_array($color);
143 | $this->assertEquals($diff, $color);
144 | }
145 | }
146 | }
147 | }
148 |
149 | /**
150 | * @test
151 | */
152 | public function Weighted_Tetrad_Set() {
153 | foreach ($this->vars['conversions'] as $hex => $conv) {
154 | $schemes = [
155 | scheme::weighted_tetrad_set($conv['hsl']['h'], $conv['hsl']['s'], $conv['hsl']['l']),
156 | scheme::weighted_tetrad_set($conv['hsl']['h'], $conv['hsl']['s'], $conv['hsl']['l'], TRUE),
157 | scheme::weighted_tetrad_set($conv['hsl']['h'], $conv['hsl']['s'], $conv['hsl']['l'], FALSE)
158 | ];
159 | foreach ($schemes as $scheme) {
160 | $this->assertEquals(5, count($scheme));
161 | $this->assertEquals($scheme[0], $conv['hsl']);
162 | foreach ($scheme as $key => $color) {
163 | $this->assertEquals(['h', 's', 'l'], array_keys($color));
164 | $diff = $color;
165 | regulate::hsl_array($color);
166 | $this->assertEquals($diff, $color);
167 | }
168 | }
169 | }
170 | }
171 |
172 | /**
173 | * @test
174 | */
175 | public function Triad_Set() {
176 | foreach ($this->vars['conversions'] as $hex => $conv) {
177 | $schemes = [
178 | scheme::triad_set($conv['hsl']['h'], $conv['hsl']['s'], $conv['hsl']['l']),
179 | scheme::triad_set($conv['hsl']['h'], $conv['hsl']['s'], $conv['hsl']['l'], TRUE),
180 | scheme::triad_set($conv['hsl']['h'], $conv['hsl']['s'], $conv['hsl']['l'], FALSE)
181 | ];
182 | foreach ($schemes as $scheme) {
183 | $this->assertEquals(5, count($scheme));
184 | $this->assertEquals($scheme[0], $conv['hsl']);
185 | foreach ($scheme as $key => $color) {
186 | $this->assertEquals(['h', 's', 'l'], array_keys($color));
187 | $diff = $color;
188 | regulate::hsl_array($color);
189 | $this->assertEquals($diff, $color);
190 | }
191 | }
192 | }
193 | }
194 |
195 | /**
196 | * @test
197 | */
198 | public function Weighted_Triad_Set() {
199 | foreach ($this->vars['conversions'] as $hex => $conv) {
200 | $schemes = [
201 | scheme::weighted_triad_set($conv['hsl']['h'], $conv['hsl']['s'], $conv['hsl']['l']),
202 | scheme::weighted_triad_set($conv['hsl']['h'], $conv['hsl']['s'], $conv['hsl']['l'], TRUE),
203 | scheme::weighted_triad_set($conv['hsl']['h'], $conv['hsl']['s'], $conv['hsl']['l'], FALSE)
204 | ];
205 | foreach ($schemes as $scheme) {
206 | $this->assertEquals(5, count($scheme));
207 | $this->assertEquals($scheme[0], $conv['hsl']);
208 | foreach ($scheme as $key => $color) {
209 | $this->assertEquals(['h', 's', 'l'], array_keys($color));
210 | $diff = $color;
211 | regulate::hsl_array($color);
212 | $this->assertEquals($diff, $color);
213 | }
214 | }
215 | }
216 | }
217 |
218 | /**
219 | * @test
220 | */
221 | public function Rectangular_Set() {
222 | foreach ($this->vars['conversions'] as $hex => $conv) {
223 | $schemes = [
224 | scheme::rectangular_set($conv['hsl']['h'], $conv['hsl']['s'], $conv['hsl']['l']),
225 | scheme::rectangular_set($conv['hsl']['h'], $conv['hsl']['s'], $conv['hsl']['l'], TRUE),
226 | scheme::rectangular_set($conv['hsl']['h'], $conv['hsl']['s'], $conv['hsl']['l'], FALSE)
227 | ];
228 | foreach ($schemes as $scheme) {
229 | $this->assertEquals(5, count($scheme));
230 | $this->assertEquals($scheme[0], $conv['hsl']);
231 | foreach ($scheme as $key => $color) {
232 | $this->assertEquals(['h', 's', 'l'], array_keys($color));
233 | $diff = $color;
234 | regulate::hsl_array($color);
235 | $this->assertEquals($diff, $color);
236 | }
237 | }
238 | }
239 | }
240 |
241 | /**
242 | * @test
243 | */
244 | public function ReturnRGB() {
245 | foreach ($this->vars['conversions'] as $hex => $conv) {
246 | $scheme = scheme::rgb($conv['hsl']['h'], $conv['hsl']['s'], $conv['hsl']['l'], 'shades');
247 | $this->assertEquals(5, count($scheme));
248 | $this->assertEquals($scheme[0], $conv['rgb']);
249 | foreach ($scheme as $key => $color) {
250 | $this->assertEquals(['r', 'g', 'b'], array_keys($color));
251 | $diff = $color;
252 | regulate::rgb_array($color);
253 | $this->assertEquals($diff, $color);
254 | }
255 | }
256 | }
257 |
258 | /**
259 | * @test
260 | */
261 | public function ReturnHSL() {
262 | foreach ($this->vars['conversions'] as $hex => $conv) {
263 | $scheme = scheme::hsl($conv['hsl']['h'], $conv['hsl']['s'], $conv['hsl']['l'], 'shades');
264 | $this->assertEquals(5, count($scheme));
265 | $this->assertEquals($scheme[0], $conv['hsl']);
266 | foreach ($scheme as $key => $color) {
267 | $this->assertEquals(['h', 's', 'l'], array_keys($color));
268 | $diff = $color;
269 | regulate::hsl_array($color);
270 | $this->assertEquals($diff, $color);
271 | }
272 | }
273 | }
274 |
275 | /**
276 | * @test
277 | */
278 | public function ReturnHSB() {
279 | foreach ($this->vars['conversions'] as $hex => $conv) {
280 | $scheme = scheme::hsb($conv['hsl']['h'], $conv['hsl']['s'], $conv['hsl']['l'], 'shades');
281 | $this->assertEquals(5, count($scheme));
282 | $this->assertEquals($scheme[0], $conv['hsb']);
283 | foreach ($scheme as $key => $color) {
284 | $this->assertEquals(['h', 's', 'b'], array_keys($color));
285 | $diff = $color;
286 | regulate::hsb_array($color);
287 | $this->assertEquals($diff, $color);
288 | }
289 | }
290 | }
291 |
292 | /**
293 | * @test
294 | */
295 | public function ReturnHex() {
296 | foreach ($this->vars['conversions'] as $hex => $conv) {
297 | $scheme = scheme::hex($conv['hsl']['h'], $conv['hsl']['s'], $conv['hsl']['l'], 'shades');
298 | $this->assertEquals(5, count($scheme));
299 | $this->assertEquals($scheme[0], $hex);
300 | foreach ($scheme as $key => $color) {
301 | $diff = $color;
302 | regulate::hex($color);
303 | $this->assertEquals($diff, $color);
304 | }
305 | }
306 | }
307 |
308 | /**
309 | * @test
310 | */
311 | public function ReturnCMYK() {
312 | foreach ($this->vars['conversions'] as $hex => $conv) {
313 | $scheme = scheme::cmyk($conv['hsl']['h'], $conv['hsl']['s'], $conv['hsl']['l'], 'shades');
314 | $this->assertEquals(5, count($scheme));
315 | $this->assertEquals($scheme[0], $conv['cmyk']);
316 | foreach ($scheme as $key => $color) {
317 | $this->assertEquals(['c', 'm', 'y', 'k'], array_keys($color));
318 | $diff = $color;
319 | regulate::cmyk_array($color);
320 | $this->assertEquals($diff, $color);
321 | }
322 | }
323 | }
324 |
325 | /**
326 | * @test
327 | */
328 | public function Error() {
329 | $hsl = $this->vars['conversions']['FFFFFF']['hsl'];
330 | $result = scheme::hsl($hsl['h'], $hsl['s'], $hsl['l'], 'invalid');
331 | $this->assertEquals([], $result);
332 | }
333 | }
334 |
--------------------------------------------------------------------------------