1<?php 2// AVAST! This be version 2007.05.22, 8:07pm DST. 3 4// Source code copyright (c) 2007, Ben Hendel-Doying 5// A few rights reserved... 6 7// Inspired by Don Park's original idea, and Charles Darke's PHP implementation 8// (I didn't happen to like Charles Darke's implementation, so this is my own) 9// (I kind of wish my name rhymed with Park and Darke...) 10 11// Generates a 9-square "ycon" using a seed out of a few (16) shapes. 12// Interesting seeds include names, IP addresses, e-mail addresses, the current 13// temperature where you live, the phase of the moon, your cat's name, or 14// anything else. Some of these are arguably more interesting than others >_> 15 16// THIS SOFTWARE IS PROVIDED BY Ben Hendel-Doying ``AS IS'' AND ANY 17// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19// DISCLAIMED. IN NO EVENT SHALL Ben Hendel-Doying BE LIABLE FOR ANY 20// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 21// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 22// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 23// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 25// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 27//////////////////////////////////////////////////////////////////////////////// 28 29// this is an arbitrary prime number, nice to add before hashing if you want to 30// additionally secure the seed value (ex: IP, e-mail, internal userid, etc). 31// HEY! DON'T USE THE PRIME PROVIDED HERE! GO FIND YOUR OWN! FOR SERIOUSLY! 32 33$ycon_salt = 263167; 34 35// some web sites that provide prime numbers: 36// * http://www.rsok.com/~jrm/printprimes.html 37// * http://en.wikipedia.org/wiki/List_of_prime_numbers 38 39//////////////////////////////////////////////////////////////////////////////// 40 41// the actual function! returns a true-color image resource, suitable for 42// imagepng'ing, or whatever else you'd like to do with it. 43 44// $hash is a 16-byte hash (for example, as generated from md5()) 45// $size is the total width and height, in pixels, of the ycon to be generated 46// $bg_* describe the background (transparent) color to be used, [0..255] 47 48function ycon($hash, $size, $bg_red, $bg_green, $bg_blue) 49{ 50 $draw_size = $size * 4; 51 52 $red = hexdec(substr($hash, 0, 3)) % 12; // 0-192 for color 53 $green = hexdec(substr($hash, 3, 3)) % 12; // (in increments of 16) 54 $blue = hexdec(substr($hash, 6, 3)) % 12; 55 56 $corners = hexdec(substr($hash, 9, 1)) % 16; // 14 gylphs 57 $corners_i = hexdec(substr($hash, 10, 1)) % 2; // inverted? 58 $corners_a = hexdec(substr($hash, 11, 1)) % 4; // 4 rotations 59 60 $edges = hexdec(substr($hash, 12, 1)) % 16; 61 $edges_i = hexdec(substr($hash, 13, 1)) % 2; 62 $edges_a = hexdec(substr($hash, 14, 1)) % 4; 63 64 $center = hexdec(substr($hash, 15, 2)) % 6; // 3 gylphs + 3 inverted 65 66 $square = $draw_size / 3; 67 68 $icon = imagecreatetruecolor($size, $size); 69 $draw_icon = imagecreatetruecolor($draw_size, $draw_size); 70 71 $background = imagecolorallocate($icon, $bg_red, $bg_green, $bg_blue); 72 $color = imagecolorallocate($icon, $red * 16, $green * 16, $blue * 16); 73 74 imagecolortransparent($icon, $background); 75 76 $shape = $corners; 77 $inverted = ($corners_i == 0); 78 $rotation = $corners_a; 79 80 draw_glpyh($draw_icon, 0, 0, $square, $color, $background, $shape, $rotation % 4, $inverted); 81 draw_glpyh($draw_icon, $square * 2, 0, $square, $color, $background, $shape, ($rotation + 1) % 4, $inverted); 82 draw_glpyh($draw_icon, $square * 2, $square * 2, $square, $color, $background, $shape, ($rotation + 2) % 4, $inverted); 83 draw_glpyh($draw_icon, 0, $square * 2, $square, $color, $background, $shape, ($rotation + 3) % 4, $inverted); 84 85 $shape = $edges; 86 $inverted = ($edges_i == 0); 87 $rotation = $edges_a; 88 89 draw_glpyh($draw_icon, $square, 0, $square, $color, $background, $shape, $rotation % 4, $inverted); 90 draw_glpyh($draw_icon, $square * 2, $square, $square, $color, $background, $shape, ($rotation + 1) % 4, $inverted); 91 draw_glpyh($draw_icon, $square, $square * 2, $square, $color, $background, $shape, ($rotation + 2) % 4, $inverted); 92 draw_glpyh($draw_icon, 0, $square, $square, $color, $background, $shape, ($rotation + 3) % 4, $inverted); 93 94 $shape = (int)($center / 2); 95 $inverted = (($center % 2) == 0); 96 97 draw_glpyh($draw_icon, $square, $square, $square, $color, $background, $shape, 0, $inverted); 98 99 imagecopyresampled($icon, $draw_icon, 0, 0, 0, 0, $size, $size, $draw_size, $draw_size); 100 101 imagedestroy($draw_icon); 102 103 return $icon; 104} 105 106//////////////////////////////////////////////////////////////////////////////// 107 108// function used internally to draw an individual glyph; one of the little guys 109// that goes into one of the 9-squares of ycon. you probably won't need to 110// call this yourself, but there it is... 111 112function draw_glpyh(&$image, $x, $y, $full, $fg_color, $bg_color, $shape, $rotation, $inverted) 113{ 114 $quarter = $full / 4; 115 $half = $full / 2; 116 117 if($inverted) 118 { 119 imagefilledpolygon($image, array(0 + $x, 0 + $y, 0 + $x, $full + $y, $full + $x, $full + $y, $full + $x, 0 + $y), 4, $fg_color); 120 $drawing_color = $bg_color; 121 } 122 else 123 { 124 imagefilledpolygon($image, array(0 + $x, 0 + $y, 0 + $x, $full + $y, $full + $x, $full + $y, $full + $x, 0 + $y), 4, $bg_color); 125 $drawing_color = $fg_color; 126 } 127 128 switch($shape) 129 { 130 // the first few shapes are visually unchanged by 90� rotations, and thus 131 // suitable for the center glyph 132 133 case 0: // full square 134 $points = array( 135 0, 0, 136 $full, 0, 137 $full, $full, 138 0, $full); 139 break; 140 141 case 1: // large diamond 142 $points = array( 143 $half, 0, 144 $full, $half, 145 $half, $full, 146 0, $half); 147 break; 148 149 case 2: // center square 150 $points = array( 151 $quarter, $quarter, 152 $half + $quarter, $quarter, 153 $half + $quarter, $half + $quarter, 154 $quarter, $half + $quarter); 155 break; 156 157 // okay, now we start with the interesting ones that change with rotation 158 159 case 3: // tilted isosceles triangle 160 $points = array( 161 $full, 0, 162 $half, $full, 163 0, $half); 164 break; 165 166 case 4: // squat isosceles triangle 167 $points = array( 168 $half, $half, 169 $full, $full, 170 0, $full); 171 break; 172 173 case 5: // corner square 174 $points = array( 175 $half, $half, 176 $half, $full, 177 0, $full, 178 0, $half); 179 break; 180 181 case 6: // rectangle 182 $points = array( 183 0, $half, 184 $full, $half, 185 $full, $full, 186 0, $full); 187 break; 188 189 case 7: // skewed hourglass on its side 190 $points = array( 191 0, 0, 192 $full, $full, 193 $full, $half, 194 0, $half); 195 break; 196 197 case 8: // upsidedown squat isosceles triangle 198 $points = array( 199 0, $half, 200 $full, $half, 201 $half, $full); 202 break; 203 204 case 9: // corner square, except one corner is pulled to the kitty-corner 205 $points = array( 206 $full, 0, 207 $half, $full, 208 0, $full, 209 0, $half); 210 break; 211 212 case 10: // large isosceles triangle 213 $points = array( 214 $half, 0, 215 $full, $full, 216 0, $full); 217 break; 218 219 case 11: // large right triangle 220 $points = array( 221 0, 0, 222 $full, $full, 223 0, $full); 224 break; 225 226 case 12: // hourglass 227 $points = array( 228 0, 0, 229 $full, $full, 230 0, $full, 231 $full, 0); 232 break; 233 234 case 13: // squat diamond 235 $points = array( 236 $quarter, 0, 237 $half, $half, 238 $quarter, $full, 239 0, $half); 240 break; 241 242 case 14: // hourglass on its side (and kinda' squished...) 243 $points = array( 244 0, $half, 245 $full, $full, 246 $full, $half, 247 0, $full); 248 break; 249 250 case 15: // corner triangle 251 $points = array( 252 0, $half, 253 $half, $half, 254 $half, $full); 255 break; 256 257 default: 258 die('$shape must be in range [0..13] (' . $shape . ' is out of range)'); 259 } 260 261 // for each point 262 for($p = 0; $p < count($points) / 2; ++$p) 263 { 264 // normalized 265 $normalized_x = $points[$p * 2] - $half; 266 $normalized_y = $points[$p * 2 + 1] - $half; 267 268 // then rotate 269 for($i = 0; $i < $rotation; ++$i) 270 { 271 $old_x = $normalized_x; 272 273 $normalized_x = -$normalized_y; 274 $normalized_y = $old_x; 275 } 276 277 // then de-normalize and offset 278 $points[$p * 2] = $normalized_x + $half + $x; 279 $points[$p * 2 + 1] = $normalized_y + $half + $y; 280 } 281 282 // draw the bastard 283 imagefilledpolygon($image, $points, count($points) / 2, $drawing_color); 284} 285 286?>