source: forum/includes/captcha/captcha_gd.php@ 651

Last change on this file since 651 was 651, checked in by aleg, 16 years ago

Změněná cesta k GM a Char logům pro realmy 4 a 7.

File size: 36.9 KB
Line 
1<?php
2/**
3*
4* @package VC
5* @version $Id: captcha_gd.php 8479 2008-03-29 00:22:48Z naderman $
6* @copyright (c) 2006 phpBB Group
7* @license http://opensource.org/licenses/gpl-license.php GNU Public License
8*
9*/
10
11/**
12* @ignore
13*/
14if (!defined('IN_PHPBB'))
15{
16 exit;
17}
18
19/**
20* Original Author - Xore (Robert Hetzler)
21* With contributions from Neothermic
22*
23* @package VC
24*/
25class captcha
26{
27 var $width = 360;
28 var $height = 96;
29
30 /**
31 * Create the image containing $code with a seed of $seed
32 */
33 function execute($code, $seed)
34 {
35 global $config;
36 srand($seed);
37 mt_srand($seed);
38
39 // Create image
40 $img = imagecreatetruecolor($this->width, $this->height);
41
42 // Generate colours
43 $colour = new colour_manager($img, array(
44 'random' => true,
45 'min_value' => 60,
46 ), 'hsv');
47
48 $scheme = $colour->colour_scheme('background', false);
49 $scheme = $colour->mono_range($scheme, 10, false);
50 shuffle($scheme);
51
52 $bg_colours = array_splice($scheme, mt_rand(6, 12));
53
54 // Generate code characters
55 $characters = $sizes = $bounding_boxes = array();
56 $width_avail = $this->width - 15;
57 $code_len = strlen($code);
58
59 $captcha_bitmaps = $this->captcha_bitmaps();
60 for ($i = 0; $i < $code_len; ++$i)
61 {
62 $characters[$i] = new char_cube3d($captcha_bitmaps, $code[$i]);
63
64 list($min, $max) = $characters[$i]->range();
65 $sizes[$i] = mt_rand($min, $max);
66
67 $box = $characters[$i]->dimensions($sizes[$i]);
68 $width_avail -= ($box[2] - $box[0]);
69 $bounding_boxes[$i] = $box;
70 }
71
72 // Redistribute leftover x-space
73 $offset = array();
74 for ($i = 0; $i < $code_len; ++$i)
75 {
76 $denom = ($code_len - $i);
77 $denom = max(1.3, $denom);
78 $offset[$i] = mt_rand(0, (1.5 * $width_avail) / $denom);
79 $width_avail -= $offset[$i];
80 }
81
82 if ($config['captcha_gd_x_grid'])
83 {
84 $grid = (int) $config['captcha_gd_x_grid'];
85 for ($y = 0; $y < $this->height; $y += mt_rand($grid - 2, $grid + 2))
86 {
87 $current_colour = $scheme[array_rand($scheme)];
88 imageline($img, mt_rand(0,4), mt_rand($y - 3, $y), mt_rand($this->width - 5, $this->width), mt_rand($y - 3, $y), $current_colour);
89 }
90 }
91
92 if ($config['captcha_gd_y_grid'])
93 {
94 $grid = (int) $config['captcha_gd_y_grid'];
95 for ($x = 0; $x < $this->width; $x += mt_rand($grid - 2, $grid + 2))
96 {
97 $current_colour = $scheme[array_rand($scheme)];
98 imagedashedline($img, mt_rand($x -3, $x + 3), mt_rand(0, 4), mt_rand($x -3, $x + 3), mt_rand($this->height - 5, $this->height), $current_colour);
99 }
100 }
101
102 $xoffset = 5;
103 for ($i = 0; $i < $code_len; ++$i)
104 {
105 $dimm = $bounding_boxes[$i];
106 $xoffset += ($offset[$i] - $dimm[0]);
107 $yoffset = mt_rand(-$dimm[1], $this->height - $dimm[3]);
108
109 $characters[$i]->drawchar($sizes[$i], $xoffset, $yoffset, $img, $colour->get_resource('background'), $scheme);
110 $xoffset += $dimm[2];
111 }
112
113 if ($config['captcha_gd_foreground_noise'])
114 {
115 $this->noise_line($img, 0, 0, $this->width, $this->height, $colour->get_resource('background'), $scheme, $bg_colours);
116 }
117
118 // Send image
119 header('Content-Type: image/png');
120 header('Cache-control: no-cache, no-store');
121 imagepng($img);
122 imagedestroy($img);
123 }
124
125 /**
126 * Noise line
127 */
128 function noise_line($img, $min_x, $min_y, $max_x, $max_y, $bg, $font, $non_font)
129 {
130 imagesetthickness($img, 2);
131
132 $x1 = $min_x;
133 $x2 = $max_x;
134 $y1 = $min_y;
135 $y2 = $min_y;
136
137 do
138 {
139 $line = array_merge(
140 array_fill(0, mt_rand(30, 60), $non_font[array_rand($non_font)]),
141 array_fill(0, mt_rand(30, 60), $bg)
142 );
143
144 imagesetstyle($img, $line);
145 imageline($img, $x1, $y1, $x2, $y2, IMG_COLOR_STYLED);
146
147 $y1 += mt_rand(12, 35);
148 $y2 += mt_rand(12, 35);
149 }
150 while ($y1 < $max_y && $y2 < $max_y);
151
152 $x1 = $min_x;
153 $x2 = $min_x;
154 $y1 = $min_y;
155 $y2 = $max_y;
156
157 do
158 {
159 $line = array_merge(
160 array_fill(0, mt_rand(30, 60), $non_font[array_rand($non_font)]),
161 array_fill(0, mt_rand(30, 60), $bg)
162 );
163
164 imagesetstyle($img, $line);
165 imageline($img, $x1, $y1, $x2, $y2, IMG_COLOR_STYLED);
166
167 $x1 += mt_rand(20, 35);
168 $x2 += mt_rand(20, 35);
169 }
170 while ($x1 < $max_x && $x2 < $max_x);
171 imagesetthickness($img, 1);
172 }
173
174 /**
175 * Return bitmaps
176 */
177 function captcha_bitmaps()
178 {
179 return array(
180 'width' => 9,
181 'height' => 15,
182 'data' => array(
183
184 'A' => array(
185 array(0,0,0,0,1,0,0,0,0),
186 array(0,0,0,1,0,1,0,0,0),
187 array(0,0,0,1,0,1,0,0,0),
188 array(0,0,0,1,0,1,0,0,0),
189 array(0,0,1,0,0,0,1,0,0),
190 array(0,0,1,0,0,0,1,0,0),
191 array(0,0,1,0,0,0,1,0,0),
192 array(0,1,0,0,0,0,0,1,0),
193 array(0,1,0,0,0,0,0,1,0),
194 array(0,1,1,1,1,1,1,1,0),
195 array(0,1,0,0,0,0,0,1,0),
196 array(1,0,0,0,0,0,0,0,1),
197 array(1,0,0,0,0,0,0,0,1),
198 array(1,0,0,0,0,0,0,0,1),
199 array(1,0,0,0,0,0,0,0,1),
200 ),
201 'B' => array(
202 array(1,1,1,1,1,1,1,0,0),
203 array(1,0,0,0,0,0,0,1,0),
204 array(1,0,0,0,0,0,0,0,1),
205 array(1,0,0,0,0,0,0,0,1),
206 array(1,0,0,0,0,0,0,0,1),
207 array(1,0,0,0,0,0,0,0,1),
208 array(1,0,0,0,0,0,0,1,0),
209 array(1,1,1,1,1,1,1,0,0),
210 array(1,0,0,0,0,0,0,1,0),
211 array(1,0,0,0,0,0,0,0,1),
212 array(1,0,0,0,0,0,0,0,1),
213 array(1,0,0,0,0,0,0,0,1),
214 array(1,0,0,0,0,0,0,0,1),
215 array(1,0,0,0,0,0,0,1,0),
216 array(1,1,1,1,1,1,1,0,0),
217 ),
218 'C' => array(
219 array(0,0,1,1,1,1,1,0,0),
220 array(0,1,0,0,0,0,0,1,0),
221 array(1,0,0,0,0,0,0,0,1),
222 array(1,0,0,0,0,0,0,0,1),
223 array(1,0,0,0,0,0,0,0,0),
224 array(1,0,0,0,0,0,0,0,0),
225 array(1,0,0,0,0,0,0,0,0),
226 array(1,0,0,0,0,0,0,0,0),
227 array(1,0,0,0,0,0,0,0,0),
228 array(1,0,0,0,0,0,0,0,0),
229 array(1,0,0,0,0,0,0,0,0),
230 array(1,0,0,0,0,0,0,0,1),
231 array(1,0,0,0,0,0,0,0,1),
232 array(0,1,0,0,0,0,0,1,0),
233 array(0,0,1,1,1,1,1,0,0),
234 ),
235 'D' => array(
236 array(1,1,1,1,1,1,1,0,0),
237 array(1,0,0,0,0,0,0,1,0),
238 array(1,0,0,0,0,0,0,0,1),
239 array(1,0,0,0,0,0,0,0,1),
240 array(1,0,0,0,0,0,0,0,1),
241 array(1,0,0,0,0,0,0,0,1),
242 array(1,0,0,0,0,0,0,0,1),
243 array(1,0,0,0,0,0,0,0,1),
244 array(1,0,0,0,0,0,0,0,1),
245 array(1,0,0,0,0,0,0,0,1),
246 array(1,0,0,0,0,0,0,0,1),
247 array(1,0,0,0,0,0,0,0,1),
248 array(1,0,0,0,0,0,0,0,1),
249 array(1,0,0,0,0,0,0,1,0),
250 array(1,1,1,1,1,1,1,0,0),
251 ),
252 'E' => array(
253 array(1,1,1,1,1,1,1,1,1),
254 array(1,0,0,0,0,0,0,0,0),
255 array(1,0,0,0,0,0,0,0,0),
256 array(1,0,0,0,0,0,0,0,0),
257 array(1,0,0,0,0,0,0,0,0),
258 array(1,0,0,0,0,0,0,0,0),
259 array(1,0,0,0,0,0,0,0,0),
260 array(1,1,1,1,1,1,1,1,0),
261 array(1,0,0,0,0,0,0,0,0),
262 array(1,0,0,0,0,0,0,0,0),
263 array(1,0,0,0,0,0,0,0,0),
264 array(1,0,0,0,0,0,0,0,0),
265 array(1,0,0,0,0,0,0,0,0),
266 array(1,0,0,0,0,0,0,0,0),
267 array(1,1,1,1,1,1,1,1,1),
268 ),
269 'F' => array(
270 array(1,1,1,1,1,1,1,1,1),
271 array(1,0,0,0,0,0,0,0,0),
272 array(1,0,0,0,0,0,0,0,0),
273 array(1,0,0,0,0,0,0,0,0),
274 array(1,0,0,0,0,0,0,0,0),
275 array(1,0,0,0,0,0,0,0,0),
276 array(1,0,0,0,0,0,0,0,0),
277 array(1,1,1,1,1,1,1,0,0),
278 array(1,0,0,0,0,0,0,0,0),
279 array(1,0,0,0,0,0,0,0,0),
280 array(1,0,0,0,0,0,0,0,0),
281 array(1,0,0,0,0,0,0,0,0),
282 array(1,0,0,0,0,0,0,0,0),
283 array(1,0,0,0,0,0,0,0,0),
284 array(1,0,0,0,0,0,0,0,0),
285 ),
286 'G' => array(
287 array(0,0,1,1,1,1,1,0,0),
288 array(0,1,0,0,0,0,0,1,0),
289 array(1,0,0,0,0,0,0,0,1),
290 array(1,0,0,0,0,0,0,0,0),
291 array(1,0,0,0,0,0,0,0,0),
292 array(1,0,0,0,0,0,0,0,0),
293 array(1,0,0,0,0,0,0,0,0),
294 array(1,0,0,0,0,0,0,0,0),
295 array(1,0,0,0,0,0,1,1,1),
296 array(1,0,0,0,0,0,0,0,1),
297 array(1,0,0,0,0,0,0,0,1),
298 array(1,0,0,0,0,0,0,0,1),
299 array(1,0,0,0,0,0,0,0,1),
300 array(0,1,0,0,0,0,0,1,0),
301 array(0,0,1,1,1,1,1,0,0),
302 ),
303 'H' => array(
304 array(1,0,0,0,0,0,0,0,1),
305 array(1,0,0,0,0,0,0,0,1),
306 array(1,0,0,0,0,0,0,0,1),
307 array(1,0,0,0,0,0,0,0,1),
308 array(1,0,0,0,0,0,0,0,1),
309 array(1,0,0,0,0,0,0,0,1),
310 array(1,0,0,0,0,0,0,0,1),
311 array(1,1,1,1,1,1,1,1,1),
312 array(1,0,0,0,0,0,0,0,1),
313 array(1,0,0,0,0,0,0,0,1),
314 array(1,0,0,0,0,0,0,0,1),
315 array(1,0,0,0,0,0,0,0,1),
316 array(1,0,0,0,0,0,0,0,1),
317 array(1,0,0,0,0,0,0,0,1),
318 array(1,0,0,0,0,0,0,0,1),
319 ),
320 'I' => array(
321 array(1,1,1,1,1,1,1,1,1),
322 array(0,0,0,0,1,0,0,0,0),
323 array(0,0,0,0,1,0,0,0,0),
324 array(0,0,0,0,1,0,0,0,0),
325 array(0,0,0,0,1,0,0,0,0),
326 array(0,0,0,0,1,0,0,0,0),
327 array(0,0,0,0,1,0,0,0,0),
328 array(0,0,0,0,1,0,0,0,0),
329 array(0,0,0,0,1,0,0,0,0),
330 array(0,0,0,0,1,0,0,0,0),
331 array(0,0,0,0,1,0,0,0,0),
332 array(0,0,0,0,1,0,0,0,0),
333 array(0,0,0,0,1,0,0,0,0),
334 array(0,0,0,0,1,0,0,0,0),
335 array(1,1,1,1,1,1,1,1,1),
336 ),
337 'J' => array(
338 array(1,1,1,1,1,1,1,1,1),
339 array(0,0,0,0,0,1,0,0,0),
340 array(0,0,0,0,0,1,0,0,0),
341 array(0,0,0,0,0,1,0,0,0),
342 array(0,0,0,0,0,1,0,0,0),
343 array(0,0,0,0,0,1,0,0,0),
344 array(0,0,0,0,0,1,0,0,0),
345 array(0,0,0,0,0,1,0,0,0),
346 array(0,0,0,0,0,1,0,0,0),
347 array(0,0,0,0,0,1,0,0,0),
348 array(0,0,0,0,0,1,0,0,0),
349 array(1,0,0,0,0,1,0,0,0),
350 array(1,0,0,0,0,1,0,0,0),
351 array(0,1,0,0,1,0,0,0,0),
352 array(0,0,1,1,0,0,0,0,0),
353 ),
354 'K' => array( // New 'K', supplied by NeoThermic
355 array(1,0,0,0,0,0,0,0,1),
356 array(1,0,0,0,0,0,0,1,0),
357 array(1,0,0,0,0,0,1,0,0),
358 array(1,0,0,0,0,1,0,0,0),
359 array(1,0,0,0,1,0,0,0,0),
360 array(1,0,0,1,0,0,0,0,0),
361 array(1,0,1,0,0,0,0,0,0),
362 array(1,1,0,0,0,0,0,0,0),
363 array(1,0,1,0,0,0,0,0,0),
364 array(1,0,0,1,0,0,0,0,0),
365 array(1,0,0,0,1,0,0,0,0),
366 array(1,0,0,0,0,1,0,0,0),
367 array(1,0,0,0,0,0,1,0,0),
368 array(1,0,0,0,0,0,0,1,0),
369 array(1,0,0,0,0,0,0,0,1),
370 ),
371 'L' => array(
372 array(0,0,0,0,0,0,0,0,0),
373 array(1,0,0,0,0,0,0,0,0),
374 array(1,0,0,0,0,0,0,0,0),
375 array(1,0,0,0,0,0,0,0,0),
376 array(1,0,0,0,0,0,0,0,0),
377 array(1,0,0,0,0,0,0,0,0),
378 array(1,0,0,0,0,0,0,0,0),
379 array(1,0,0,0,0,0,0,0,0),
380 array(1,0,0,0,0,0,0,0,0),
381 array(1,0,0,0,0,0,0,0,0),
382 array(1,0,0,0,0,0,0,0,0),
383 array(1,0,0,0,0,0,0,0,0),
384 array(1,0,0,0,0,0,0,0,0),
385 array(1,0,0,0,0,0,0,0,0),
386 array(1,1,1,1,1,1,1,1,1),
387 ),
388 'M' => array(
389 array(1,1,0,0,0,0,0,1,1),
390 array(1,1,0,0,0,0,0,1,1),
391 array(1,0,1,0,0,0,1,0,1),
392 array(1,0,1,0,0,0,1,0,1),
393 array(1,0,1,0,0,0,1,0,1),
394 array(1,0,0,1,0,1,0,0,1),
395 array(1,0,0,1,0,1,0,0,1),
396 array(1,0,0,1,0,1,0,0,1),
397 array(1,0,0,0,1,0,0,0,1),
398 array(1,0,0,0,1,0,0,0,1),
399 array(1,0,0,0,0,0,0,0,1),
400 array(1,0,0,0,0,0,0,0,1),
401 array(1,0,0,0,0,0,0,0,1),
402 array(1,0,0,0,0,0,0,0,1),
403 array(1,0,0,0,0,0,0,0,1),
404 ),
405 'N' => array(
406 array(1,1,0,0,0,0,0,0,1),
407 array(1,1,0,0,0,0,0,0,1),
408 array(1,0,1,0,0,0,0,0,1),
409 array(1,0,1,0,0,0,0,0,1),
410 array(1,0,0,1,0,0,0,0,1),
411 array(1,0,0,1,0,0,0,0,1),
412 array(1,0,0,0,1,0,0,0,1),
413 array(1,0,0,0,1,0,0,0,1),
414 array(1,0,0,0,1,0,0,0,1),
415 array(1,0,0,0,0,1,0,0,1),
416 array(1,0,0,0,0,1,0,0,1),
417 array(1,0,0,0,0,0,1,0,1),
418 array(1,0,0,0,0,0,1,0,1),
419 array(1,0,0,0,0,0,0,1,1),
420 array(1,0,0,0,0,0,0,1,1),
421 ),
422 'O' => array(
423 array(0,0,1,1,1,1,1,0,0),
424 array(0,1,0,0,0,0,0,1,0),
425 array(1,0,0,0,0,0,0,0,1),
426 array(1,0,0,0,0,0,0,0,1),
427 array(1,0,0,0,0,0,0,0,1),
428 array(1,0,0,0,0,0,0,0,1),
429 array(1,0,0,0,0,0,0,0,1),
430 array(1,0,0,0,0,0,0,0,1),
431 array(1,0,0,0,0,0,0,0,1),
432 array(1,0,0,0,0,0,0,0,1),
433 array(1,0,0,0,0,0,0,0,1),
434 array(1,0,0,0,0,0,0,0,1),
435 array(1,0,0,0,0,0,0,0,1),
436 array(0,1,0,0,0,0,0,1,0),
437 array(0,0,1,1,1,1,1,0,0),
438 ),
439 'P' => array(
440 array(1,1,1,1,1,1,1,0,0),
441 array(1,0,0,0,0,0,0,1,0),
442 array(1,0,0,0,0,0,0,0,1),
443 array(1,0,0,0,0,0,0,0,1),
444 array(1,0,0,0,0,0,0,0,1),
445 array(1,0,0,0,0,0,0,0,1),
446 array(1,0,0,0,0,0,0,1,0),
447 array(1,1,1,1,1,1,1,0,0),
448 array(1,0,0,0,0,0,0,0,0),
449 array(1,0,0,0,0,0,0,0,0),
450 array(1,0,0,0,0,0,0,0,0),
451 array(1,0,0,0,0,0,0,0,0),
452 array(1,0,0,0,0,0,0,0,0),
453 array(1,0,0,0,0,0,0,0,0),
454 array(1,0,0,0,0,0,0,0,0),
455 ),
456 'Q' => array(
457 array(0,0,1,1,1,1,1,0,0),
458 array(0,1,0,0,0,0,0,1,0),
459 array(1,0,0,0,0,0,0,0,1),
460 array(1,0,0,0,0,0,0,0,1),
461 array(1,0,0,0,0,0,0,0,1),
462 array(1,0,0,0,0,0,0,0,1),
463 array(1,0,0,0,0,0,0,0,1),
464 array(1,0,0,0,0,0,0,0,1),
465 array(1,0,0,0,0,0,0,0,1),
466 array(1,0,0,0,0,0,0,0,1),
467 array(1,0,0,0,0,0,0,0,1),
468 array(1,0,0,0,0,1,0,0,1),
469 array(1,0,0,0,0,0,1,0,1),
470 array(0,1,0,0,0,0,0,1,0),
471 array(0,0,1,1,1,1,1,0,1),
472 ),
473 'R' => array(
474 array(1,1,1,1,1,1,1,0,0),
475 array(1,0,0,0,0,0,0,1,0),
476 array(1,0,0,0,0,0,0,0,1),
477 array(1,0,0,0,0,0,0,0,1),
478 array(1,0,0,0,0,0,0,0,1),
479 array(1,0,0,0,0,0,0,0,1),
480 array(1,0,0,0,0,0,0,1,0),
481 array(1,1,1,1,1,1,1,0,0),
482 array(1,1,1,0,0,0,0,0,0),
483 array(1,0,0,1,0,0,0,0,0),
484 array(1,0,0,0,1,0,0,0,0),
485 array(1,0,0,0,0,1,0,0,0),
486 array(1,0,0,0,0,0,1,0,0),
487 array(1,0,0,0,0,0,0,1,0),
488 array(1,0,0,0,0,0,0,0,1),
489 ),
490 'S' => array(
491 array(0,0,1,1,1,1,1,0,0),
492 array(0,1,0,0,0,0,0,1,0),
493 array(1,0,0,0,0,0,0,0,1),
494 array(1,0,0,0,0,0,0,0,0),
495 array(1,0,0,0,0,0,0,0,0),
496 array(1,0,0,0,0,0,0,0,0),
497 array(0,1,0,0,0,0,0,0,0),
498 array(0,0,1,1,1,1,1,0,0),
499 array(0,0,0,0,0,0,0,1,0),
500 array(0,0,0,0,0,0,0,0,1),
501 array(0,0,0,0,0,0,0,0,1),
502 array(0,0,0,0,0,0,0,0,1),
503 array(1,0,0,0,0,0,0,0,1),
504 array(0,1,0,0,0,0,0,1,0),
505 array(0,0,1,1,1,1,1,0,0),
506 ),
507 'T' => array(
508 array(1,1,1,1,1,1,1,1,1),
509 array(0,0,0,0,1,0,0,0,0),
510 array(0,0,0,0,1,0,0,0,0),
511 array(0,0,0,0,1,0,0,0,0),
512 array(0,0,0,0,1,0,0,0,0),
513 array(0,0,0,0,1,0,0,0,0),
514 array(0,0,0,0,1,0,0,0,0),
515 array(0,0,0,0,1,0,0,0,0),
516 array(0,0,0,0,1,0,0,0,0),
517 array(0,0,0,0,1,0,0,0,0),
518 array(0,0,0,0,1,0,0,0,0),
519 array(0,0,0,0,1,0,0,0,0),
520 array(0,0,0,0,1,0,0,0,0),
521 array(0,0,0,0,1,0,0,0,0),
522 array(0,0,0,0,1,0,0,0,0),
523 ),
524 'U' => array(
525 array(1,0,0,0,0,0,0,0,1),
526 array(1,0,0,0,0,0,0,0,1),
527 array(1,0,0,0,0,0,0,0,1),
528 array(1,0,0,0,0,0,0,0,1),
529 array(1,0,0,0,0,0,0,0,1),
530 array(1,0,0,0,0,0,0,0,1),
531 array(1,0,0,0,0,0,0,0,1),
532 array(1,0,0,0,0,0,0,0,1),
533 array(1,0,0,0,0,0,0,0,1),
534 array(1,0,0,0,0,0,0,0,1),
535 array(1,0,0,0,0,0,0,0,1),
536 array(1,0,0,0,0,0,0,0,1),
537 array(1,0,0,0,0,0,0,0,1),
538 array(0,1,0,0,0,0,0,1,0),
539 array(0,0,1,1,1,1,1,0,0),
540 ),
541 'V' => array(
542 array(1,0,0,0,0,0,0,0,1),
543 array(1,0,0,0,0,0,0,0,1),
544 array(1,0,0,0,0,0,0,0,1),
545 array(0,1,0,0,0,0,0,1,0),
546 array(0,1,0,0,0,0,0,1,0),
547 array(0,1,0,0,0,0,0,1,0),
548 array(0,0,1,0,0,0,1,0,0),
549 array(0,0,1,0,0,0,1,0,0),
550 array(0,0,1,0,0,0,1,0,0),
551 array(0,0,1,0,0,0,1,0,0),
552 array(0,0,0,1,0,1,0,0,0),
553 array(0,0,0,1,0,1,0,0,0),
554 array(0,0,0,1,0,1,0,0,0),
555 array(0,0,0,0,1,0,0,0,0),
556 array(0,0,0,0,1,0,0,0,0),
557 ),
558 'W' => array( // New 'W', supplied by MHobbit
559 array(1,0,0,0,0,0,0,0,1),
560 array(1,0,0,0,0,0,0,0,1),
561 array(1,0,0,0,0,0,0,0,1),
562 array(1,0,0,0,0,0,0,0,1),
563 array(1,0,0,0,0,0,0,0,1),
564 array(1,0,0,0,1,0,0,0,1),
565 array(1,0,0,0,1,0,0,0,1),
566 array(1,0,0,1,0,1,0,0,1),
567 array(1,0,0,1,0,1,0,0,1),
568 array(1,0,0,1,0,1,0,0,1),
569 array(1,0,1,0,0,0,1,0,1),
570 array(1,0,1,0,0,0,1,0,1),
571 array(1,0,1,0,0,0,1,0,1),
572 array(1,1,0,0,0,0,0,1,1),
573 array(1,1,0,0,0,0,0,1,1),
574 ),
575 'X' => array(
576 array(1,0,0,0,0,0,0,0,1),
577 array(1,0,0,0,0,0,0,0,1),
578 array(0,1,0,0,0,0,0,1,0),
579 array(0,1,0,0,0,0,0,1,0),
580 array(0,0,1,0,0,0,1,0,0),
581 array(0,0,0,1,0,1,0,0,0),
582 array(0,0,0,1,0,1,0,0,0),
583 array(0,0,0,0,1,0,0,0,0),
584 array(0,0,0,1,0,1,0,0,0),
585 array(0,0,0,1,0,1,0,0,0),
586 array(0,0,1,0,0,0,1,0,0),
587 array(0,1,0,0,0,0,1,0,0),
588 array(0,1,0,0,0,0,0,1,0),
589 array(1,0,0,0,0,0,0,0,1),
590 array(1,0,0,0,0,0,0,0,1),
591 ),
592 'Y' => array(
593 array(1,0,0,0,0,0,0,0,1),
594 array(1,0,0,0,0,0,0,0,1),
595 array(0,1,0,0,0,0,0,1,0),
596 array(0,1,0,0,0,0,0,1,0),
597 array(0,0,1,0,0,0,1,0,0),
598 array(0,0,1,0,0,0,1,0,0),
599 array(0,0,0,1,0,1,0,0,0),
600 array(0,0,0,0,1,0,0,0,0),
601 array(0,0,0,0,1,0,0,0,0),
602 array(0,0,0,0,1,0,0,0,0),
603 array(0,0,0,0,1,0,0,0,0),
604 array(0,0,0,0,1,0,0,0,0),
605 array(0,0,0,0,1,0,0,0,0),
606 array(0,0,0,0,1,0,0,0,0),
607 array(0,0,0,0,1,0,0,0,0),
608 ),
609 'Z' => array( // New 'Z' supplied by Anon
610 array(1,1,1,1,1,1,1,1,1),
611 array(1,0,0,0,0,0,0,0,1),
612 array(0,0,0,0,0,0,0,0,1),
613 array(0,0,0,0,0,0,0,1,0),
614 array(0,0,0,0,0,0,1,0,0),
615 array(0,0,0,0,0,1,0,0,0),
616 array(0,0,0,0,0,1,0,0,0),
617 array(0,0,0,0,1,0,0,0,0),
618 array(0,0,0,1,0,0,0,0,0),
619 array(0,0,0,1,0,0,0,0,0),
620 array(0,0,1,0,0,0,0,0,0),
621 array(0,1,0,0,0,0,0,0,0),
622 array(1,0,0,0,0,0,0,0,0),
623 array(1,0,0,0,0,0,0,0,1),
624 array(1,1,1,1,1,1,1,1,1),
625 ),
626 '1' => array(
627 array(0,0,0,1,1,0,0,0,0),
628 array(0,0,1,0,1,0,0,0,0),
629 array(0,1,0,0,1,0,0,0,0),
630 array(0,0,0,0,1,0,0,0,0),
631 array(0,0,0,0,1,0,0,0,0),
632 array(0,0,0,0,1,0,0,0,0),
633 array(0,0,0,0,1,0,0,0,0),
634 array(0,0,0,0,1,0,0,0,0),
635 array(0,0,0,0,1,0,0,0,0),
636 array(0,0,0,0,1,0,0,0,0),
637 array(0,0,0,0,1,0,0,0,0),
638 array(0,0,0,0,1,0,0,0,0),
639 array(0,0,0,0,1,0,0,0,0),
640 array(0,0,0,0,1,0,0,0,0),
641 array(0,1,1,1,1,1,1,1,0),
642 ),
643 '2' => array( // New '2' supplied by Anon
644 array(0,0,0,1,1,1,0,0,0),
645 array(0,0,1,0,0,0,1,0,0),
646 array(0,1,0,0,0,0,1,1,0),
647 array(0,0,0,0,0,0,0,0,1),
648 array(0,0,0,0,0,0,0,0,1),
649 array(0,0,0,0,0,0,0,1,1),
650 array(0,0,0,0,0,0,0,1,0),
651 array(0,0,0,0,0,0,1,0,0),
652 array(0,0,0,0,0,1,0,0,0),
653 array(0,0,0,0,1,0,0,0,0),
654 array(0,0,0,1,0,0,0,0,0),
655 array(0,0,1,0,0,0,0,0,0),
656 array(0,1,0,0,0,0,0,0,0),
657 array(1,1,1,1,1,1,1,1,1),
658 array(0,0,0,0,0,0,0,0,0),
659 ),
660 '3' => array(
661 array(0,0,1,1,1,1,1,0,0),
662 array(0,1,0,0,0,0,0,1,0),
663 array(1,0,0,0,0,0,0,0,1),
664 array(0,0,0,0,0,0,0,0,1),
665 array(0,0,0,0,0,0,0,0,1),
666 array(0,0,0,0,0,0,0,0,1),
667 array(0,0,0,0,0,0,0,1,0),
668 array(0,0,0,0,0,1,1,0,0),
669 array(0,0,0,0,0,0,0,1,0),
670 array(0,0,0,0,0,0,0,0,1),
671 array(0,0,0,0,0,0,0,0,1),
672 array(0,0,0,0,0,0,0,0,1),
673 array(1,0,0,0,0,0,0,0,1),
674 array(0,1,0,0,0,0,0,1,0),
675 array(0,0,1,1,1,1,1,0,0),
676 ),
677 '4' => array(
678 array(0,0,0,0,0,0,1,1,0),
679 array(0,0,0,0,0,1,0,1,0),
680 array(0,0,0,0,1,0,0,1,0),
681 array(0,0,0,1,0,0,0,1,0),
682 array(0,0,1,0,0,0,0,1,0),
683 array(0,1,0,0,0,0,0,1,0),
684 array(1,0,0,0,0,0,0,1,0),
685 array(1,0,0,0,0,0,0,1,0),
686 array(1,1,1,1,1,1,1,1,1),
687 array(0,0,0,0,0,0,0,1,0),
688 array(0,0,0,0,0,0,0,1,0),
689 array(0,0,0,0,0,0,0,1,0),
690 array(0,0,0,0,0,0,0,1,0),
691 array(0,0,0,0,0,0,0,1,0),
692 array(0,0,0,0,0,0,0,1,0),
693 ),
694 '5' => array(
695 array(1,1,1,1,1,1,1,1,1),
696 array(1,0,0,0,0,0,0,0,0),
697 array(1,0,0,0,0,0,0,0,0),
698 array(1,0,0,0,0,0,0,0,0),
699 array(1,0,0,0,0,0,0,0,0),
700 array(0,1,0,0,0,0,0,0,0),
701 array(0,0,1,1,1,1,1,0,0),
702 array(0,0,0,0,0,0,0,1,0),
703 array(0,0,0,0,0,0,0,0,1),
704 array(0,0,0,0,0,0,0,0,1),
705 array(0,0,0,0,0,0,0,0,1),
706 array(0,0,0,0,0,0,0,0,1),
707 array(1,0,0,0,0,0,0,0,1),
708 array(0,1,0,0,0,0,0,1,0),
709 array(0,0,1,1,1,1,1,0,0),
710 ),
711 '6' => array(
712 array(0,0,1,1,1,1,1,0,0),
713 array(0,1,0,0,0,0,0,1,0),
714 array(1,0,0,0,0,0,0,0,1),
715 array(1,0,0,0,0,0,0,0,1),
716 array(1,0,0,0,0,0,0,0,0),
717 array(1,0,0,0,0,0,0,0,0),
718 array(1,0,0,1,1,1,1,0,0),
719 array(1,0,1,0,0,0,0,1,0),
720 array(1,1,0,0,0,0,0,0,1),
721 array(1,0,0,0,0,0,0,0,1),
722 array(1,0,0,0,0,0,0,0,1),
723 array(1,0,0,0,0,0,0,0,1),
724 array(1,0,0,0,0,0,0,0,1),
725 array(0,1,0,0,0,0,0,1,0),
726 array(0,0,1,1,1,1,1,0,0),
727 ),
728 '7' => array(
729 array(1,1,1,1,1,1,1,1,1),
730 array(0,0,0,0,0,0,0,0,1),
731 array(0,0,0,0,0,0,0,1,0),
732 array(0,0,0,0,0,0,0,1,0),
733 array(0,0,0,0,0,0,1,0,0),
734 array(0,0,0,0,0,1,0,0,0),
735 array(0,0,0,0,0,1,0,0,0),
736 array(0,0,0,0,1,0,0,0,0),
737 array(0,0,0,1,0,0,0,0,0),
738 array(0,0,0,1,0,0,0,0,0),
739 array(0,0,1,0,0,0,0,0,0),
740 array(0,1,0,0,0,0,0,0,0),
741 array(0,1,0,0,0,0,0,0,0),
742 array(1,0,0,0,0,0,0,0,0),
743 array(1,0,0,0,0,0,0,0,0),
744 ),
745 '8' => array(
746 array(0,0,1,1,1,1,1,0,0),
747 array(0,1,0,0,0,0,0,1,0),
748 array(1,0,0,0,0,0,0,0,1),
749 array(1,0,0,0,0,0,0,0,1),
750 array(1,0,0,0,0,0,0,0,1),
751 array(1,0,0,0,0,0,0,0,1),
752 array(0,1,0,0,0,0,0,1,0),
753 array(0,0,1,1,1,1,1,0,0),
754 array(0,1,0,0,0,0,0,1,0),
755 array(1,0,0,0,0,0,0,0,1),
756 array(1,0,0,0,0,0,0,0,1),
757 array(1,0,0,0,0,0,0,0,1),
758 array(1,0,0,0,0,0,0,0,1),
759 array(0,1,0,0,0,0,0,1,0),
760 array(0,0,1,1,1,1,1,0,0),
761 ),
762 '9' => array(
763 array(0,0,1,1,1,1,1,0,0),
764 array(0,1,0,0,0,0,0,1,0),
765 array(1,0,0,0,0,0,0,0,1),
766 array(1,0,0,0,0,0,0,0,1),
767 array(1,0,0,0,0,0,0,0,1),
768 array(1,0,0,0,0,0,0,0,1),
769 array(1,0,0,0,0,0,0,1,1),
770 array(0,1,0,0,0,0,1,0,1),
771 array(0,0,1,1,1,1,0,0,1),
772 array(0,0,0,0,0,0,0,0,1),
773 array(0,0,0,0,0,0,0,0,1),
774 array(1,0,0,0,0,0,0,0,1),
775 array(1,0,0,0,0,0,0,0,1),
776 array(0,1,0,0,0,0,0,1,0),
777 array(0,0,1,1,1,1,1,0,0),
778 ),
779 )
780 );
781 }
782}
783
784/**
785* @package VC
786*/
787class char_cube3d
788{
789 var $bitmap;
790 var $bitmap_width;
791 var $bitmap_height;
792
793 var $basis_matrix = array(array(1, 0, 0), array(0, 1, 0), array(0, 0, 1));
794 var $abs_x = array(1, 0);
795 var $abs_y = array(0, 1);
796 var $x = 0;
797 var $y = 1;
798 var $z = 2;
799 var $letter = '';
800
801 /**
802 */
803 function char_cube3d(&$bitmaps, $letter)
804 {
805 $this->bitmap = $bitmaps['data'][$letter];
806 $this->bitmap_width = $bitmaps['width'];
807 $this->bitmap_height = $bitmaps['height'];
808
809 $this->basis_matrix[0][0] = mt_rand(-600, 600);
810 $this->basis_matrix[0][1] = mt_rand(-600, 600);
811 $this->basis_matrix[0][2] = (mt_rand(0, 1) * 2000) - 1000;
812 $this->basis_matrix[1][0] = mt_rand(-1000, 1000);
813 $this->basis_matrix[1][1] = mt_rand(-1000, 1000);
814 $this->basis_matrix[1][2] = mt_rand(-1000, 1000);
815
816 $this->normalize($this->basis_matrix[0]);
817 $this->normalize($this->basis_matrix[1]);
818 $this->basis_matrix[2] = $this->cross_product($this->basis_matrix[0], $this->basis_matrix[1]);
819 $this->normalize($this->basis_matrix[2]);
820
821 // $this->basis_matrix[1] might not be (probably isn't) orthogonal to $basis_matrix[0]
822 $this->basis_matrix[1] = $this->cross_product($this->basis_matrix[0], $this->basis_matrix[2]);
823 $this->normalize($this->basis_matrix[1]);
824
825 // Make sure our cube is facing into the canvas (assuming +z == in)
826 for ($i = 0; $i < 3; ++$i)
827 {
828 if ($this->basis_matrix[$i][2] < 0)
829 {
830 $this->basis_matrix[$i][0] *= -1;
831 $this->basis_matrix[$i][1] *= -1;
832 $this->basis_matrix[$i][2] *= -1;
833 }
834 }
835
836 // Force our "z" basis vector to be the one with greatest absolute z value
837 $this->x = 0;
838 $this->y = 1;
839 $this->z = 2;
840
841 // Swap "y" with "z"
842 if ($this->basis_matrix[1][2] > $this->basis_matrix[2][2])
843 {
844 $this->z = 1;
845 $this->y = 2;
846 }
847
848 // Swap "x" with "z"
849 if ($this->basis_matrix[0][2] > $this->basis_matrix[$this->z][2])
850 {
851 $this->x = $this->z;
852 $this->z = 0;
853 }
854
855 // Still need to determine which of $x,$y are which.
856 // wrong orientation if y's y-component is less than it's x-component
857 // likewise if x's x-component is less than it's y-component
858 // if they disagree, go with the one with the greater weight difference.
859 // rotate if positive
860 $weight = (abs($this->basis_matrix[$this->x][1]) - abs($this->basis_matrix[$this->x][0])) + (abs($this->basis_matrix[$this->y][0]) - abs($this->basis_matrix[$this->y][1]));
861
862 // Swap "x" with "y"
863 if ($weight > 0)
864 {
865 list($this->x, $this->y) = array($this->y, $this->x);
866 }
867
868 $this->abs_x = array($this->basis_matrix[$this->x][0], $this->basis_matrix[$this->x][1]);
869 $this->abs_y = array($this->basis_matrix[$this->y][0], $this->basis_matrix[$this->y][1]);
870
871 if ($this->abs_x[0] < 0)
872 {
873 $this->abs_x[0] *= -1;
874 $this->abs_x[1] *= -1;
875 }
876
877 if ($this->abs_y[1] > 0)
878 {
879 $this->abs_y[0] *= -1;
880 $this->abs_y[1] *= -1;
881 }
882
883 $this->letter = $letter;
884 }
885
886 /**
887 * Draw a character
888 */
889 function drawchar($scale, $xoff, $yoff, $img, $background, $colours)
890 {
891 $width = $this->bitmap_width;
892 $height = $this->bitmap_height;
893 $bitmap = $this->bitmap;
894
895 $colour1 = $colours[array_rand($colours)];
896 $colour2 = $colours[array_rand($colours)];
897
898 $swapx = ($this->basis_matrix[$this->x][0] > 0);
899 $swapy = ($this->basis_matrix[$this->y][1] < 0);
900
901 for ($y = 0; $y < $height; ++$y)
902 {
903 for ($x = 0; $x < $width; ++$x)
904 {
905 $xp = ($swapx) ? ($width - $x - 1) : $x;
906 $yp = ($swapy) ? ($height - $y - 1) : $y;
907
908 if ($bitmap[$height - $yp - 1][$xp])
909 {
910 $dx = $this->scale($this->abs_x, ($xp - ($swapx ? ($width / 2) : ($width / 2) - 1)) * $scale);
911 $dy = $this->scale($this->abs_y, ($yp - ($swapy ? ($height / 2) : ($height / 2) - 1)) * $scale);
912 $xo = $xoff + $dx[0] + $dy[0];
913 $yo = $yoff + $dx[1] + $dy[1];
914
915 $origin = array(0, 0, 0);
916 $xvec = $this->scale($this->basis_matrix[$this->x], $scale);
917 $yvec = $this->scale($this->basis_matrix[$this->y], $scale);
918 $face_corner = $this->sum2($xvec, $yvec);
919
920 $zvec = $this->scale($this->basis_matrix[$this->z], $scale);
921 $x_corner = $this->sum2($xvec, $zvec);
922 $y_corner = $this->sum2($yvec, $zvec);
923
924 imagefilledpolygon($img, $this->gen_poly($xo, $yo, $origin, $xvec, $x_corner,$zvec), 4, $colour1);
925 imagefilledpolygon($img, $this->gen_poly($xo, $yo, $origin, $yvec, $y_corner,$zvec), 4, $colour2);
926
927 $face = $this->gen_poly($xo, $yo, $origin, $xvec, $face_corner, $yvec);
928
929 imagefilledpolygon($img, $face, 4, $background);
930 imagepolygon($img, $face, 4, $colour1);
931 }
932 }
933 }
934 }
935
936 /*
937 * return a roughly acceptable range of sizes for rendering with this texttype
938 */
939 function range()
940 {
941 return array(3, 4);
942 }
943
944 /**
945 * Vector length
946 */
947 function vectorlen($vector)
948 {
949 return sqrt(pow($vector[0], 2) + pow($vector[1], 2) + pow($vector[2], 2));
950 }
951
952 /**
953 * Normalize
954 */
955 function normalize(&$vector, $length = 1)
956 {
957 $length = (( $length < 1) ? 1 : $length);
958 $length /= $this->vectorlen($vector);
959 $vector[0] *= $length;
960 $vector[1] *= $length;
961 $vector[2] *= $length;
962 }
963
964 /**
965 */
966 function cross_product($vector1, $vector2)
967 {
968 $retval = array(0, 0, 0);
969 $retval[0] = (($vector1[1] * $vector2[2]) - ($vector1[2] * $vector2[1]));
970 $retval[1] = -(($vector1[0] * $vector2[2]) - ($vector1[2] * $vector2[0]));
971 $retval[2] = (($vector1[0] * $vector2[1]) - ($vector1[1] * $vector2[0]));
972
973 return $retval;
974 }
975
976 /**
977 */
978 function sum($vector1, $vector2)
979 {
980 return array($vector1[0] + $vector2[0], $vector1[1] + $vector2[1], $vector1[2] + $vector2[2]);
981 }
982
983 /**
984 */
985 function sum2($vector1, $vector2)
986 {
987 return array($vector1[0] + $vector2[0], $vector1[1] + $vector2[1]);
988 }
989
990 /**
991 */
992 function scale($vector, $length)
993 {
994 if (sizeof($vector) == 2)
995 {
996 return array($vector[0] * $length, $vector[1] * $length);
997 }
998
999 return array($vector[0] * $length, $vector[1] * $length, $vector[2] * $length);
1000 }
1001
1002 /**
1003 */
1004 function gen_poly($xoff, $yoff, &$vec1, &$vec2, &$vec3, &$vec4)
1005 {
1006 $poly = array();
1007 $poly[0] = $xoff + $vec1[0];
1008 $poly[1] = $yoff + $vec1[1];
1009 $poly[2] = $xoff + $vec2[0];
1010 $poly[3] = $yoff + $vec2[1];
1011 $poly[4] = $xoff + $vec3[0];
1012 $poly[5] = $yoff + $vec3[1];
1013 $poly[6] = $xoff + $vec4[0];
1014 $poly[7] = $yoff + $vec4[1];
1015
1016 return $poly;
1017 }
1018
1019 /**
1020 * dimensions
1021 */
1022 function dimensions($size)
1023 {
1024 $xn = $this->scale($this->basis_matrix[$this->x], -($this->bitmap_width / 2) * $size);
1025 $xp = $this->scale($this->basis_matrix[$this->x], ($this->bitmap_width / 2) * $size);
1026 $yn = $this->scale($this->basis_matrix[$this->y], -($this->bitmap_height / 2) * $size);
1027 $yp = $this->scale($this->basis_matrix[$this->y], ($this->bitmap_height / 2) * $size);
1028
1029 $p = array();
1030 $p[0] = $this->sum2($xn, $yn);
1031 $p[1] = $this->sum2($xp, $yn);
1032 $p[2] = $this->sum2($xp, $yp);
1033 $p[3] = $this->sum2($xn, $yp);
1034
1035 $min_x = $max_x = $p[0][0];
1036 $min_y = $max_y = $p[0][1];
1037
1038 for ($i = 1; $i < 4; ++$i)
1039 {
1040 $min_x = ($min_x > $p[$i][0]) ? $p[$i][0] : $min_x;
1041 $min_y = ($min_y > $p[$i][1]) ? $p[$i][1] : $min_y;
1042 $max_x = ($max_x < $p[$i][0]) ? $p[$i][0] : $max_x;
1043 $max_y = ($max_y < $p[$i][1]) ? $p[$i][1] : $max_y;
1044 }
1045
1046 return array($min_x, $min_y, $max_x, $max_y);
1047 }
1048}
1049
1050/**
1051* @package VC
1052*/
1053class colour_manager
1054{
1055 var $img;
1056 var $mode;
1057 var $colours;
1058 var $named_colours;
1059
1060 /**
1061 * Create the colour manager, link it to the image resource
1062 */
1063 function colour_manager($img, $background = false, $mode = 'ahsv')
1064 {
1065 $this->img = $img;
1066 $this->mode = $mode;
1067 $this->colours = array();
1068 $this->named_colours = array();
1069
1070 if ($background !== false)
1071 {
1072 $bg = $this->allocate_named('background', $background);
1073 imagefill($this->img, 0, 0, $bg);
1074 }
1075 }
1076
1077 /**
1078 * Lookup a named colour resource
1079 */
1080 function get_resource($named_colour)
1081 {
1082 if (isset($this->named_colours[$named_colour]))
1083 {
1084 return $this->named_colours[$named_colour];
1085 }
1086
1087 if (isset($this->named_rgb[$named_colour]))
1088 {
1089 return $this->allocate_named($named_colour, $this->named_rgb[$named_colour], 'rgb');
1090 }
1091
1092 return false;
1093 }
1094
1095 /**
1096 * Assign a name to a colour resource
1097 */
1098 function name_colour($name, $resource)
1099 {
1100 $this->named_colours[$name] = $resource;
1101 }
1102
1103 /**
1104 * names and allocates a colour resource
1105 */
1106 function allocate_named($name, $colour, $mode = false)
1107 {
1108 $resource = $this->allocate($colour, $mode);
1109
1110 if ($resource !== false)
1111 {
1112 $this->name_colour($name, $resource);
1113 }
1114 return $resource;
1115 }
1116
1117 /**
1118 * allocates a specified colour into the image
1119 */
1120 function allocate($colour, $mode = false)
1121 {
1122 if ($mode === false)
1123 {
1124 $mode = $this->mode;
1125 }
1126
1127 if (!is_array($colour))
1128 {
1129 if (isset($this->named_rgb[$colour]))
1130 {
1131 return $this->allocate_named($colour, $this->named_rgb[$colour], 'rgb');
1132 }
1133
1134 if (!is_int($colour))
1135 {
1136 return false;
1137 }
1138
1139 $mode = 'rgb';
1140 $colour = array(255 & ($colour >> 16), 255 & ($colour >> 8), 255 & $colour);
1141 }
1142
1143 if (isset($colour['mode']))
1144 {
1145 $mode = $colour['mode'];
1146 unset($colour['mode']);
1147 }
1148
1149 if (isset($colour['random']))
1150 {
1151 unset($colour['random']);
1152 // everything else is params
1153 return $this->random_colour($colour, $mode);
1154 }
1155
1156 $rgb = colour_manager::model_convert($colour, $mode, 'rgb');
1157 $store = ($this->mode == 'rgb') ? $rgb : colour_manager::model_convert($colour, $mode, $this->mode);
1158 $resource = imagecolorallocate($this->img, $rgb[0], $rgb[1], $rgb[2]);
1159 $this->colours[$resource] = $store;
1160
1161 return $resource;
1162 }
1163
1164 /**
1165 * randomly generates a colour, with optional params
1166 */
1167 function random_colour($params = array(), $mode = false)
1168 {
1169 if ($mode === false)
1170 {
1171 $mode = $this->mode;
1172 }
1173
1174 switch ($mode)
1175 {
1176 case 'rgb':
1177 // @TODO random rgb generation. do we intend to do this, or is it just too tedious?
1178 break;
1179
1180 case 'ahsv':
1181 case 'hsv':
1182 default:
1183
1184 $default_params = array(
1185 'hue_bias' => false, // degree / 'r'/'g'/'b'/'c'/'m'/'y' /'o'
1186 'hue_range' => false, // if hue bias, then difference range +/- from bias
1187 'min_saturation' => 30, // 0 - 100
1188 'max_saturation' => 80, // 0 - 100
1189 'min_value' => 30, // 0 - 100
1190 'max_value' => 80, // 0 - 100
1191 );
1192
1193 $alt = ($mode == 'ahsv') ? true : false;
1194 $params = array_merge($default_params, $params);
1195
1196 $min_hue = 0;
1197 $max_hue = 359;
1198 $min_saturation = max(0, $params['min_saturation']);
1199 $max_saturation = min(100, $params['max_saturation']);
1200 $min_value = max(0, $params['min_value']);
1201 $max_value = min(100, $params['max_value']);
1202
1203 if ($params['hue_bias'] !== false)
1204 {
1205 if (is_numeric($params['hue_bias']))
1206 {
1207 $h = intval($params['hue_bias']) % 360;
1208 }
1209 else
1210 {
1211 switch ($params['hue_bias'])
1212 {
1213 case 'o':
1214 $h = $alt ? 60 : 30;
1215 break;
1216
1217 case 'y':
1218 $h = $alt ? 120 : 60;
1219 break;
1220
1221 case 'g':
1222 $h = $alt ? 180 : 120;
1223 break;
1224
1225 case 'c':
1226 $h = $alt ? 210 : 180;
1227 break;
1228
1229 case 'b':
1230 $h = 240;
1231 break;
1232
1233 case 'm':
1234 $h = 300;
1235 break;
1236
1237 case 'r':
1238 default:
1239 $h = 0;
1240 break;
1241 }
1242 }
1243
1244 $min_hue = $h + 360;
1245 $max_hue = $h + 360;
1246
1247 if ($params['hue_range'])
1248 {
1249 $min_hue -= min(180, $params['hue_range']);
1250 $max_hue += min(180, $params['hue_range']);
1251 }
1252 }
1253
1254 $h = mt_rand($min_hue, $max_hue);
1255 $s = mt_rand($min_saturation, $max_saturation);
1256 $v = mt_rand($min_value, $max_value);
1257
1258 return $this->allocate(array($h, $s, $v), $mode);
1259
1260 break;
1261 }
1262 }
1263
1264 /**
1265 */
1266 function colour_scheme($resource, $include_original = true)
1267 {
1268 $mode = 'hsv';
1269
1270 if (($pre = $this->get_resource($resource)) !== false)
1271 {
1272 $resource = $pre;
1273 }
1274
1275 $colour = colour_manager::model_convert($this->colours[$resource], $this->mode, $mode);
1276 $results = ($include_original) ? array($resource) : array();
1277 $colour2 = $colour3 = $colour4 = $colour;
1278 $colour2[0] += 150;
1279 $colour3[0] += 180;
1280 $colour4[0] += 210;
1281
1282
1283 $results[] = $this->allocate($colour2, $mode);
1284 $results[] = $this->allocate($colour3, $mode);
1285 $results[] = $this->allocate($colour4, $mode);
1286
1287 return $results;
1288 }
1289
1290 /**
1291 */
1292 function mono_range($resource, $count = 5, $include_original = true)
1293 {
1294 if (is_array($resource))
1295 {
1296 $results = array();
1297 for ($i = 0, $size = sizeof($resource); $i < $size; ++$i)
1298 {
1299 $results = array_merge($results, $this->mono_range($resource[$i], $count, $include_original));
1300 }
1301 return $results;
1302 }
1303
1304 $mode = (in_array($this->mode, array('hsv', 'ahsv'), true) ? $this->mode : 'ahsv');
1305 if (($pre = $this->get_resource($resource)) !== false)
1306 {
1307 $resource = $pre;
1308 }
1309
1310 $colour = colour_manager::model_convert($this->colours[$resource], $this->mode, $mode);
1311
1312 $results = array();
1313 if ($include_original)
1314 {
1315 $results[] = $resource;
1316 $count--;
1317 }
1318
1319 // This is a hard problem. I chicken out and try to maintain readability at the cost of less randomness.
1320
1321 while ($count > 0)
1322 {
1323 $colour[1] = ($colour[1] + mt_rand(40,60)) % 99;
1324 $colour[2] = ($colour[2] + mt_rand(40,60));
1325 $results[] = $this->allocate($colour, $mode);
1326 $count--;
1327 }
1328 return $results;
1329 }
1330
1331 /**
1332 * Convert from one colour model to another
1333 */
1334 function model_convert($colour, $from_model, $to_model)
1335 {
1336 if ($from_model == $to_model)
1337 {
1338 return $colour;
1339 }
1340
1341 switch ($to_model)
1342 {
1343 case 'hsv':
1344
1345 switch ($from_model)
1346 {
1347 case 'ahsv':
1348 return colour_manager::ah2h($colour);
1349 break;
1350
1351 case 'rgb':
1352 return colour_manager::rgb2hsv($colour);
1353 break;
1354 }
1355 break;
1356
1357 case 'ahsv':
1358
1359 switch ($from_model)
1360 {
1361 case 'hsv':
1362 return colour_manager::h2ah($colour);
1363 break;
1364
1365 case 'rgb':
1366 return colour_manager::h2ah(colour_manager::rgb2hsv($colour));
1367 break;
1368 }
1369 break;
1370
1371 case 'rgb':
1372 switch ($from_model)
1373 {
1374 case 'hsv':
1375 return colour_manager::hsv2rgb($colour);
1376 break;
1377
1378 case 'ahsv':
1379 return colour_manager::hsv2rgb(colour_manager::ah2h($colour));
1380 break;
1381 }
1382 break;
1383 }
1384 return false;
1385 }
1386
1387 /**
1388 * Slightly altered from wikipedia's algorithm
1389 */
1390 function hsv2rgb($hsv)
1391 {
1392 colour_manager::normalize_hue($hsv[0]);
1393
1394 $h = $hsv[0];
1395 $s = min(1, max(0, $hsv[1] / 100));
1396 $v = min(1, max(0, $hsv[2] / 100));
1397
1398 // calculate hue sector
1399 $hi = floor($hsv[0] / 60);
1400
1401 // calculate opposite colour
1402 $p = $v * (1 - $s);
1403
1404 // calculate distance between hex vertices
1405 $f = ($h / 60) - $hi;
1406
1407 // coming in or going out?
1408 if (!($hi & 1))
1409 {
1410 $f = 1 - $f;
1411 }
1412
1413 // calculate adjacent colour
1414 $q = $v * (1 - ($f * $s));
1415
1416 switch ($hi)
1417 {
1418 case 0:
1419 $rgb = array($v, $q, $p);
1420 break;
1421
1422 case 1:
1423 $rgb = array($q, $v, $p);
1424 break;
1425
1426 case 2:
1427 $rgb = array($p, $v, $q);
1428 break;
1429
1430 case 3:
1431 $rgb = array($p, $q, $v);
1432 break;
1433
1434 case 4:
1435 $rgb = array($q, $p, $v);
1436 break;
1437
1438 case 5:
1439 $rgb = array($v, $p, $q);
1440 break;
1441
1442 default:
1443 return array(0, 0, 0);
1444 break;
1445 }
1446
1447 return array(255 * $rgb[0], 255 * $rgb[1], 255 * $rgb[2]);
1448 }
1449
1450 /**
1451 * (more than) Slightly altered from wikipedia's algorithm
1452 */
1453 function rgb2hsv($rgb)
1454 {
1455 $r = min(255, max(0, $rgb[0]));
1456 $g = min(255, max(0, $rgb[1]));
1457 $b = min(255, max(0, $rgb[2]));
1458 $max = max($r, $g, $b);
1459 $min = min($r, $g, $b);
1460
1461 $v = $max / 255;
1462 $s = (!$max) ? 0 : 1 - ($min / $max);
1463
1464 // if max - min is 0, we want hue to be 0 anyway.
1465 $h = $max - $min;
1466
1467 if ($h)
1468 {
1469 switch ($max)
1470 {
1471 case $g:
1472 $h = 120 + (60 * ($b - $r) / $h);
1473 break;
1474
1475 case $b:
1476 $h = 240 + (60 * ($r - $g) / $h);
1477 break;
1478
1479 case $r:
1480 $h = 360 + (60 * ($g - $b) / $h);
1481 break;
1482 }
1483 }
1484 colour_manager::normalize_hue($h);
1485
1486 return array($h, $s * 100, $v * 100);
1487 }
1488
1489 /**
1490 */
1491 function normalize_hue(&$hue)
1492 {
1493 $hue %= 360;
1494
1495 if ($hue < 0)
1496 {
1497 $hue += 360;
1498 }
1499 }
1500
1501 /**
1502 * Alternate hue to hue
1503 */
1504 function ah2h($ahue)
1505 {
1506 if (is_array($ahue))
1507 {
1508 $ahue[0] = colour_manager::ah2h($ahue[0]);
1509 return $ahue;
1510 }
1511 colour_manager::normalize_hue($ahue);
1512
1513 // blue through red is already ok
1514 if ($ahue >= 240)
1515 {
1516 return $ahue;
1517 }
1518
1519 // ahue green is at 180
1520 if ($ahue >= 180)
1521 {
1522 // return (240 - (2 * (240 - $ahue)));
1523 return (2 * $ahue) - 240; // equivalent
1524 }
1525
1526 // ahue yellow is at 120 (RYB rather than RGB)
1527 if ($ahue >= 120)
1528 {
1529 return $ahue - 60;
1530 }
1531
1532 return $ahue / 2;
1533 }
1534
1535 /**
1536 * hue to Alternate hue
1537 */
1538 function h2ah($hue)
1539 {
1540 if (is_array($hue))
1541 {
1542 $hue[0] = colour_manager::h2ah($hue[0]);
1543 return $hue;
1544 }
1545 colour_manager::normalize_hue($hue);
1546
1547 // blue through red is already ok
1548 if ($hue >= 240)
1549 {
1550 return $hue;
1551 }
1552 else if ($hue <= 60)
1553 {
1554 return $hue * 2;
1555 }
1556 else if ($hue <= 120)
1557 {
1558 return $hue + 60;
1559 }
1560 else
1561 {
1562 return ($hue + 240) / 2;
1563 }
1564 }
1565}
1566
1567?>
Note: See TracBrowser for help on using the repository browser.