PageRenderTime 43ms CodeModel.GetById 14ms RepoModel.GetById 0ms app.codeStats 0ms

/src/logic/SimpleCaptchaGenerator.class.php

https://github.com/okinaka/soy-inquiry
PHP | 359 lines | 251 code | 62 blank | 46 comment | 17 complexity | a147f48e97b37103eac72fae6abbe5d6 MD5 | raw file
Possible License(s): GPL-2.0
  1. <?php
  2. /**
  3. * SimpleCaptchaGenerator
  4. *
  5. * CAPTCHA画像生成ツール
  6. */
  7. class SimpleCaptchaGenerator{
  8. private $fonts = array("Arial");
  9. private $width = 200; //ディフォルトの幅
  10. private $height = 50; //ディフォルトの高さ
  11. private $bgRange = array(60, 160); //背景色の範囲
  12. private $borderRange = array(60,160); //邪魔線の範囲
  13. private $fgRange = array(100, 255); //文字色の範囲
  14. private $contrast = 1;//1.24;
  15. private $sizeRange = array(0.3, 0.6); //文字の大きさの範囲
  16. private $rotRange = array(-20, 20); //回転の範囲
  17. private $maxLine = 10; //邪魔線の最大本数
  18. private $maxLineWidth = 5; //邪魔線の最大幅
  19. private $blurCount = 1; //ぼかし線の数
  20. private $blurLevel = array(0.2, 3, 3, 3); //ぼかしレベル 大きさ、傾き、x, y
  21. private $wrapWidth = 10;
  22. private $wrapCount = 1;
  23. private $noise = false;
  24. private $lines = true;
  25. private $debug = false;
  26. /*
  27. * Singleton
  28. */
  29. private function SimpleCaptchaGenerator(){}
  30. public static function getInstance(){
  31. static $_inst;
  32. if(!$_inst)$_inst = new SimpleCaptchaGenerator();
  33. return $_inst;
  34. }
  35. /**
  36. * 画像を出力して終了
  37. */
  38. function output($text, $width = null, $height = null){
  39. $img = $this->generate($text, $width, $height);
  40. if($this->debug){
  41. imagejpeg($img,"test.jpg");
  42. echo "<img src='test.jpg' />";
  43. exit;
  44. }
  45. header('Content-type: image/jpeg');
  46. imagejpeg($img);
  47. imagedestroy($img);
  48. exit;
  49. }
  50. /**
  51. * 画像生成
  52. */
  53. function generate($text, $width = null, $height = null){
  54. $self = $this;
  55. if(!is_null($width))$self->width = $width;
  56. if(!is_null($height))$self->height = $height;
  57. $width = $self->width;
  58. $height = $self->height;
  59. $im = imagecreate($width, $height);
  60. $data = array();
  61. $maxWidth = $width / strlen($text) - 5;
  62. /*
  63. * 文字の大きさとかの準備
  64. */
  65. for($i=0; $i<strlen($text); $i++) {
  66. $char = substr($text, $i, 1);
  67. $size = mt_rand($height * $self->sizeRange[0], $height * $self->sizeRange[1]);
  68. $angle = mt_rand($self->rotRange[0], $self->rotRange[1]);
  69. $key = array_rand($self->fonts);
  70. $font = $self->fonts[$key];
  71. $bbox = imagettfbbox( (float)$size, (float)$angle, $font, $char );
  72. $char_width = max($bbox[2],$bbox[4]) - min($bbox[0],$bbox[6]);
  73. $char_height = max($bbox[1],$bbox[3]) - min($bbox[7],$bbox[5]);
  74. $pos_x = ($i>0) ? $data[$i-1]['pos_x'] + $data[$i-1]['char_width'] : 5;
  75. $pos_y = ($height + $char_height) / 2;
  76. $pos_x += mt_rand(0,$width * (1 - $self->sizeRange[1]) / strlen($text) / 2);
  77. $char_width = max($char_width, $maxWidth);
  78. $data[$i] = array(
  79. 'char' => $char,
  80. 'size' => $size,
  81. 'angle' => $angle,
  82. 'font' => $font,
  83. 'char_height' => $char_height,
  84. 'char_width' => $char_width,
  85. 'pos_x' => $pos_x,
  86. 'pos_y' => $pos_y,
  87. 'color' => 0,
  88. );
  89. for($j=0; $j<$self->blurCount; $j++) {
  90. $data[$i]['blur'][$j] = array (
  91. 'size' => $size*(1+(mt_rand(-$self->blurLevel[0],$self->blurLevel[0])/100)),
  92. 'angle' => $angle+mt_rand(-$self->blurLevel[1],$self->blurLevel[1]),
  93. 'pos_x' => $pos_x+mt_rand(-$self->blurLevel[2],$self->blurLevel[2]),
  94. 'pos_y' => $pos_y+mt_rand(-$self->blurLevel[3],$self->blurLevel[3]),
  95. );
  96. }
  97. }
  98. //邪魔線の本数
  99. $lineCount = min($self->maxLine,mt_rand($self->maxLine,strlen($text)-1));
  100. //色の準備
  101. $color_bg=imagecolorallocate($im, $self->getBgColor(), $self->getBgColor(), $self->getBgColor());
  102. $color_border=imagecolorallocate($im, 0,0,0);
  103. for($i=0; $i<strlen($text); $i++) {
  104. $data[$i]['color'] = imagecolorallocate($im, $self->getFgColor(), $self->getFgColor(), $self->getFgColor());
  105. }
  106. $line_color = array();
  107. for($i=0;$i<$lineCount; $i++){
  108. $line_color[$i]=imagecolorallocate($im, $self->getBorderColor(), $self->getBorderColor(), $self->getBorderColor());
  109. }
  110. /*
  111. * 邪魔線の記述
  112. */
  113. if($self->lines)$self->drawLines($im, $lineCount, $line_color);
  114. /*
  115. * 文字の出力
  116. */
  117. $self->drawWords($im, $data);
  118. /*
  119. * ノイズの出力
  120. */
  121. if($self->noise)$self->drawNoise($im);
  122. /*
  123. * ゆがませる
  124. */
  125. //$self->drawWrap($im);
  126. /*
  127. * 枠線を記述
  128. */
  129. imagerectangle($im, 0, 0, $width-1, $height-1, $color_border);
  130. return $im;
  131. }
  132. function drawWords($im, $data){
  133. $l=0;
  134. foreach($data as $d) {
  135. imagettftext($im, $d['size'], $d['angle'], $d['pos_x'], $d['pos_y'], $d['color'], $d['font'], $d['char'] );
  136. for($j=0; $j<$this->blurCount; $j++) {
  137. imagettftext($im, $d['blur'][$j]['size'], $d['blur'][$j]['angle'], $d['blur'][$j]['pos_x'], $d['blur'][$j]['pos_y'], $d['color'], $d['font'], $d['char'] );
  138. }
  139. }
  140. }
  141. function drawLines($im,$lineCount,$line_color){
  142. $width = $this->width;
  143. $height = $this->height;
  144. for($l=0; $l<$lineCount; $l++) {
  145. $thick = mt_rand(1,$this->maxLineWidth);
  146. if($l % 2 == 1) { // alternate between top-to-bottom and side-to-side lines
  147. $line_data[$l] = array( // horizontal
  148. 0,mt_rand(0,$height),
  149. $width,mt_rand(0,$height),
  150. $width,0,
  151. 0,0,
  152. );
  153. $line_data[$l][5] = $line_data[$l][3] + $thick;
  154. $line_data[$l][7] = $line_data[$l][1] + $thick;
  155. } else {
  156. $line_data[$l] = array( // vertical
  157. mt_rand(0,$width),0,
  158. mt_rand(0,$width),$height,
  159. 0,$height,
  160. 0,0,
  161. );
  162. $line_data[$l][4] = $line_data[$l][2] + $thick;
  163. $line_data[$l][6] = $line_data[$l][0] + $thick;
  164. }
  165. imagefilledpolygon($im, $line_data[$l], 4, $line_color[$l]);
  166. }
  167. }
  168. function drawWrap($im){
  169. if($this->wrapCount < 1)return;
  170. $cycle = $this->width / ($this->wrapCount * pi() * 2);
  171. $lamda = create_function('$v','return '. $this->wrapWidth.' * sin($v / '. $cycle.');');
  172. $target = imagecreate($this->width, $this->height);
  173. for($i=0; $i<$this->width; $i++){
  174. $y = $lamda($i);
  175. imagecopy($target, $im, $i, $y, $i, 0, 1, $this->height);
  176. }
  177. // $cycle = $this->height / ($this->wrapCount * pi() * 2);
  178. //
  179. // $lamda = create_function('$v','return '. $this->wrapWidth.' * cos($v / '. $cycle.');');
  180. //
  181. // $target = imagecreate($this->width, $this->height);
  182. //
  183. // for($i=0; $i<$this->height; $i++){
  184. // $x = $lamda($i);
  185. // imagecopy($target, $im, $x, $i, 0, $i, $this->width, 1);
  186. // }
  187. imagecopy($im, $target, 0, 0, 0, 0, $this->width, $this->height);
  188. imagedestroy($target);
  189. }
  190. function getBgColor(){
  191. return $this->contrast * $this->getRandomColor($this->bgRange[0],$this->bgRange[1]);
  192. }
  193. function getBorderColor(){
  194. return $this->contrast * $this->getRandomColor($this->borderRange[0],$this->borderRange[1]);
  195. }
  196. function getFgColor(){
  197. return $this->contrast * $this->getRandomColor($this->fgRange[0],$this->fgRange[1]);
  198. }
  199. function getRandomColor($min, $max){
  200. $min = max(0,min(255,$min));
  201. $max = max(0,min(255,$max));
  202. $out = mt_rand($min,$max);
  203. //echo $min . "," . $max . " -&gt; " . $out. "<br>";
  204. return $out;
  205. }
  206. function getFonts() {
  207. return $this->fonts;
  208. }
  209. function setFonts($fonts) {
  210. $this->fonts = $fonts;
  211. }
  212. function getWidth() {
  213. return $this->width;
  214. }
  215. function setWidth($width) {
  216. $this->width = $width;
  217. }
  218. function getHeight() {
  219. return $this->height;
  220. }
  221. function setHeight($height) {
  222. $this->height = $height;
  223. }
  224. function getBgRange() {
  225. return $this->bgRange;
  226. }
  227. function setBgRange($bgRange) {
  228. $this->bgRange = func_get_args();
  229. }
  230. function getFgRange() {
  231. return $this->fgRange;
  232. }
  233. function setFgRange($fgRange) {
  234. $this->fgRange = func_get_args();
  235. }
  236. function getContrast() {
  237. return $this->contrast;
  238. }
  239. function setContrast($contrast) {
  240. $this->contrast = $contrast;
  241. }
  242. function getSizeRange() {
  243. return $this->sizeRange;
  244. }
  245. function setSizeRange($sizeRange) {
  246. $this->sizeRange = $sizeRange;
  247. }
  248. function getRotRange() {
  249. return $this->rotRange;
  250. }
  251. function setRotRange($rotRange) {
  252. $this->rotRange = $rotRange;
  253. }
  254. function getMaxLine() {
  255. return $this->maxLine;
  256. }
  257. function setMaxLine($maxLine) {
  258. $this->maxLine = $maxLine;
  259. }
  260. function getMaxLineWidth() {
  261. return $this->maxLineWidth;
  262. }
  263. function setMaxLineWidth($maxLineWidth) {
  264. $this->maxLineWidth = $maxLineWidth;
  265. }
  266. function getBlurCount() {
  267. return $this->blurCount;
  268. }
  269. function setBlurCount($blurCount) {
  270. $this->blurCount = $blurCount;
  271. }
  272. function getBlurLevel() {
  273. return $this->blurLevel;
  274. }
  275. function setBlurLevel($blurLevel) {
  276. $this->blurLevel = $blurLevel;
  277. }
  278. function getNoise() {
  279. return $this->noise;
  280. }
  281. function setNoise($noise) {
  282. $this->noise = $noise;
  283. }
  284. function getLines() {
  285. return $this->lines;
  286. }
  287. function setLines($lines) {
  288. $this->lines = $lines;
  289. }
  290. function getBorderRange() {
  291. return $this->borderRange;
  292. }
  293. function setBorderRange() {
  294. $this->borderRange = func_get_args();
  295. }
  296. }
  297. ?>