Verzeichnisstruktur phpBB-3.0.0
- Veröffentlicht
- 12.12.2007
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 |
captcha_gd.php
0001 <?php
0002 /**
0003 *
0004 * @package VC
0005 * @version $Id$
0006 * @copyright (c) 2006 phpBB Group
0007 * @license http://opensource.org/licenses/gpl-license.php GNU Public License
0008 *
0009 */
0010
0011 /**
0012 * @ignore
0013 */
0014 if (!defined('IN_PHPBB'))
0015 {
0016 exit;
0017 }
0018
0019 /**
0020 * Original Author - Xore (Robert Hetzler)
0021 * With contributions from Neothermic
0022 *
0023 * @package VC
0024 */
0025 class captcha
0026 {
0027 var $width = 360;
0028 var $height = 96;
0029
0030 /**
0031 * Create the image containing $code with a seed of $seed
0032 */
0033 function execute($code, $seed)
0034 {
0035 global $config;
0036 srand($seed);
0037 mt_srand($seed);
0038
0039 // Create image
0040 $img = imagecreatetruecolor($this->width, $this->height);
0041
0042 // Generate colours
0043 $colour = new colour_manager($img, array(
0044 'random' => true,
0045 'min_value' => 60,
0046 ), 'hsv');
0047
0048 $scheme = $colour->colour_scheme('background', false);
0049 $scheme = $colour->mono_range($scheme, 10, false);
0050 shuffle($scheme);
0051
0052 $bg_colours = array_splice($scheme, mt_rand(6, 12));
0053
0054 // Generate code characters
0055 $characters = $sizes = $bounding_boxes = array();
0056 $width_avail = $this->width - 15;
0057 $code_len = strlen($code);
0058
0059 $captcha_bitmaps = $this->captcha_bitmaps();
0060 for ($i = 0; $i < $code_len; ++$i)
0061 {
0062 $characters[$i] = new char_cube3d($captcha_bitmaps, $code[$i]);
0063
0064 list($min, $max) = $characters[$i]->range();
0065 $sizes[$i] = mt_rand($min, $max);
0066
0067 $box = $characters[$i]->dimensions($sizes[$i]);
0068 $width_avail -= ($box[2] - $box[0]);
0069 $bounding_boxes[$i] = $box;
0070 }
0071
0072 // Redistribute leftover x-space
0073 $offset = array();
0074 for ($i = 0; $i < $code_len; ++$i)
0075 {
0076 $denom = ($code_len - $i);
0077 $denom = max(1.3, $denom);
0078 $offset[$i] = mt_rand(0, (1.5 * $width_avail) / $denom);
0079 $width_avail -= $offset[$i];
0080 }
0081
0082 if ($config['captcha_gd_x_grid'])
0083 {
0084 $grid = (int) $config['captcha_gd_x_grid'];
0085 for ($y = 0; $y < $this->height; $y += mt_rand($grid - 2, $grid + 2))
0086 {
0087 $current_colour = $scheme[array_rand($scheme)];
0088 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);
0089 }
0090 }
0091
0092 if ($config['captcha_gd_y_grid'])
0093 {
0094 $grid = (int) $config['captcha_gd_y_grid'];
0095 for ($x = 0; $x < $this->width; $x += mt_rand($grid - 2, $grid + 2))
0096 {
0097 $current_colour = $scheme[array_rand($scheme)];
0098 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);
0099 }
0100 }
0101
0102 $xoffset = 5;
0103 for ($i = 0; $i < $code_len; ++$i)
0104 {
0105 $dimm = $bounding_boxes[$i];
0106 $xoffset += ($offset[$i] - $dimm[0]);
0107 $yoffset = mt_rand(-$dimm[1], $this->height - $dimm[3]);
0108
0109 $characters[$i]->drawchar($sizes[$i], $xoffset, $yoffset, $img, $colour->get_resource('background'), $scheme);
0110 $xoffset += $dimm[2];
0111 }
0112
0113 if ($config['captcha_gd_foreground_noise'])
0114 {
0115 $this->noise_line($img, 0, 0, $this->width, $this->height, $colour->get_resource('background'), $scheme, $bg_colours);
0116 }
0117
0118 // Send image
0119 header('Content-Type: image/png');
0120 header('Cache-control: no-cache, no-store');
0121 imagepng($img);
0122 imagedestroy($img);
0123 }
0124
0125 /**
0126 * Noise line
0127 */
0128 function noise_line($img, $min_x, $min_y, $max_x, $max_y, $bg, $font, $non_font)
0129 {
0130 imagesetthickness($img, 2);
0131
0132 $x1 = $min_x;
0133 $x2 = $max_x;
0134 $y1 = $min_y;
0135 $y2 = $min_y;
0136
0137 do
0138 {
0139 $line = array_merge(
0140 array_fill(0, mt_rand(30, 60), $non_font[array_rand($non_font)]),
0141 array_fill(0, mt_rand(30, 60), $bg)
0142 );
0143
0144 imagesetstyle($img, $line);
0145 imageline($img, $x1, $y1, $x2, $y2, IMG_COLOR_STYLED);
0146
0147 $y1 += mt_rand(12, 35);
0148 $y2 += mt_rand(12, 35);
0149 }
0150 while ($y1 < $max_y && $y2 < $max_y);
0151
0152 $x1 = $min_x;
0153 $x2 = $min_x;
0154 $y1 = $min_y;
0155 $y2 = $max_y;
0156
0157 do
0158 {
0159 $line = array_merge(
0160 array_fill(0, mt_rand(30, 60), $non_font[array_rand($non_font)]),
0161 array_fill(0, mt_rand(30, 60), $bg)
0162 );
0163
0164 imagesetstyle($img, $line);
0165 imageline($img, $x1, $y1, $x2, $y2, IMG_COLOR_STYLED);
0166
0167 $x1 += mt_rand(20, 35);
0168 $x2 += mt_rand(20, 35);
0169 }
0170 while ($x1 < $max_x && $x2 < $max_x);
0171 imagesetthickness($img, 1);
0172 }
0173
0174 /**
0175 * Return bitmaps
0176 */
0177 function captcha_bitmaps()
0178 {
0179 return array(
0180 'width' => 9,
0181 'height' => 15,
0182 'data' => array(
0183
0184 'A' => array(
0185 array(0,0,0,0,1,0,0,0,0),
0186 array(0,0,0,1,0,1,0,0,0),
0187 array(0,0,0,1,0,1,0,0,0),
0188 array(0,0,0,1,0,1,0,0,0),
0189 array(0,0,1,0,0,0,1,0,0),
0190 array(0,0,1,0,0,0,1,0,0),
0191 array(0,0,1,0,0,0,1,0,0),
0192 array(0,1,0,0,0,0,0,1,0),
0193 array(0,1,0,0,0,0,0,1,0),
0194 array(0,1,1,1,1,1,1,1,0),
0195 array(0,1,0,0,0,0,0,1,0),
0196 array(1,0,0,0,0,0,0,0,1),
0197 array(1,0,0,0,0,0,0,0,1),
0198 array(1,0,0,0,0,0,0,0,1),
0199 array(1,0,0,0,0,0,0,0,1),
0200 ),
0201 'B' => array(
0202 array(1,1,1,1,1,1,1,0,0),
0203 array(1,0,0,0,0,0,0,1,0),
0204 array(1,0,0,0,0,0,0,0,1),
0205 array(1,0,0,0,0,0,0,0,1),
0206 array(1,0,0,0,0,0,0,0,1),
0207 array(1,0,0,0,0,0,0,0,1),
0208 array(1,0,0,0,0,0,0,1,0),
0209 array(1,1,1,1,1,1,1,0,0),
0210 array(1,0,0,0,0,0,0,1,0),
0211 array(1,0,0,0,0,0,0,0,1),
0212 array(1,0,0,0,0,0,0,0,1),
0213 array(1,0,0,0,0,0,0,0,1),
0214 array(1,0,0,0,0,0,0,0,1),
0215 array(1,0,0,0,0,0,0,1,0),
0216 array(1,1,1,1,1,1,1,0,0),
0217 ),
0218 'C' => array(
0219 array(0,0,1,1,1,1,1,0,0),
0220 array(0,1,0,0,0,0,0,1,0),
0221 array(1,0,0,0,0,0,0,0,1),
0222 array(1,0,0,0,0,0,0,0,1),
0223 array(1,0,0,0,0,0,0,0,0),
0224 array(1,0,0,0,0,0,0,0,0),
0225 array(1,0,0,0,0,0,0,0,0),
0226 array(1,0,0,0,0,0,0,0,0),
0227 array(1,0,0,0,0,0,0,0,0),
0228 array(1,0,0,0,0,0,0,0,0),
0229 array(1,0,0,0,0,0,0,0,0),
0230 array(1,0,0,0,0,0,0,0,1),
0231 array(1,0,0,0,0,0,0,0,1),
0232 array(0,1,0,0,0,0,0,1,0),
0233 array(0,0,1,1,1,1,1,0,0),
0234 ),
0235 'D' => array(
0236 array(1,1,1,1,1,1,1,0,0),
0237 array(1,0,0,0,0,0,0,1,0),
0238 array(1,0,0,0,0,0,0,0,1),
0239 array(1,0,0,0,0,0,0,0,1),
0240 array(1,0,0,0,0,0,0,0,1),
0241 array(1,0,0,0,0,0,0,0,1),
0242 array(1,0,0,0,0,0,0,0,1),
0243 array(1,0,0,0,0,0,0,0,1),
0244 array(1,0,0,0,0,0,0,0,1),
0245 array(1,0,0,0,0,0,0,0,1),
0246 array(1,0,0,0,0,0,0,0,1),
0247 array(1,0,0,0,0,0,0,0,1),
0248 array(1,0,0,0,0,0,0,0,1),
0249 array(1,0,0,0,0,0,0,1,0),
0250 array(1,1,1,1,1,1,1,0,0),
0251 ),
0252 'E' => array(
0253 array(1,1,1,1,1,1,1,1,1),
0254 array(1,0,0,0,0,0,0,0,0),
0255 array(1,0,0,0,0,0,0,0,0),
0256 array(1,0,0,0,0,0,0,0,0),
0257 array(1,0,0,0,0,0,0,0,0),
0258 array(1,0,0,0,0,0,0,0,0),
0259 array(1,0,0,0,0,0,0,0,0),
0260 array(1,1,1,1,1,1,1,1,0),
0261 array(1,0,0,0,0,0,0,0,0),
0262 array(1,0,0,0,0,0,0,0,0),
0263 array(1,0,0,0,0,0,0,0,0),
0264 array(1,0,0,0,0,0,0,0,0),
0265 array(1,0,0,0,0,0,0,0,0),
0266 array(1,0,0,0,0,0,0,0,0),
0267 array(1,1,1,1,1,1,1,1,1),
0268 ),
0269 'F' => array(
0270 array(1,1,1,1,1,1,1,1,1),
0271 array(1,0,0,0,0,0,0,0,0),
0272 array(1,0,0,0,0,0,0,0,0),
0273 array(1,0,0,0,0,0,0,0,0),
0274 array(1,0,0,0,0,0,0,0,0),
0275 array(1,0,0,0,0,0,0,0,0),
0276 array(1,0,0,0,0,0,0,0,0),
0277 array(1,1,1,1,1,1,1,0,0),
0278 array(1,0,0,0,0,0,0,0,0),
0279 array(1,0,0,0,0,0,0,0,0),
0280 array(1,0,0,0,0,0,0,0,0),
0281 array(1,0,0,0,0,0,0,0,0),
0282 array(1,0,0,0,0,0,0,0,0),
0283 array(1,0,0,0,0,0,0,0,0),
0284 array(1,0,0,0,0,0,0,0,0),
0285 ),
0286 'G' => array(
0287 array(0,0,1,1,1,1,1,0,0),
0288 array(0,1,0,0,0,0,0,1,0),
0289 array(1,0,0,0,0,0,0,0,1),
0290 array(1,0,0,0,0,0,0,0,0),
0291 array(1,0,0,0,0,0,0,0,0),
0292 array(1,0,0,0,0,0,0,0,0),
0293 array(1,0,0,0,0,0,0,0,0),
0294 array(1,0,0,0,0,0,0,0,0),
0295 array(1,0,0,0,0,0,1,1,1),
0296 array(1,0,0,0,0,0,0,0,1),
0297 array(1,0,0,0,0,0,0,0,1),
0298 array(1,0,0,0,0,0,0,0,1),
0299 array(1,0,0,0,0,0,0,0,1),
0300 array(0,1,0,0,0,0,0,1,0),
0301 array(0,0,1,1,1,1,1,0,0),
0302 ),
0303 'H' => array(
0304 array(1,0,0,0,0,0,0,0,1),
0305 array(1,0,0,0,0,0,0,0,1),
0306 array(1,0,0,0,0,0,0,0,1),
0307 array(1,0,0,0,0,0,0,0,1),
0308 array(1,0,0,0,0,0,0,0,1),
0309 array(1,0,0,0,0,0,0,0,1),
0310 array(1,0,0,0,0,0,0,0,1),
0311 array(1,1,1,1,1,1,1,1,1),
0312 array(1,0,0,0,0,0,0,0,1),
0313 array(1,0,0,0,0,0,0,0,1),
0314 array(1,0,0,0,0,0,0,0,1),
0315 array(1,0,0,0,0,0,0,0,1),
0316 array(1,0,0,0,0,0,0,0,1),
0317 array(1,0,0,0,0,0,0,0,1),
0318 array(1,0,0,0,0,0,0,0,1),
0319 ),
0320 'I' => array(
0321 array(1,1,1,1,1,1,1,1,1),
0322 array(0,0,0,0,1,0,0,0,0),
0323 array(0,0,0,0,1,0,0,0,0),
0324 array(0,0,0,0,1,0,0,0,0),
0325 array(0,0,0,0,1,0,0,0,0),
0326 array(0,0,0,0,1,0,0,0,0),
0327 array(0,0,0,0,1,0,0,0,0),
0328 array(0,0,0,0,1,0,0,0,0),
0329 array(0,0,0,0,1,0,0,0,0),
0330 array(0,0,0,0,1,0,0,0,0),
0331 array(0,0,0,0,1,0,0,0,0),
0332 array(0,0,0,0,1,0,0,0,0),
0333 array(0,0,0,0,1,0,0,0,0),
0334 array(0,0,0,0,1,0,0,0,0),
0335 array(1,1,1,1,1,1,1,1,1),
0336 ),
0337 'J' => array(
0338 array(1,1,1,1,1,1,1,1,1),
0339 array(0,0,0,0,0,1,0,0,0),
0340 array(0,0,0,0,0,1,0,0,0),
0341 array(0,0,0,0,0,1,0,0,0),
0342 array(0,0,0,0,0,1,0,0,0),
0343 array(0,0,0,0,0,1,0,0,0),
0344 array(0,0,0,0,0,1,0,0,0),
0345 array(0,0,0,0,0,1,0,0,0),
0346 array(0,0,0,0,0,1,0,0,0),
0347 array(0,0,0,0,0,1,0,0,0),
0348 array(0,0,0,0,0,1,0,0,0),
0349 array(1,0,0,0,0,1,0,0,0),
0350 array(1,0,0,0,0,1,0,0,0),
0351 array(0,1,0,0,1,0,0,0,0),
0352 array(0,0,1,1,0,0,0,0,0),
0353 ),
0354 'K' => array( // New 'K', supplied by NeoThermic
0355 array(1,0,0,0,0,0,0,0,1),
0356 array(1,0,0,0,0,0,0,1,0),
0357 array(1,0,0,0,0,0,1,0,0),
0358 array(1,0,0,0,0,1,0,0,0),
0359 array(1,0,0,0,1,0,0,0,0),
0360 array(1,0,0,1,0,0,0,0,0),
0361 array(1,0,1,0,0,0,0,0,0),
0362 array(1,1,0,0,0,0,0,0,0),
0363 array(1,0,1,0,0,0,0,0,0),
0364 array(1,0,0,1,0,0,0,0,0),
0365 array(1,0,0,0,1,0,0,0,0),
0366 array(1,0,0,0,0,1,0,0,0),
0367 array(1,0,0,0,0,0,1,0,0),
0368 array(1,0,0,0,0,0,0,1,0),
0369 array(1,0,0,0,0,0,0,0,1),
0370 ),
0371 'L' => array(
0372 array(0,0,0,0,0,0,0,0,0),
0373 array(1,0,0,0,0,0,0,0,0),
0374 array(1,0,0,0,0,0,0,0,0),
0375 array(1,0,0,0,0,0,0,0,0),
0376 array(1,0,0,0,0,0,0,0,0),
0377 array(1,0,0,0,0,0,0,0,0),
0378 array(1,0,0,0,0,0,0,0,0),
0379 array(1,0,0,0,0,0,0,0,0),
0380 array(1,0,0,0,0,0,0,0,0),
0381 array(1,0,0,0,0,0,0,0,0),
0382 array(1,0,0,0,0,0,0,0,0),
0383 array(1,0,0,0,0,0,0,0,0),
0384 array(1,0,0,0,0,0,0,0,0),
0385 array(1,0,0,0,0,0,0,0,0),
0386 array(1,1,1,1,1,1,1,1,1),
0387 ),
0388 'M' => array(
0389 array(1,1,0,0,0,0,0,1,1),
0390 array(1,1,0,0,0,0,0,1,1),
0391 array(1,0,1,0,0,0,1,0,1),
0392 array(1,0,1,0,0,0,1,0,1),
0393 array(1,0,1,0,0,0,1,0,1),
0394 array(1,0,0,1,0,1,0,0,1),
0395 array(1,0,0,1,0,1,0,0,1),
0396 array(1,0,0,1,0,1,0,0,1),
0397 array(1,0,0,0,1,0,0,0,1),
0398 array(1,0,0,0,1,0,0,0,1),
0399 array(1,0,0,0,0,0,0,0,1),
0400 array(1,0,0,0,0,0,0,0,1),
0401 array(1,0,0,0,0,0,0,0,1),
0402 array(1,0,0,0,0,0,0,0,1),
0403 array(1,0,0,0,0,0,0,0,1),
0404 ),
0405 'N' => array(
0406 array(1,1,0,0,0,0,0,0,1),
0407 array(1,1,0,0,0,0,0,0,1),
0408 array(1,0,1,0,0,0,0,0,1),
0409 array(1,0,1,0,0,0,0,0,1),
0410 array(1,0,0,1,0,0,0,0,1),
0411 array(1,0,0,1,0,0,0,0,1),
0412 array(1,0,0,0,1,0,0,0,1),
0413 array(1,0,0,0,1,0,0,0,1),
0414 array(1,0,0,0,1,0,0,0,1),
0415 array(1,0,0,0,0,1,0,0,1),
0416 array(1,0,0,0,0,1,0,0,1),
0417 array(1,0,0,0,0,0,1,0,1),
0418 array(1,0,0,0,0,0,1,0,1),
0419 array(1,0,0,0,0,0,0,1,1),
0420 array(1,0,0,0,0,0,0,1,1),
0421 ),
0422 'O' => array(
0423 array(0,0,1,1,1,1,1,0,0),
0424 array(0,1,0,0,0,0,0,1,0),
0425 array(1,0,0,0,0,0,0,0,1),
0426 array(1,0,0,0,0,0,0,0,1),
0427 array(1,0,0,0,0,0,0,0,1),
0428 array(1,0,0,0,0,0,0,0,1),
0429 array(1,0,0,0,0,0,0,0,1),
0430 array(1,0,0,0,0,0,0,0,1),
0431 array(1,0,0,0,0,0,0,0,1),
0432 array(1,0,0,0,0,0,0,0,1),
0433 array(1,0,0,0,0,0,0,0,1),
0434 array(1,0,0,0,0,0,0,0,1),
0435 array(1,0,0,0,0,0,0,0,1),
0436 array(0,1,0,0,0,0,0,1,0),
0437 array(0,0,1,1,1,1,1,0,0),
0438 ),
0439 'P' => array(
0440 array(1,1,1,1,1,1,1,0,0),
0441 array(1,0,0,0,0,0,0,1,0),
0442 array(1,0,0,0,0,0,0,0,1),
0443 array(1,0,0,0,0,0,0,0,1),
0444 array(1,0,0,0,0,0,0,0,1),
0445 array(1,0,0,0,0,0,0,0,1),
0446 array(1,0,0,0,0,0,0,1,0),
0447 array(1,1,1,1,1,1,1,0,0),
0448 array(1,0,0,0,0,0,0,0,0),
0449 array(1,0,0,0,0,0,0,0,0),
0450 array(1,0,0,0,0,0,0,0,0),
0451 array(1,0,0,0,0,0,0,0,0),
0452 array(1,0,0,0,0,0,0,0,0),
0453 array(1,0,0,0,0,0,0,0,0),
0454 array(1,0,0,0,0,0,0,0,0),
0455 ),
0456 'Q' => array(
0457 array(0,0,1,1,1,1,1,0,0),
0458 array(0,1,0,0,0,0,0,1,0),
0459 array(1,0,0,0,0,0,0,0,1),
0460 array(1,0,0,0,0,0,0,0,1),
0461 array(1,0,0,0,0,0,0,0,1),
0462 array(1,0,0,0,0,0,0,0,1),
0463 array(1,0,0,0,0,0,0,0,1),
0464 array(1,0,0,0,0,0,0,0,1),
0465 array(1,0,0,0,0,0,0,0,1),
0466 array(1,0,0,0,0,0,0,0,1),
0467 array(1,0,0,0,0,0,0,0,1),
0468 array(1,0,0,0,0,1,0,0,1),
0469 array(1,0,0,0,0,0,1,0,1),
0470 array(0,1,0,0,0,0,0,1,0),
0471 array(0,0,1,1,1,1,1,0,1),
0472 ),
0473 'R' => array(
0474 array(1,1,1,1,1,1,1,0,0),
0475 array(1,0,0,0,0,0,0,1,0),
0476 array(1,0,0,0,0,0,0,0,1),
0477 array(1,0,0,0,0,0,0,0,1),
0478 array(1,0,0,0,0,0,0,0,1),
0479 array(1,0,0,0,0,0,0,0,1),
0480 array(1,0,0,0,0,0,0,1,0),
0481 array(1,1,1,1,1,1,1,0,0),
0482 array(1,1,1,0,0,0,0,0,0),
0483 array(1,0,0,1,0,0,0,0,0),
0484 array(1,0,0,0,1,0,0,0,0),
0485 array(1,0,0,0,0,1,0,0,0),
0486 array(1,0,0,0,0,0,1,0,0),
0487 array(1,0,0,0,0,0,0,1,0),
0488 array(1,0,0,0,0,0,0,0,1),
0489 ),
0490 'S' => array(
0491 array(0,0,1,1,1,1,1,0,0),
0492 array(0,1,0,0,0,0,0,1,0),
0493 array(1,0,0,0,0,0,0,0,1),
0494 array(1,0,0,0,0,0,0,0,0),
0495 array(1,0,0,0,0,0,0,0,0),
0496 array(1,0,0,0,0,0,0,0,0),
0497 array(0,1,0,0,0,0,0,0,0),
0498 array(0,0,1,1,1,1,1,0,0),
0499 array(0,0,0,0,0,0,0,1,0),
0500 array(0,0,0,0,0,0,0,0,1),
0501 array(0,0,0,0,0,0,0,0,1),
0502 array(0,0,0,0,0,0,0,0,1),
0503 array(1,0,0,0,0,0,0,0,1),
0504 array(0,1,0,0,0,0,0,1,0),
0505 array(0,0,1,1,1,1,1,0,0),
0506 ),
0507 'T' => array(
0508 array(1,1,1,1,1,1,1,1,1),
0509 array(0,0,0,0,1,0,0,0,0),
0510 array(0,0,0,0,1,0,0,0,0),
0511 array(0,0,0,0,1,0,0,0,0),
0512 array(0,0,0,0,1,0,0,0,0),
0513 array(0,0,0,0,1,0,0,0,0),
0514 array(0,0,0,0,1,0,0,0,0),
0515 array(0,0,0,0,1,0,0,0,0),
0516 array(0,0,0,0,1,0,0,0,0),
0517 array(0,0,0,0,1,0,0,0,0),
0518 array(0,0,0,0,1,0,0,0,0),
0519 array(0,0,0,0,1,0,0,0,0),
0520 array(0,0,0,0,1,0,0,0,0),
0521 array(0,0,0,0,1,0,0,0,0),
0522 array(0,0,0,0,1,0,0,0,0),
0523 ),
0524 'U' => array(
0525 array(1,0,0,0,0,0,0,0,1),
0526 array(1,0,0,0,0,0,0,0,1),
0527 array(1,0,0,0,0,0,0,0,1),
0528 array(1,0,0,0,0,0,0,0,1),
0529 array(1,0,0,0,0,0,0,0,1),
0530 array(1,0,0,0,0,0,0,0,1),
0531 array(1,0,0,0,0,0,0,0,1),
0532 array(1,0,0,0,0,0,0,0,1),
0533 array(1,0,0,0,0,0,0,0,1),
0534 array(1,0,0,0,0,0,0,0,1),
0535 array(1,0,0,0,0,0,0,0,1),
0536 array(1,0,0,0,0,0,0,0,1),
0537 array(1,0,0,0,0,0,0,0,1),
0538 array(0,1,0,0,0,0,0,1,0),
0539 array(0,0,1,1,1,1,1,0,0),
0540 ),
0541 'V' => array(
0542 array(1,0,0,0,0,0,0,0,1),
0543 array(1,0,0,0,0,0,0,0,1),
0544 array(1,0,0,0,0,0,0,0,1),
0545 array(0,1,0,0,0,0,0,1,0),
0546 array(0,1,0,0,0,0,0,1,0),
0547 array(0,1,0,0,0,0,0,1,0),
0548 array(0,0,1,0,0,0,1,0,0),
0549 array(0,0,1,0,0,0,1,0,0),
0550 array(0,0,1,0,0,0,1,0,0),
0551 array(0,0,1,0,0,0,1,0,0),
0552 array(0,0,0,1,0,1,0,0,0),
0553 array(0,0,0,1,0,1,0,0,0),
0554 array(0,0,0,1,0,1,0,0,0),
0555 array(0,0,0,0,1,0,0,0,0),
0556 array(0,0,0,0,1,0,0,0,0),
0557 ),
0558 'W' => array( // New 'W', supplied by MHobbit
0559 array(1,0,0,0,0,0,0,0,1),
0560 array(1,0,0,0,0,0,0,0,1),
0561 array(1,0,0,0,0,0,0,0,1),
0562 array(1,0,0,0,0,0,0,0,1),
0563 array(1,0,0,0,0,0,0,0,1),
0564 array(1,0,0,0,1,0,0,0,1),
0565 array(1,0,0,0,1,0,0,0,1),
0566 array(1,0,0,1,0,1,0,0,1),
0567 array(1,0,0,1,0,1,0,0,1),
0568 array(1,0,0,1,0,1,0,0,1),
0569 array(1,0,1,0,0,0,1,0,1),
0570 array(1,0,1,0,0,0,1,0,1),
0571 array(1,0,1,0,0,0,1,0,1),
0572 array(1,1,0,0,0,0,0,1,1),
0573 array(1,1,0,0,0,0,0,1,1),
0574 ),
0575 'X' => array(
0576 array(1,0,0,0,0,0,0,0,1),
0577 array(1,0,0,0,0,0,0,0,1),
0578 array(0,1,0,0,0,0,0,1,0),
0579 array(0,1,0,0,0,0,0,1,0),
0580 array(0,0,1,0,0,0,1,0,0),
0581 array(0,0,0,1,0,1,0,0,0),
0582 array(0,0,0,1,0,1,0,0,0),
0583 array(0,0,0,0,1,0,0,0,0),
0584 array(0,0,0,1,0,1,0,0,0),
0585 array(0,0,0,1,0,1,0,0,0),
0586 array(0,0,1,0,0,0,1,0,0),
0587 array(0,1,0,0,0,0,1,0,0),
0588 array(0,1,0,0,0,0,0,1,0),
0589 array(1,0,0,0,0,0,0,0,1),
0590 array(1,0,0,0,0,0,0,0,1),
0591 ),
0592 'Y' => array(
0593 array(1,0,0,0,0,0,0,0,1),
0594 array(1,0,0,0,0,0,0,0,1),
0595 array(0,1,0,0,0,0,0,1,0),
0596 array(0,1,0,0,0,0,0,1,0),
0597 array(0,0,1,0,0,0,1,0,0),
0598 array(0,0,1,0,0,0,1,0,0),
0599 array(0,0,0,1,0,1,0,0,0),
0600 array(0,0,0,0,1,0,0,0,0),
0601 array(0,0,0,0,1,0,0,0,0),
0602 array(0,0,0,0,1,0,0,0,0),
0603 array(0,0,0,0,1,0,0,0,0),
0604 array(0,0,0,0,1,0,0,0,0),
0605 array(0,0,0,0,1,0,0,0,0),
0606 array(0,0,0,0,1,0,0,0,0),
0607 array(0,0,0,0,1,0,0,0,0),
0608 ),
0609 'Z' => array( // New 'Z' supplied by Anon
0610 array(1,1,1,1,1,1,1,1,1),
0611 array(1,0,0,0,0,0,0,0,1),
0612 array(0,0,0,0,0,0,0,0,1),
0613 array(0,0,0,0,0,0,0,1,0),
0614 array(0,0,0,0,0,0,1,0,0),
0615 array(0,0,0,0,0,1,0,0,0),
0616 array(0,0,0,0,0,1,0,0,0),
0617 array(0,0,0,0,1,0,0,0,0),
0618 array(0,0,0,1,0,0,0,0,0),
0619 array(0,0,0,1,0,0,0,0,0),
0620 array(0,0,1,0,0,0,0,0,0),
0621 array(0,1,0,0,0,0,0,0,0),
0622 array(1,0,0,0,0,0,0,0,0),
0623 array(1,0,0,0,0,0,0,0,1),
0624 array(1,1,1,1,1,1,1,1,1),
0625 ),
0626 '1' => array(
0627 array(0,0,0,1,1,0,0,0,0),
0628 array(0,0,1,0,1,0,0,0,0),
0629 array(0,1,0,0,1,0,0,0,0),
0630 array(0,0,0,0,1,0,0,0,0),
0631 array(0,0,0,0,1,0,0,0,0),
0632 array(0,0,0,0,1,0,0,0,0),
0633 array(0,0,0,0,1,0,0,0,0),
0634 array(0,0,0,0,1,0,0,0,0),
0635 array(0,0,0,0,1,0,0,0,0),
0636 array(0,0,0,0,1,0,0,0,0),
0637 array(0,0,0,0,1,0,0,0,0),
0638 array(0,0,0,0,1,0,0,0,0),
0639 array(0,0,0,0,1,0,0,0,0),
0640 array(0,0,0,0,1,0,0,0,0),
0641 array(0,1,1,1,1,1,1,1,0),
0642 ),
0643 '2' => array( // New '2' supplied by Anon
0644 array(0,0,0,1,1,1,0,0,0),
0645 array(0,0,1,0,0,0,1,0,0),
0646 array(0,1,0,0,0,0,1,1,0),
0647 array(0,0,0,0,0,0,0,0,1),
0648 array(0,0,0,0,0,0,0,0,1),
0649 array(0,0,0,0,0,0,0,1,1),
0650 array(0,0,0,0,0,0,0,1,0),
0651 array(0,0,0,0,0,0,1,0,0),
0652 array(0,0,0,0,0,1,0,0,0),
0653 array(0,0,0,0,1,0,0,0,0),
0654 array(0,0,0,1,0,0,0,0,0),
0655 array(0,0,1,0,0,0,0,0,0),
0656 array(0,1,0,0,0,0,0,0,0),
0657 array(1,1,1,1,1,1,1,1,1),
0658 array(0,0,0,0,0,0,0,0,0),
0659 ),
0660 '3' => array(
0661 array(0,0,1,1,1,1,1,0,0),
0662 array(0,1,0,0,0,0,0,1,0),
0663 array(1,0,0,0,0,0,0,0,1),
0664 array(0,0,0,0,0,0,0,0,1),
0665 array(0,0,0,0,0,0,0,0,1),
0666 array(0,0,0,0,0,0,0,0,1),
0667 array(0,0,0,0,0,0,0,1,0),
0668 array(0,0,0,0,0,1,1,0,0),
0669 array(0,0,0,0,0,0,0,1,0),
0670 array(0,0,0,0,0,0,0,0,1),
0671 array(0,0,0,0,0,0,0,0,1),
0672 array(0,0,0,0,0,0,0,0,1),
0673 array(1,0,0,0,0,0,0,0,1),
0674 array(0,1,0,0,0,0,0,1,0),
0675 array(0,0,1,1,1,1,1,0,0),
0676 ),
0677 '4' => array(
0678 array(0,0,0,0,0,0,1,1,0),
0679 array(0,0,0,0,0,1,0,1,0),
0680 array(0,0,0,0,1,0,0,1,0),
0681 array(0,0,0,1,0,0,0,1,0),
0682 array(0,0,1,0,0,0,0,1,0),
0683 array(0,1,0,0,0,0,0,1,0),
0684 array(1,0,0,0,0,0,0,1,0),
0685 array(1,0,0,0,0,0,0,1,0),
0686 array(1,1,1,1,1,1,1,1,1),
0687 array(0,0,0,0,0,0,0,1,0),
0688 array(0,0,0,0,0,0,0,1,0),
0689 array(0,0,0,0,0,0,0,1,0),
0690 array(0,0,0,0,0,0,0,1,0),
0691 array(0,0,0,0,0,0,0,1,0),
0692 array(0,0,0,0,0,0,0,1,0),
0693 ),
0694 '5' => array(
0695 array(1,1,1,1,1,1,1,1,1),
0696 array(1,0,0,0,0,0,0,0,0),
0697 array(1,0,0,0,0,0,0,0,0),
0698 array(1,0,0,0,0,0,0,0,0),
0699 array(1,0,0,0,0,0,0,0,0),
0700 array(0,1,0,0,0,0,0,0,0),
0701 array(0,0,1,1,1,1,1,0,0),
0702 array(0,0,0,0,0,0,0,1,0),
0703 array(0,0,0,0,0,0,0,0,1),
0704 array(0,0,0,0,0,0,0,0,1),
0705 array(0,0,0,0,0,0,0,0,1),
0706 array(0,0,0,0,0,0,0,0,1),
0707 array(1,0,0,0,0,0,0,0,1),
0708 array(0,1,0,0,0,0,0,1,0),
0709 array(0,0,1,1,1,1,1,0,0),
0710 ),
0711 '6' => array(
0712 array(0,0,1,1,1,1,1,0,0),
0713 array(0,1,0,0,0,0,0,1,0),
0714 array(1,0,0,0,0,0,0,0,1),
0715 array(1,0,0,0,0,0,0,0,1),
0716 array(1,0,0,0,0,0,0,0,0),
0717 array(1,0,0,0,0,0,0,0,0),
0718 array(1,0,0,1,1,1,1,0,0),
0719 array(1,0,1,0,0,0,0,1,0),
0720 array(1,1,0,0,0,0,0,0,1),
0721 array(1,0,0,0,0,0,0,0,1),
0722 array(1,0,0,0,0,0,0,0,1),
0723 array(1,0,0,0,0,0,0,0,1),
0724 array(1,0,0,0,0,0,0,0,1),
0725 array(0,1,0,0,0,0,0,1,0),
0726 array(0,0,1,1,1,1,1,0,0),
0727 ),
0728 '7' => array(
0729 array(1,1,1,1,1,1,1,1,1),
0730 array(0,0,0,0,0,0,0,0,1),
0731 array(0,0,0,0,0,0,0,1,0),
0732 array(0,0,0,0,0,0,0,1,0),
0733 array(0,0,0,0,0,0,1,0,0),
0734 array(0,0,0,0,0,1,0,0,0),
0735 array(0,0,0,0,0,1,0,0,0),
0736 array(0,0,0,0,1,0,0,0,0),
0737 array(0,0,0,1,0,0,0,0,0),
0738 array(0,0,0,1,0,0,0,0,0),
0739 array(0,0,1,0,0,0,0,0,0),
0740 array(0,1,0,0,0,0,0,0,0),
0741 array(0,1,0,0,0,0,0,0,0),
0742 array(1,0,0,0,0,0,0,0,0),
0743 array(1,0,0,0,0,0,0,0,0),
0744 ),
0745 '8' => array(
0746 array(0,0,1,1,1,1,1,0,0),
0747 array(0,1,0,0,0,0,0,1,0),
0748 array(1,0,0,0,0,0,0,0,1),
0749 array(1,0,0,0,0,0,0,0,1),
0750 array(1,0,0,0,0,0,0,0,1),
0751 array(1,0,0,0,0,0,0,0,1),
0752 array(0,1,0,0,0,0,0,1,0),
0753 array(0,0,1,1,1,1,1,0,0),
0754 array(0,1,0,0,0,0,0,1,0),
0755 array(1,0,0,0,0,0,0,0,1),
0756 array(1,0,0,0,0,0,0,0,1),
0757 array(1,0,0,0,0,0,0,0,1),
0758 array(1,0,0,0,0,0,0,0,1),
0759 array(0,1,0,0,0,0,0,1,0),
0760 array(0,0,1,1,1,1,1,0,0),
0761 ),
0762 '9' => array(
0763 array(0,0,1,1,1,1,1,0,0),
0764 array(0,1,0,0,0,0,0,1,0),
0765 array(1,0,0,0,0,0,0,0,1),
0766 array(1,0,0,0,0,0,0,0,1),
0767 array(1,0,0,0,0,0,0,0,1),
0768 array(1,0,0,0,0,0,0,0,1),
0769 array(1,0,0,0,0,0,0,1,1),
0770 array(0,1,0,0,0,0,1,0,1),
0771 array(0,0,1,1,1,1,0,0,1),
0772 array(0,0,0,0,0,0,0,0,1),
0773 array(0,0,0,0,0,0,0,0,1),
0774 array(1,0,0,0,0,0,0,0,1),
0775 array(1,0,0,0,0,0,0,0,1),
0776 array(0,1,0,0,0,0,0,1,0),
0777 array(0,0,1,1,1,1,1,0,0),
0778 ),
0779 )
0780 );
0781 }
0782 }
0783
0784 /**
0785 * @package VC
0786 */
0787 class char_cube3d
0788 {
0789 var $bitmap;
0790 var $bitmap_width;
0791 var $bitmap_height;
0792
0793 var $basis_matrix = array(array(1, 0, 0), array(0, 1, 0), array(0, 0, 1));
0794 var $abs_x = array(1, 0);
0795 var $abs_y = array(0, 1);
0796 var $x = 0;
0797 var $y = 1;
0798 var $z = 2;
0799 var $letter = '';
0800
0801 /**
0802 */
0803 function char_cube3d(&$bitmaps, $letter)
0804 {
0805 $this->bitmap = $bitmaps['data'][$letter];
0806 $this->bitmap_width = $bitmaps['width'];
0807 $this->bitmap_height = $bitmaps['height'];
0808
0809 $this->basis_matrix[0][0] = mt_rand(-600, 600);
0810 $this->basis_matrix[0][1] = mt_rand(-600, 600);
0811 $this->basis_matrix[0][2] = (mt_rand(0, 1) * 2000) - 1000;
0812 $this->basis_matrix[1][0] = mt_rand(-1000, 1000);
0813 $this->basis_matrix[1][1] = mt_rand(-1000, 1000);
0814 $this->basis_matrix[1][2] = mt_rand(-1000, 1000);
0815
0816 $this->normalize($this->basis_matrix[0]);
0817 $this->normalize($this->basis_matrix[1]);
0818 $this->basis_matrix[2] = $this->cross_product($this->basis_matrix[0], $this->basis_matrix[1]);
0819 $this->normalize($this->basis_matrix[2]);
0820
0821 // $this->basis_matrix[1] might not be (probably isn't) orthogonal to $basis_matrix[0]
0822 $this->basis_matrix[1] = $this->cross_product($this->basis_matrix[0], $this->basis_matrix[2]);
0823 $this->normalize($this->basis_matrix[1]);
0824
0825 // Make sure our cube is facing into the canvas (assuming +z == in)
0826 for ($i = 0; $i < 3; ++$i)
0827 {
0828 if ($this->basis_matrix[$i][2] < 0)
0829 {
0830 $this->basis_matrix[$i][0] *= -1;
0831 $this->basis_matrix[$i][1] *= -1;
0832 $this->basis_matrix[$i][2] *= -1;
0833 }
0834 }
0835
0836 // Force our "z" basis vector to be the one with greatest absolute z value
0837 $this->x = 0;
0838 $this->y = 1;
0839 $this->z = 2;
0840
0841 // Swap "y" with "z"
0842 if ($this->basis_matrix[1][2] > $this->basis_matrix[2][2])
0843 {
0844 $this->z = 1;
0845 $this->y = 2;
0846 }
0847
0848 // Swap "x" with "z"
0849 if ($this->basis_matrix[0][2] > $this->basis_matrix[$this->z][2])
0850 {
0851 $this->x = $this->z;
0852 $this->z = 0;
0853 }
0854
0855 // Still need to determine which of $x,$y are which.
0856 // wrong orientation if y's y-component is less than it's x-component
0857 // likewise if x's x-component is less than it's y-component
0858 // if they disagree, go with the one with the greater weight difference.
0859 // rotate if positive
0860 $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]));
0861
0862 // Swap "x" with "y"
0863 if ($weight > 0)
0864 {
0865 list($this->x, $this->y) = array($this->y, $this->x);
0866 }
0867
0868 $this->abs_x = array($this->basis_matrix[$this->x][0], $this->basis_matrix[$this->x][1]);
0869 $this->abs_y = array($this->basis_matrix[$this->y][0], $this->basis_matrix[$this->y][1]);
0870
0871 if ($this->abs_x[0] < 0)
0872 {
0873 $this->abs_x[0] *= -1;
0874 $this->abs_x[1] *= -1;
0875 }
0876
0877 if ($this->abs_y[1] > 0)
0878 {
0879 $this->abs_y[0] *= -1;
0880 $this->abs_y[1] *= -1;
0881 }
0882
0883 $this->letter = $letter;
0884 }
0885
0886 /**
0887 * Draw a character
0888 */
0889 function drawchar($scale, $xoff, $yoff, $img, $background, $colours)
0890 {
0891 $width = $this->bitmap_width;
0892 $height = $this->bitmap_height;
0893 $bitmap = $this->bitmap;
0894
0895 $colour1 = $colours[array_rand($colours)];
0896 $colour2 = $colours[array_rand($colours)];
0897
0898 $swapx = ($this->basis_matrix[$this->x][0] > 0);
0899 $swapy = ($this->basis_matrix[$this->y][1] < 0);
0900
0901 for ($y = 0; $y < $height; ++$y)
0902 {
0903 for ($x = 0; $x < $width; ++$x)
0904 {
0905 $xp = ($swapx) ? ($width - $x - 1) : $x;
0906 $yp = ($swapy) ? ($height - $y - 1) : $y;
0907
0908 if ($bitmap[$height - $yp - 1][$xp])
0909 {
0910 $dx = $this->scale($this->abs_x, ($xp - ($swapx ? ($width / 2) : ($width / 2) - 1)) * $scale);
0911 $dy = $this->scale($this->abs_y, ($yp - ($swapy ? ($height / 2) : ($height / 2) - 1)) * $scale);
0912 $xo = $xoff + $dx[0] + $dy[0];
0913 $yo = $yoff + $dx[1] + $dy[1];
0914
0915 $origin = array(0, 0, 0);
0916 $xvec = $this->scale($this->basis_matrix[$this->x], $scale);
0917 $yvec = $this->scale($this->basis_matrix[$this->y], $scale);
0918 $face_corner = $this->sum2($xvec, $yvec);
0919
0920 $zvec = $this->scale($this->basis_matrix[$this->z], $scale);
0921 $x_corner = $this->sum2($xvec, $zvec);
0922 $y_corner = $this->sum2($yvec, $zvec);
0923
0924 imagefilledpolygon($img, $this->gen_poly($xo, $yo, $origin, $xvec, $x_corner,$zvec), 4, $colour1);
0925 imagefilledpolygon($img, $this->gen_poly($xo, $yo, $origin, $yvec, $y_corner,$zvec), 4, $colour2);
0926
0927 $face = $this->gen_poly($xo, $yo, $origin, $xvec, $face_corner, $yvec);
0928
0929 imagefilledpolygon($img, $face, 4, $background);
0930 imagepolygon($img, $face, 4, $colour1);
0931 }
0932 }
0933 }
0934 }
0935
0936 /*
0937 * return a roughly acceptable range of sizes for rendering with this texttype
0938 */
0939 function range()
0940 {
0941 return array(3, 4);
0942 }
0943
0944 /**
0945 * Vector length
0946 */
0947 function vectorlen($vector)
0948 {
0949 return sqrt(pow($vector[0], 2) + pow($vector[1], 2) + pow($vector[2], 2));
0950 }
0951
0952 /**
0953 * Normalize
0954 */
0955 function normalize(&$vector, $length = 1)
0956 {
0957 $length = (( $length < 1) ? 1 : $length);
0958 $length /= $this->vectorlen($vector);
0959 $vector[0] *= $length;
0960 $vector[1] *= $length;
0961 $vector[2] *= $length;
0962 }
0963
0964 /**
0965 */
0966 function cross_product($vector1, $vector2)
0967 {
0968 $retval = array(0, 0, 0);
0969 $retval[0] = (($vector1[1] * $vector2[2]) - ($vector1[2] * $vector2[1]));
0970 $retval[1] = -(($vector1[0] * $vector2[2]) - ($vector1[2] * $vector2[0]));
0971 $retval[2] = (($vector1[0] * $vector2[1]) - ($vector1[1] * $vector2[0]));
0972
0973 return $retval;
0974 }
0975
0976 /**
0977 */
0978 function sum($vector1, $vector2)
0979 {
0980 return array($vector1[0] + $vector2[0], $vector1[1] + $vector2[1], $vector1[2] + $vector2[2]);
0981 }
0982
0983 /**
0984 */
0985 function sum2($vector1, $vector2)
0986 {
0987 return array($vector1[0] + $vector2[0], $vector1[1] + $vector2[1]);
0988 }
0989
0990 /**
0991 */
0992 function scale($vector, $length)
0993 {
0994 if (sizeof($vector) == 2)
0995 {
0996 return array($vector[0] * $length, $vector[1] * $length);
0997 }
0998
0999 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 */
1053 class 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 ?>