Verzeichnisstruktur phpBB-3.3.15
- Veröffentlicht
- 28.08.2024
So funktioniert es
|
Auf das letzte Element klicken. Dies geht jeweils ein Schritt zurück |
Auf das Icon klicken, dies öffnet das Verzeichnis. Nochmal klicken schließt das Verzeichnis. |
|
(Beispiel Datei-Icons)
|
Auf das Icon klicken um den Quellcode anzuzeigen |
colour_manager.php
001 <?php
002 /**
003 *
004 * This file is part of the phpBB Forum Software package.
005 *
006 * @copyright (c) phpBB Limited <https://www.phpbb.com>
007 * @license GNU General Public License, version 2 (GPL-2.0)
008 *
009 * For full copyright and license information, please see
010 * the docs/CREDITS.txt file.
011 *
012 */
013
014 namespace phpbb\captcha;
015
016 class colour_manager
017 {
018 var $img;
019 var $mode;
020 var $colours;
021 var $named_colours;
022
023 /**
024 * Create the colour manager, link it to the image resource
025 */
026 function __construct($img, $background = false, $mode = 'ahsv')
027 {
028 $this->img = $img;
029 $this->mode = $mode;
030 $this->colours = array();
031 $this->named_colours = array();
032
033 if ($background !== false)
034 {
035 $bg = $this->allocate_named('background', $background);
036 imagefill($this->img, 0, 0, $bg);
037 }
038 }
039
040 /**
041 * Lookup a named colour resource
042 */
043 function get_resource($named_colour)
044 {
045 if (isset($this->named_colours[$named_colour]))
046 {
047 return $this->named_colours[$named_colour];
048 }
049
050 if (isset($this->named_rgb[$named_colour]))
051 {
052 return $this->allocate_named($named_colour, $this->named_rgb[$named_colour], 'rgb');
053 }
054
055 return false;
056 }
057
058 /**
059 * Assign a name to a colour resource
060 */
061 function name_colour($name, $resource)
062 {
063 $this->named_colours[$name] = $resource;
064 }
065
066 /**
067 * names and allocates a colour resource
068 */
069 function allocate_named($name, $colour, $mode = false)
070 {
071 $resource = $this->allocate($colour, $mode);
072
073 if ($resource !== false)
074 {
075 $this->name_colour($name, $resource);
076 }
077 return $resource;
078 }
079
080 /**
081 * allocates a specified colour into the image
082 */
083 function allocate($colour, $mode = false)
084 {
085 if ($mode === false)
086 {
087 $mode = $this->mode;
088 }
089
090 if (!is_array($colour))
091 {
092 if (isset($this->named_rgb[$colour]))
093 {
094 return $this->allocate_named($colour, $this->named_rgb[$colour], 'rgb');
095 }
096
097 if (!is_int($colour))
098 {
099 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 = count($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 }
528