Squiz Matrix  4.12.2
 All Data Structures Namespaces Functions Variables Pages
colour.inc
1 <?php
29 class Colour
30 {
31 
40  public static function colourPalette($name=null)
41  {
42  $palette = Array(
43  'aliceblue' => 'f0f8ff',
44  'antiquewhite' => 'faebd7',
45  'aqua' => '00ffff',
46  'aquamarine' => '7fffd4',
47  'azure' => 'f0ffff',
48  'beige' => 'f5f5dc',
49  'bisque' => 'ffe4c4',
50  'black' => '000000',
51  'blanchedalmond' => 'ffebcd',
52  'blue' => '0000ff',
53  'blueviolet' => '8a2be2',
54  'brown' => 'a52a2a',
55  'burlywood' => 'deb887',
56  'cadetblue' => '5f9ea0',
57  'chartreuse' => '7fff00',
58  'chocolate' => 'd2691e',
59  'coral' => 'ff7f50',
60  'cornflowerblue' => '6495ed',
61  'cornsilk' => 'fff8dc',
62  'crimson' => 'dc143c',
63  'cyan' => '00ffff',
64  'darkblue' => '00008b',
65  'darkcyan' => '008b8b',
66  'darkgoldenrod' => 'b8860b',
67  'darkgray' => 'a9a9a9',
68  'darkgreen' => '006400',
69  'darkkhaki' => 'bdb76b',
70  'darkmagenta' => '8b008b',
71  'darkolivegreen' => '556b2f',
72  'darkorange' => 'ff8c00',
73  'darkorchid' => '9932cc',
74  'darkred' => '8b0000',
75  'darksalmon' => 'e9967a',
76  'darkseagreen' => '8fbc8f',
77  'darkslateblue' => '483d8b',
78  'darkslategray' => '2f4f4f',
79  'darkturquoise' => '00ced1',
80  'darkviolet' => '9400d3',
81  'deeppink' => 'ff1493',
82  'deepskyblue' => '00bfff',
83  'dimgray' => '696969',
84  'dodgerblue' => '1e90ff',
85  'firebrick' => 'b22222',
86  'floralwhite' => 'fffaf0',
87  'forestgreen' => '228b22',
88  'fuchsia' => 'ff00ff',
89  'gainsboro' => 'dcdcdc',
90  'ghostwhite' => 'f8f8ff',
91  'gold' => 'ffd700',
92  'goldenrod' => 'daa520',
93  'gray' => '808080',
94  'green' => '008000',
95  'greenyellow' => 'adff2f',
96  'honeydew' => 'f0fff0',
97  'hotpink' => 'ff69b4',
98  'indianred' => 'cd5c5c',
99  'indigo' => '4b0082',
100  'ivory' => 'fffff0',
101  'khaki' => 'f0e68c',
102  'lavender' => 'e6e6fa',
103  'lavenderblush' => 'fff0f5',
104  'lawngreen' => '7cfc00',
105  'lemonchiffon' => 'fffacd',
106  'lightblue' => 'add8e6',
107  'lightcoral' => 'f08080',
108  'lightcyan' => 'e0ffff',
109  'lightgoldenrodyellow' => 'fafad2',
110  'lightgreen' => '90ee90',
111  'lightgrey' => 'd3d3d3',
112  'lightpink' => 'ffb6c1',
113  'lightsalmon' => 'ffa07a',
114  'lightseagreen' => '20b2aa',
115  'lightskyblue' => '87cefa',
116  'lightslategray' => '778899',
117  'lightsteelblue' => 'b0c4de',
118  'lightyellow' => 'ffffe0',
119  'lime' => '00ff00',
120  'limegreen' => '32cd32',
121  'linen' => 'faf0e6',
122  'magenta' => 'ff00ff',
123  'maroon' => '800000',
124  'mediumaquamarine' => '66cdaa',
125  'mediumblue' => '0000cd',
126  'mediumorchid' => 'ba55d3',
127  'mediumpurple' => '9370db',
128  'mediumseagreen' => '3cb371',
129  'mediumslateblue' => '7b68ee',
130  'mediumspringgreen' => '00fa9a',
131  'mediumturquoise' => '48d1cc',
132  'mediumvioletred' => 'c71585',
133  'midnightblue' => '191970',
134  'mintcream' => 'f5fffa',
135  'mistyrose' => 'ffe4e1',
136  'moccasin' => 'ffe4b5',
137  'navajowhite' => 'ffdead',
138  'navy' => '000080',
139  'oldlace' => 'fdf5e6',
140  'olive' => '808000',
141  'olivedrab' => '6b8e23',
142  'orange' => 'ffa500',
143  'orangered' => 'ff4500',
144  'orchid' => 'da70d6',
145  'palegoldenrod' => 'eee8aa',
146  'palegreen' => '98fb98',
147  'paleturquoise' => 'afeeee',
148  'palevioletred' => 'db7093',
149  'papayawhip' => 'ffefd5',
150  'peachpuff' => 'ffdab9',
151  'peru' => 'cd853f',
152  'pink' => 'ffc0cb',
153  'plum' => 'dda0dd',
154  'powderblue' => 'b0e0e6',
155  'purple' => '800080',
156  'red' => 'ff0000',
157  'rosybrown' => 'bc8f8f',
158  'royalblue' => '4169e1',
159  'saddlebrown' => '8b4513',
160  'salmon' => 'fa8072',
161  'sandybrown' => 'f4a460',
162  'seagreen' => '2e8b57',
163  'seashell' => 'fff5ee',
164  'sienna' => 'a0522d',
165  'silver' => 'c0c0c0',
166  'skyblue' => '87ceeb',
167  'slateblue' => '6a5acd',
168  'slategray' => '708090',
169  'snow' => 'fffafa',
170  'springgreen' => '00ff7f',
171  'steelblue' => '4682b4',
172  'tan' => 'd2b48c',
173  'teal' => '008080',
174  'thistle' => 'd8bfd8',
175  'tomato' => 'ff6347',
176  'turquoise' => '40e0d0',
177  'violet' => 'ee82ee',
178  'wheat' => 'f5deb3',
179  'white' => 'ffffff',
180  'whitesmoke' => 'f5f5f5',
181  'yellow' => 'ffff00',
182  'yellowgreen' => '9acd32'
183  );
184 
185  if (is_null($name)) {
186  return $palette;
187  } else {
188  return (empty($palette[$name])) ? '' : $palette[$name];
189  }
190  }//end colourPalette()
191 
192 
205  public static function rgb($r, $g, $b, $zero_to_one_range=true)
206  {
207 
208  if ($zero_to_one_range) {
209  return Array(
210  'r' => (($r >= 0) ? (($r <= 255) ? (double) ( ((double)$r) / 255.0) : 1) : 0),
211  'g' => (($g >= 0) ? (($g <= 255) ? (double) ( ((double)$g) / 255.0) : 1) : 0),
212  'b' => (($b >= 0) ? (($b <= 255) ? (double) ( ((double)$b) / 255.0) : 1) : 0)
213  );
214  } else {
215  return Array(
216  'r' => (($r >= 0) ? (($r <= 255) ? ((int) $r) : 255) : 0),
217  'g' => (($g >= 0) ? (($g <= 255) ? ((int) $g) : 255) : 0),
218  'b' => (($b >= 0) ? (($b <= 255) ? ((int) $b) : 255) : 0)
219  );
220  }
221 
222  }//end rgb()
223 
224 
237  public static function cmyk($c, $m, $y, $k)
238  {
239  $output = Array(
240  'c' => (($c >= 0) ? (($c <= 100) ? (double) ( ((double)$c) / 100.0) : 1) : 0),
241  'm' => (($g >= 0) ? (($m <= 100) ? (double) ( ((double)$m) / 100.0) : 1) : 0),
242  'y' => (($y >= 0) ? (($y <= 100) ? (double) ( ((double)$y) / 100.0) : 1) : 0),
243  'k' => (($k >= 0) ? (($k <= 100) ? (double) ( ((double)$k) / 100.0) : 1) : 0)
244  );
245  Colour::cmykCorrect($output);
246  return $output;
247 
248  }//end cmyk()
249 
250 
262  public static function hsv($h,$s,$v)
263  {
264  return Array('h' => $h, 's' => $s/100, 'v' => $v/100);
265 
266  }//end hsv()
267 
268 
278  public static function cmykToRgb($input)
279  {
280  $c = $input['c'];
281  $m = $input['m'];
282  $y = $input['y'];
283  $k = $input['k'];
284  $output = Array('r' => 0, 'g' => 0, 'b' => 0);
285 
286  if (($c + $k) < 1)
287  $output['r'] = 1 - ($c + $k);
288  else
289  $output['r'] = 0;
290 
291  if (($m + $k) < 1)
292  $output['g'] = 1 - ($m + $k);
293  else
294  $output['g'] = 0;
295 
296  if (($y + $k) < 1)
297  $output['b'] = 1 - ($y + $k);
298  else
299  $output['b'] = 0;
300 
301  return $output;
302 
303  }//end cmykToRgb()
304 
305 
315  public static function rgbToCmyk($input)
316  {
317  $r = $input['r'];
318  $g = $input['g'];
319  $b = $input['b'];
320 
321  $c = 1 - $r;
322  $m = 1 - $g;
323  $y = 1 - $b;
324 
325  if ($c < $m)
326  $k = $c;
327  else
328  $k = $m;
329 
330  if ($y < $k)
331  $k = $y;
332 
333  if ($k > 0) {
334  $c -= $k;
335  $m -= $k;
336  $y -= $k;
337  }
338 
339  $output = Array('c' => $c, 'm' => $m, 'y' => $y, 'k' => $k);
340 
341  Colour::cmykCorrect($output);
342 
343  return $output;
344 
345  }//end rgbToCmyk()
346 
347 
357  public static function cmykCorrect(&$input)
358  {
359  if ($input['c'] < $input['m'])
360  $min = $input['c'];
361  else
362  $min = $input['m'];
363 
364  if ($input['y'] < $min)
365  $min = $input['y'];
366 
367  if (($min + $input['k']) > 1)
368  $min = 1 - $input['k'];
369 
370  $input['c'] -= $min;
371  $input['m'] -= $min;
372  $input['y'] -= $min;
373  $input['k'] += $min;
374 
375  }//end cmykCorrect()
376 
377 
387  public static function rgbInvert($i)
388  {
389  return Array('r' => (1 - $i['r']), 'g' => (1 - $i['g']), 'b' => (1 - $i['b']));
390 
391  }//end rgbInvert()
392 
393 
403  public static function rgbToHtml($input)
404  {
405  return sprintf('%02x%02x%02x', $input['r'] * 255, $input['g'] * 255, $input['b'] * 255);
406 
407  }//end rgbToHtml()
408 
418  public static function intToHtml($input)
419  {
420  return sprintf('%06x', $input);
421 
422  }//end intToHtml()
423 
424 
435  public static function intToRgb($input, $zero_to_one_range=true)
436  {
437  $b = min($input % 256, 255);
438  $g = min(($input >> 8) % 256, 255);
439  $r = min($input >> 16, 255);
440  return Colour::rgb($r, $g, $b, $zero_to_one_range);
441 
442  }//end intToRgb()
443 
453  public static function htmlToHex($input)
454  {
455  // remove any hashes from the start
456  $input = preg_replace('/^#/', '', strtolower($input));
457  if (sprintf('%06x',hexdec($input)) != $input) {
458  // must be a colour name
459  if ($hex = Colour::colourPalette($input) ) {
460  $input = $hex;
461  }
462  }
463  return $input;
464 
465  }//end htmlToHex()
466 
477  public static function htmlToRgb($input, $zero_to_one_range=true)
478  {
479  $input = Colour::htmlToHex($input);
480  return Colour::rgb(
481  hexdec(substr($input, 0, 2)),
482  hexdec(substr($input, 2, 2)),
483  hexdec(substr($input, 4, 2)),
484  $zero_to_one_range
485  );
486 
487  }//end htmlToRgb()
488 
498  public static function htmlToInt($input)
499  {
500  return hexdec(Colour::htmlToHex($input));
501 
502  }//end htmlToInt()
503 
513  public static function rgbToInt($input)
514  {
515  return Colour::htmlToInt(Colour::rgbToHtml($input));
516 
517  }//end rgbToInt()
518 
532  public static function rgbToHsv($input)
533  {
534  $r = max(0,min(1,$input['r']));
535  $g = max(0,min(1,$input['g']));
536  $b = max(0,min(1,$input['b']));
537  $min = min($r,$g,$b);
538  $max = max($r,$g,$b);
539  if (!$max) { // Black
540  return Array('h' => -1, 's' => 0, 'v' => 0);
541  }
542  $delta = $max - $min;
543  $v = $max;
544  $s = $delta / $max;
545  if (!$s) { // Grey
546  return Array('h' => -1, 's' => 0, 'v' => $v);
547  }
548  if ($r == $max) {
549  // between yellow & magenta
550  $h = ($g - $b) / $delta;
551  } elseif ($g == $max) {
552  // between cyan & yellow
553  $h = 2 + ($b - $r) / $delta;
554  } else {
555  // between magenta & cyan
556  $h = 4 + ($r - $g) / $delta;
557  }
558  $h *= 60; // degrees
559  if ($h < 0) $h += 360;
560  return Array('h' => $h, 's' => $s, 'v' => $v);
561 
562  }//end rgbToHsv()
563 
573  public static function hsvToRgb($input)
574  {
575  $h = $input['h'] % 360;
576  $s = max(0,min(1,$input['s']));
577  $v = max(0,min(1,$input['v']));
578  if (!$s) { // Grey
579  return Array('r' => $v, 'g' => $v, 'b' => $v);
580  }
581  // Split into the six sections of the colour wheel
582  $h /= 60;
583  // Section number (0 - 5)
584  $i = floor($h);
585  // Amount through the sector towards the next one [0,1]
586  $f = $h - $i;
587  // Remember, $v is the value of the maximum colour [r,g,b]
588  // $p is the minimum colour, according to the saturation
589  $p = $v * (1 - $s);
590  // $q is the colour in between, assuming we're heading down
591  $q = $v * (1 - $s * $f );
592  // $tq is the colour in between, assuming we're heading up
593  $t = $v * (1 - $s * (1 - $f ));
594  switch ($i) {
595  case 0: // Between red and yellow
596  $r = $v;
597  $g = $t;
598  $b = $p;
599  break;
600  case 1: // Between yellow and green
601  $r = $q;
602  $g = $v;
603  $b = $p;
604  break;
605  case 2: // Between green and cyan
606  $r = $p;
607  $g = $v;
608  $b = $t;
609  break;
610  case 3: // Between cyan and blue
611  $r = $p;
612  $g = $q;
613  $b = $v;
614  break;
615  case 4: // Between blue and magenta
616  $r = $t;
617  $g = $p;
618  $b = $v;
619  break;
620  case 5: default: // Between magenta and red
621  $r = $v;
622  $g = $p;
623  $b = $q;
624  break;
625  }
626  return Array('r' => $r, 'g' => $g, 'b' => $b);
627 
628  }//end hsvToRgb()
629 
639  public static function htmlToHsv($input)
640  {
641  return Colour::rgbToHsv(Colour::htmlToRgb($input));
642 
643  }//end htmlToHsv()
644 
654  public static function hsvToHtml($input)
655  {
656  return Colour::rgbToHtml(Colour::hsvToRgb($input));
657 
658  }//end hsvToHtml()
659 
669  public static function contrastingShade($input)
670  {
671  $c = Colour::htmlToRgb($input);
672  $weight_r = $c['r'] * 0.75;
673  $weight_g = $c['g'] * 1.75; // Green's bright
674  $weight_b = $c['b'] * 0.5; // Blue's dim
675  if (($weight_r + $weight_g + $weight_b) >= 1.5) {
676  return '000000';
677  } else {
678  return 'ffffff';
679  }
680 
681  }//end contrastingShade()
682 
692  public static function twiceAsLight($input)
693  {
694  $c = Colour::htmlToRgb($input);
695  $c['r'] += ((1 - $c['r']) / 2);
696  $c['g'] += ((1 - $c['g']) / 2);
697  $c['b'] += ((1 - $c['b']) / 2);
698  return Colour::rgbToHtml($c);
699 
700  }//end twiceAsLight()
701 
711  public static function twiceAsDark($input)
712  {
713  $c = Colour::htmlToRgb($input);
714  $c['r'] /= 2;
715  $c['g'] /= 2;
716  $c['b'] /= 2;
717  return Colour::rgbToHtml($c);
718 
719  }//end twiceAsDark()
720 
721 
732  public static function adjustBrightness($input, $amount)
733  {
734  $c = Colour::htmlToRgb($input);
735  if ($amount > 0 && $amount <= 1) { // Going up !
736  $c['r'] += ((1 - $c['r']) * $amount);
737  $c['g'] += ((1 - $c['g']) * $amount);
738  $c['b'] += ((1 - $c['b']) * $amount);
739  } elseif ($amount < 0 && $amount >= -1) {
740  $c['r'] += ($c['r'] * $amount);
741  $c['g'] += ($c['g'] * $amount);
742  $c['b'] += ($c['b'] * $amount);
743  }
744  return Colour::rgbToHtml($c);
745 
746  }//end adjustBrightness()
747 
748 
759  public static function adjustContrast($input, $amount)
760  {
761  $c = Colour::htmlToRgb($input);
762  $avg = ($c['r'] + $c['g'] + $c['b']) / 3.0;
763  if ($amount < 0) {
764  if ($amount < -1) $amount = -1;
765  $c['r'] = ($avg * -$amount) + ($c['r'] * (1 + $amount));
766  $c['g'] = ($avg * -$amount) + ($c['g'] * (1 + $amount));
767  $c['b'] = ($avg * -$amount) + ($c['b'] * (1 + $amount));
768  } elseif ($amount > 0) {
769  if ($amount > 1) $amount = 1;
770  $c['r'] = ( (($c['r'] > $avg) ? 1 : 0) * $amount) + ($c['r'] * (1 - $amount));
771  $c['g'] = ( (($c['g'] > $avg) ? 1 : 0) * $amount) + ($c['g'] * (1 - $amount));
772  $c['b'] = ( (($c['b'] > $avg) ? 1 : 0) * $amount) + ($c['b'] * (1 - $amount));
773  }
774  return Colour::rgbToHtml($c);
775 
776  }//end adjustContrast()
777 
789  public static function mix($a, $b, $ratio=0.5)
790  {
791  $ratio = max(0,min(1,$ratio));
792  $a = Colour::htmlToRgb($a);
793  $b = Colour::htmlToRgb($b);
794  $c = Array(
795  'r' => $a['r'] * (1-$ratio) + $b['r'] * $ratio,
796  'g' => $a['g'] * (1-$ratio) + $b['g'] * $ratio,
797  'b' => $a['b'] * (1-$ratio) + $b['b'] * $ratio,
798  );
799  return Colour::rgbToHtml($c);
800 
801  }//end mix()
802 
813  public static function hueRotate($input,$degrees)
814  {
815  return Colour::hsvAdjust($input, $degrees, 0, 0);
816 
817  }//end hueRotate()
818 
829  public static function adjustSaturate($input,$amount)
830  {
831  return Colour::hsvAdjust($input, 0, $amount, 0);
832 
833  }//end adjustSaturate()
834 
845  public static function adjustLightness($input,$amount)
846  {
847  return Colour::hsvAdjust($input, 0, 0, $amount);
848 
849  }//end adjustLightness()
850 
851 
864  public static function hsvAdjust($input,$h,$s,$v)
865  {
866  $hsv = Colour::htmlToHsv($input);
867  if ($h != 0) {
868  $h = $h % 360.0;
869  if ($h < 0) $h = 360.0 + $h;
870  $hsv['h'] += $h;
871  while ($hsv['h'] > 360.0) $hsv['h'] -= 360.0;
872  }
873  if ($s != 0) {
874  if ($s > 0) $hsv['s'] += $s * (1 - $hsv['s']);
875  else $hsv['s'] += $s * $hsv['s'];
876  }
877  if ($v != 0) {
878  if ($v > 0) $hsv['v'] += $v * (1 - $hsv['v']);
879  else $hsv['v'] += $v * $hsv['v'];
880  }
881  return Colour::hsvToHtml($hsv);
882 
883  }//end hsvAdjust()
884 
896  public static function hsvDifference($a, $b)
897  {
898  $a = Colour::htmlToHsv($a);
899  $b = Colour::htmlToHsv($b);
900  $r['h'] = $b['h'] - $a['h'];
901  if (abs($r['h']) > 180.0) {
902  if ($r['h'] > 0) $r['h'] -= 360.0;
903  else $r['h'] += 360.0;
904  }
905  if ($b['s'] > $a['s']) $r['s'] = $b['s'] / (1 - $a['s']) - $a['s'];
906  else $r['s'] = ($b['s'] - $a['s']) / $a['s'];
907  if ($b['v'] > $a['v']) $r['v'] = $b['v'] / (1 - $a['v']) - $a['v'];
908  else $r['v'] = ($b['v'] - $a['v']) / $a['v'];
909  return $r;
910 
911  }//end hsvDifference()
912 
913 
927  public static function remap($input_html,$map,$tolerance=0.2)
928  {
929  $tolerance = min(max($tolerance,0),1);
930  $input_hsv = Colour::htmlToHsv($input_html);
931 
932  $shift = Array();
933  $closeness_total = Array();
934  foreach ($map as $from => $to) {
935  if (!$tolerance) {
936  if ($from == $input_html) {
937  return $to;
938  }
939  } else {
940  $from = Colour::htmlToHsv($from);
941  $to = Colour::htmlToHsv($to);
942  // The difference between the original colour and the new one
943  $map_diff = Array('h'=>$to['h']-$from['h'],'s'=>$to['s']-$from['s'],'v'=>$to['v']-$from['v']);
944  // The differnce between the original colour and the input
945  $in_diff = Array('h'=>$input_hsv['h']-$from['h'],'s'=>$input_hsv['s']-$from['s'],'v'=>$input_hsv['v']-$from['v']);
946 
947  // Work out how 'close' the input is to the from colour, this indicates
948  // How much effect this particular mapping should have on it
949  $closeness['h'] = pow(1 - abs($in_diff['h'])/360, 16);
950  $closeness['s'] = pow(1 - abs($in_diff['s']), 8);
951  $closeness['v'] = pow(1 - abs($in_diff['v']), 2);
952 
953  $tolerance = min(max($tolerance,0),1);
954 
955  $closeness['h'] *= $tolerance;
956  $closeness['s'] *= $tolerance;
957  $closeness['v'] *= $tolerance;
958 
959  $closeness['h'] = max(0,$closeness['h']);
960  $closeness['s'] = max(0,$closeness['s']);
961  $closeness['v'] = max(0,$closeness['v']);
962 
963  // Another modifier ensuring that the hue MUST be close
964  $closeness['s'] *= pow($closeness['h'],1);
965  $closeness['v'] *= pow($closeness['h'],1);
966 
967  // Keep a total of this
968  $closeness_total['h'] += $closeness['h'];
969  $closeness_total['s'] += $closeness['s'];
970  $closeness_total['v'] += $closeness['v'];
971 
972 
973  // This is how much the input will be shifted in the output
974  // To by divided by the total closeness
975  $shift['h'] += $map_diff['h'] * $closeness['h'];
976  $shift['s'] += $map_diff['s'] * $closeness['s'];
977  $shift['v'] += $map_diff['v'] * $closeness['v'];
978 
979  }//end if
980 
981  }//end foreach
982 
983  // Trim this down again
984  if ($tolerance) {
985  $input_hsv['h'] += $shift['h'] / $closeness_total['h'];
986  $input_hsv['s'] += $shift['s'] / $closeness_total['s'];
987  $input_hsv['v'] += $shift['v'] / $closeness_total['v'];
988  }
989 
990  return Colour::hsvToHtml($input_hsv);
991 
992  }//end remap()
993 
994 }//end class
995 ?>