[ Index ]

PHP Cross Reference of phpBB-3.1.12-deutsch

title

Body

[close]

/phpbb/captcha/ -> colour_manager.php (source)

   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  }


Generated: Thu Jan 11 00:25:41 2018 Cross-referenced by PHPXref 0.7.1