[ Index ] |
PHP Cross Reference of phpBB-3.1.12-deutsch |
[Summary view] [Print] [Text view]
1 <?php 2 /** 3 * 4 * This file is part of the phpBB Forum Software package. 5 * 6 * @copyright (c) phpBB Limited <https://www.phpbb.com> 7 * @license GNU General Public License, version 2 (GPL-2.0) 8 * 9 * For full copyright and license information, please see 10 * the docs/CREDITS.txt file. 11 * 12 */ 13 14 namespace phpbb\captcha; 15 16 class colour_manager 17 { 18 var $img; 19 var $mode; 20 var $colours; 21 var $named_colours; 22 23 /** 24 * Create the colour manager, link it to the image resource 25 */ 26 function __construct($img, $background = false, $mode = 'ahsv') 27 { 28 $this->img = $img; 29 $this->mode = $mode; 30 $this->colours = array(); 31 $this->named_colours = array(); 32 33 if ($background !== false) 34 { 35 $bg = $this->allocate_named('background', $background); 36 imagefill($this->img, 0, 0, $bg); 37 } 38 } 39 40 /** 41 * Lookup a named colour resource 42 */ 43 function get_resource($named_colour) 44 { 45 if (isset($this->named_colours[$named_colour])) 46 { 47 return $this->named_colours[$named_colour]; 48 } 49 50 if (isset($this->named_rgb[$named_colour])) 51 { 52 return $this->allocate_named($named_colour, $this->named_rgb[$named_colour], 'rgb'); 53 } 54 55 return false; 56 } 57 58 /** 59 * Assign a name to a colour resource 60 */ 61 function name_colour($name, $resource) 62 { 63 $this->named_colours[$name] = $resource; 64 } 65 66 /** 67 * names and allocates a colour resource 68 */ 69 function allocate_named($name, $colour, $mode = false) 70 { 71 $resource = $this->allocate($colour, $mode); 72 73 if ($resource !== false) 74 { 75 $this->name_colour($name, $resource); 76 } 77 return $resource; 78 } 79 80 /** 81 * allocates a specified colour into the image 82 */ 83 function allocate($colour, $mode = false) 84 { 85 if ($mode === false) 86 { 87 $mode = $this->mode; 88 } 89 90 if (!is_array($colour)) 91 { 92 if (isset($this->named_rgb[$colour])) 93 { 94 return $this->allocate_named($colour, $this->named_rgb[$colour], 'rgb'); 95 } 96 97 if (!is_int($colour)) 98 { 99 return false; 100 } 101 102 $mode = 'rgb'; 103 $colour = array(255 & ($colour >> 16), 255 & ($colour >> 8), 255 & $colour); 104 } 105 106 if (isset($colour['mode'])) 107 { 108 $mode = $colour['mode']; 109 unset($colour['mode']); 110 } 111 112 if (isset($colour['random'])) 113 { 114 unset($colour['random']); 115 // everything else is params 116 return $this->random_colour($colour, $mode); 117 } 118 119 $rgb = $this->model_convert($colour, $mode, 'rgb'); 120 $store = ($this->mode == 'rgb') ? $rgb : $this->model_convert($colour, $mode, $this->mode); 121 $resource = imagecolorallocate($this->img, $rgb[0], $rgb[1], $rgb[2]); 122 $this->colours[$resource] = $store; 123 124 return $resource; 125 } 126 127 /** 128 * randomly generates a colour, with optional params 129 */ 130 function random_colour($params = array(), $mode = false) 131 { 132 if ($mode === false) 133 { 134 $mode = $this->mode; 135 } 136 137 switch ($mode) 138 { 139 case 'rgb': 140 // @TODO random rgb generation. do we intend to do this, or is it just too tedious? 141 break; 142 143 case 'ahsv': 144 case 'hsv': 145 default: 146 147 $default_params = array( 148 'hue_bias' => false, // degree / 'r'/'g'/'b'/'c'/'m'/'y' /'o' 149 'hue_range' => false, // if hue bias, then difference range +/- from bias 150 'min_saturation' => 30, // 0 - 100 151 'max_saturation' => 80, // 0 - 100 152 'min_value' => 30, // 0 - 100 153 'max_value' => 80, // 0 - 100 154 ); 155 156 $alt = ($mode == 'ahsv') ? true : false; 157 $params = array_merge($default_params, $params); 158 159 $min_hue = 0; 160 $max_hue = 359; 161 $min_saturation = max(0, $params['min_saturation']); 162 $max_saturation = min(100, $params['max_saturation']); 163 $min_value = max(0, $params['min_value']); 164 $max_value = min(100, $params['max_value']); 165 166 if ($params['hue_bias'] !== false) 167 { 168 if (is_numeric($params['hue_bias'])) 169 { 170 $h = intval($params['hue_bias']) % 360; 171 } 172 else 173 { 174 switch ($params['hue_bias']) 175 { 176 case 'o': 177 $h = $alt ? 60 : 30; 178 break; 179 180 case 'y': 181 $h = $alt ? 120 : 60; 182 break; 183 184 case 'g': 185 $h = $alt ? 180 : 120; 186 break; 187 188 case 'c': 189 $h = $alt ? 210 : 180; 190 break; 191 192 case 'b': 193 $h = 240; 194 break; 195 196 case 'm': 197 $h = 300; 198 break; 199 200 case 'r': 201 default: 202 $h = 0; 203 break; 204 } 205 } 206 207 $min_hue = $h + 360; 208 $max_hue = $h + 360; 209 210 if ($params['hue_range']) 211 { 212 $min_hue -= min(180, $params['hue_range']); 213 $max_hue += min(180, $params['hue_range']); 214 } 215 } 216 217 $h = mt_rand($min_hue, $max_hue); 218 $s = mt_rand($min_saturation, $max_saturation); 219 $v = mt_rand($min_value, $max_value); 220 221 return $this->allocate(array($h, $s, $v), $mode); 222 223 break; 224 } 225 } 226 227 /** 228 */ 229 function colour_scheme($resource, $include_original = true) 230 { 231 $mode = 'hsv'; 232 233 if (($pre = $this->get_resource($resource)) !== false) 234 { 235 $resource = $pre; 236 } 237 238 $colour = $this->model_convert($this->colours[$resource], $this->mode, $mode); 239 $results = ($include_original) ? array($resource) : array(); 240 $colour2 = $colour3 = $colour4 = $colour; 241 $colour2[0] += 150; 242 $colour3[0] += 180; 243 $colour4[0] += 210; 244 245 $results[] = $this->allocate($colour2, $mode); 246 $results[] = $this->allocate($colour3, $mode); 247 $results[] = $this->allocate($colour4, $mode); 248 249 return $results; 250 } 251 252 /** 253 */ 254 function mono_range($resource, $count = 5, $include_original = true) 255 { 256 if (is_array($resource)) 257 { 258 $results = array(); 259 for ($i = 0, $size = sizeof($resource); $i < $size; ++$i) 260 { 261 $results = array_merge($results, $this->mono_range($resource[$i], $count, $include_original)); 262 } 263 return $results; 264 } 265 266 $mode = (in_array($this->mode, array('hsv', 'ahsv'), true) ? $this->mode : 'ahsv'); 267 if (($pre = $this->get_resource($resource)) !== false) 268 { 269 $resource = $pre; 270 } 271 272 $colour = $this->model_convert($this->colours[$resource], $this->mode, $mode); 273 274 $results = array(); 275 if ($include_original) 276 { 277 $results[] = $resource; 278 $count--; 279 } 280 281 // This is a hard problem. I chicken out and try to maintain readability at the cost of less randomness. 282 283 while ($count > 0) 284 { 285 $colour[1] = ($colour[1] + mt_rand(40,60)) % 99; 286 $colour[2] = ($colour[2] + mt_rand(40,60)); 287 $results[] = $this->allocate($colour, $mode); 288 $count--; 289 } 290 return $results; 291 } 292 293 /** 294 * Convert from one colour model to another 295 */ 296 function model_convert($colour, $from_model, $to_model) 297 { 298 if ($from_model == $to_model) 299 { 300 return $colour; 301 } 302 303 switch ($to_model) 304 { 305 case 'hsv': 306 307 switch ($from_model) 308 { 309 case 'ahsv': 310 return $this->ah2h($colour); 311 break; 312 313 case 'rgb': 314 return $this->rgb2hsv($colour); 315 break; 316 } 317 break; 318 319 case 'ahsv': 320 321 switch ($from_model) 322 { 323 case 'hsv': 324 return $this->h2ah($colour); 325 break; 326 327 case 'rgb': 328 return $this->h2ah($this->rgb2hsv($colour)); 329 break; 330 } 331 break; 332 333 case 'rgb': 334 switch ($from_model) 335 { 336 case 'hsv': 337 return $this->hsv2rgb($colour); 338 break; 339 340 case 'ahsv': 341 return $this->hsv2rgb($this->ah2h($colour)); 342 break; 343 } 344 break; 345 } 346 return false; 347 } 348 349 /** 350 * Slightly altered from wikipedia's algorithm 351 */ 352 function hsv2rgb($hsv) 353 { 354 $this->normalize_hue($hsv[0]); 355 356 $h = $hsv[0]; 357 $s = min(1, max(0, $hsv[1] / 100)); 358 $v = min(1, max(0, $hsv[2] / 100)); 359 360 // calculate hue sector 361 $hi = floor($hsv[0] / 60); 362 363 // calculate opposite colour 364 $p = $v * (1 - $s); 365 366 // calculate distance between hex vertices 367 $f = ($h / 60) - $hi; 368 369 // coming in or going out? 370 if (!($hi & 1)) 371 { 372 $f = 1 - $f; 373 } 374 375 // calculate adjacent colour 376 $q = $v * (1 - ($f * $s)); 377 378 switch ($hi) 379 { 380 case 0: 381 $rgb = array($v, $q, $p); 382 break; 383 384 case 1: 385 $rgb = array($q, $v, $p); 386 break; 387 388 case 2: 389 $rgb = array($p, $v, $q); 390 break; 391 392 case 3: 393 $rgb = array($p, $q, $v); 394 break; 395 396 case 4: 397 $rgb = array($q, $p, $v); 398 break; 399 400 case 5: 401 $rgb = array($v, $p, $q); 402 break; 403 404 default: 405 return array(0, 0, 0); 406 break; 407 } 408 409 return array(255 * $rgb[0], 255 * $rgb[1], 255 * $rgb[2]); 410 } 411 412 /** 413 * (more than) Slightly altered from wikipedia's algorithm 414 */ 415 function rgb2hsv($rgb) 416 { 417 $r = min(255, max(0, $rgb[0])); 418 $g = min(255, max(0, $rgb[1])); 419 $b = min(255, max(0, $rgb[2])); 420 $max = max($r, $g, $b); 421 $min = min($r, $g, $b); 422 423 $v = $max / 255; 424 $s = (!$max) ? 0 : 1 - ($min / $max); 425 426 // if max - min is 0, we want hue to be 0 anyway. 427 $h = $max - $min; 428 429 if ($h) 430 { 431 switch ($max) 432 { 433 case $g: 434 $h = 120 + (60 * ($b - $r) / $h); 435 break; 436 437 case $b: 438 $h = 240 + (60 * ($r - $g) / $h); 439 break; 440 441 case $r: 442 $h = 360 + (60 * ($g - $b) / $h); 443 break; 444 } 445 } 446 $this->normalize_hue($h); 447 448 return array($h, $s * 100, $v * 100); 449 } 450 451 /** 452 */ 453 function normalize_hue(&$hue) 454 { 455 $hue %= 360; 456 457 if ($hue < 0) 458 { 459 $hue += 360; 460 } 461 } 462 463 /** 464 * Alternate hue to hue 465 */ 466 function ah2h($ahue) 467 { 468 if (is_array($ahue)) 469 { 470 $ahue[0] = $this->ah2h($ahue[0]); 471 return $ahue; 472 } 473 $this->normalize_hue($ahue); 474 475 // blue through red is already ok 476 if ($ahue >= 240) 477 { 478 return $ahue; 479 } 480 481 // ahue green is at 180 482 if ($ahue >= 180) 483 { 484 // return (240 - (2 * (240 - $ahue))); 485 return (2 * $ahue) - 240; // equivalent 486 } 487 488 // ahue yellow is at 120 (RYB rather than RGB) 489 if ($ahue >= 120) 490 { 491 return $ahue - 60; 492 } 493 494 return $ahue / 2; 495 } 496 497 /** 498 * hue to Alternate hue 499 */ 500 function h2ah($hue) 501 { 502 if (is_array($hue)) 503 { 504 $hue[0] = $this->h2ah($hue[0]); 505 return $hue; 506 } 507 $this->normalize_hue($hue); 508 509 // blue through red is already ok 510 if ($hue >= 240) 511 { 512 return $hue; 513 } 514 else if ($hue <= 60) 515 { 516 return $hue * 2; 517 } 518 else if ($hue <= 120) 519 { 520 return $hue + 60; 521 } 522 else 523 { 524 return ($hue + 240) / 2; 525 } 526 } 527 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Thu Jan 11 00:25:41 2018 | Cross-referenced by PHPXref 0.7.1 |