1<?php 2/** 3 * VizHash_GD 4 * 5 * Visual Hash implementation in php4+GD, 6 * stripped down and modified version for PrivateBin 7 * 8 * @link http://sebsauvage.net/wiki/doku.php?id=php:vizhash_gd 9 * @copyright 2012 Sébastien SAUVAGE (sebsauvage.net) 10 * @license https://www.opensource.org/licenses/zlib-license.php The zlib/libpng License 11 * @version 0.0.5 beta PrivateBin 1.3.5 12 */ 13 14namespace PrivateBin; 15 16/** 17 * Vizhash16x16 18 * 19 * Example: 20 * $vz = new Vizhash16x16(); 21 * $data = $vz->generate(sha512('hello')); 22 * header('Content-type: image/png'); 23 * echo $data; 24 * exit; 25 */ 26class Vizhash16x16 27{ 28 /** 29 * hash values 30 * 31 * @access private 32 * @var array 33 */ 34 private $VALUES; 35 36 /** 37 * index of current value 38 * 39 * @access private 40 * @var int 41 */ 42 private $VALUES_INDEX; 43 44 /** 45 * image width 46 * 47 * @access private 48 * @var int 49 */ 50 private $width; 51 52 /** 53 * image height 54 * 55 * @access private 56 * @var int 57 */ 58 private $height; 59 60 /** 61 * constructor 62 * 63 * @access public 64 */ 65 public function __construct() 66 { 67 $this->width = 16; 68 $this->height = 16; 69 } 70 71 /** 72 * Generate a 16x16 png corresponding to $text. 73 * 74 * The given text should to be 128 to 150 characters long 75 * 76 * @access public 77 * @param string $text 78 * @return string PNG data. Or empty string if GD is not available. 79 */ 80 public function generate($text) 81 { 82 if (!function_exists('gd_info')) { 83 return ''; 84 } 85 86 $textlen = strlen($text); 87 88 // We convert the hash into an array of integers. 89 $this->VALUES = array(); 90 for ($i = 0; $i < $textlen; $i = $i + 2) { 91 array_push($this->VALUES, hexdec(substr($text, $i, 2))); 92 } 93 $this->VALUES_INDEX = 0; // to walk the array. 94 95 // Then use these integers to drive the creation of an image. 96 $image = imagecreatetruecolor($this->width, $this->height); 97 98 $r = $r0 = $this->getInt(); 99 $g = $g0 = $this->getInt(); 100 $b = $b0 = $this->getInt(); 101 102 // First, create an image with a specific gradient background. 103 $op = 'v'; 104 if (($this->getInt() % 2) == 0) { 105 $op = 'h'; 106 } 107 $image = $this->degrade($image, $op, array($r0, $g0, $b0), array(0, 0, 0)); 108 109 for ($i = 0; $i < 7; ++$i) { 110 $action = $this->getInt(); 111 $color = imagecolorallocate($image, $r, $g, $b); 112 $r = $r0 = ($r0 + $this->getInt() / 25) % 256; 113 $g = $g0 = ($g0 + $this->getInt() / 25) % 256; 114 $b = $b0 = ($b0 + $this->getInt() / 25) % 256; 115 $this->drawshape($image, $action, $color); 116 } 117 118 $color = imagecolorallocate($image, $this->getInt(), $this->getInt(), $this->getInt()); 119 $this->drawshape($image, $this->getInt(), $color); 120 ob_start(); 121 imagepng($image); 122 $imagedata = ob_get_contents(); 123 ob_end_clean(); 124 imagedestroy($image); 125 126 return $imagedata; 127 } 128 129 /** 130 * Returns a single integer from the $VALUES array (0...255) 131 * 132 * @access private 133 * @return int 134 */ 135 private function getInt() 136 { 137 $v = $this->VALUES[$this->VALUES_INDEX]; 138 ++$this->VALUES_INDEX; 139 $this->VALUES_INDEX %= count($this->VALUES); // Warp around the array 140 return $v; 141 } 142 143 /** 144 * Returns a single integer from the array (roughly mapped to image width) 145 * 146 * @access private 147 * @return int 148 */ 149 private function getX() 150 { 151 return $this->width * $this->getInt() / 256; 152 } 153 154 /** 155 * Returns a single integer from the array (roughly mapped to image height) 156 * 157 * @access private 158 * @return int 159 */ 160 private function getY() 161 { 162 return $this->height * $this->getInt() / 256; 163 } 164 165 /** 166 * Gradient function 167 * 168 * taken from: 169 * http://www.supportduweb.com/scripts_tutoriaux-code-source-41-gd-faire-un-degrade-en-php-gd-fonction-degrade-imagerie.html 170 * 171 * @access private 172 * @param resource $img 173 * @param string $direction 174 * @param array $color1 175 * @param array $color2 176 * @return resource 177 */ 178 private function degrade($img, $direction, $color1, $color2) 179 { 180 if ($direction == 'h') { 181 $size = imagesx($img); 182 $sizeinv = imagesy($img); 183 } else { 184 $size = imagesy($img); 185 $sizeinv = imagesx($img); 186 } 187 $diffs = array( 188 (($color2[0] - $color1[0]) / $size), 189 (($color2[1] - $color1[1]) / $size), 190 (($color2[2] - $color1[2]) / $size), 191 ); 192 for ($i = 0; $i < $size; ++$i) { 193 $r = $color1[0] + ($diffs[0] * $i); 194 $g = $color1[1] + ($diffs[1] * $i); 195 $b = $color1[2] + ($diffs[2] * $i); 196 if ($direction == 'h') { 197 imageline($img, $i, 0, $i, $sizeinv, imagecolorallocate($img, $r, $g, $b)); 198 } else { 199 imageline($img, 0, $i, $sizeinv, $i, imagecolorallocate($img, $r, $g, $b)); 200 } 201 } 202 return $img; 203 } 204 205 /** 206 * Draw a shape 207 * 208 * @access private 209 * @param resource $image 210 * @param int $action 211 * @param int $color 212 */ 213 private function drawshape($image, $action, $color) 214 { 215 switch ($action % 7) { 216 case 0: 217 imagefilledrectangle($image, $this->getX(), $this->getY(), $this->getX(), $this->getY(), $color); 218 break; 219 case 1: 220 case 2: 221 imagefilledellipse($image, $this->getX(), $this->getY(), $this->getX(), $this->getY(), $color); 222 break; 223 case 3: 224 $points = array($this->getX(), $this->getY(), $this->getX(), $this->getY(), $this->getX(), $this->getY(), $this->getX(), $this->getY()); 225 imagefilledpolygon($image, $points, 4, $color); 226 break; 227 default: 228 $start = $this->getInt() * 360 / 256; 229 $end = $start + $this->getInt() * 180 / 256; 230 imagefilledarc($image, $this->getX(), $this->getY(), $this->getX(), $this->getY(), $start, $end, $color, IMG_ARC_PIE); 231 } 232 } 233} 234