<?php
002 class Captcha
003 {
004 private $_about = array(
005 'imageLine'=>8, // 線條幹擾,為0正常
006 'imagePixel'=>300, // 像素幹擾,為0正常
007 'location'=>true, // 字型隨機位置,false正常
008 'bgColor'=>'#ffffff', // 背景
009 'textColor'=>'', // 文本
010 'borColor'=>'#e1e1e1', // 邊框
011 'lineColor'=>'#dedede', // 線條
012 'pixelColor'=>'#646464' // 像素
013 );
014
015 /**
016 * 構造<SPAN class=t_tag onclick=tagshow(event) href="tag.php?name=%BA%AF%CA%FD">函數</SPAN>
017 */
018 public function __construct(){}
019
020 /**
021 * setCookie
022 *
023 * @param string $data 寫入<SPAN class=t_tag onclick=tagshow(event) href="tag.php?name=%CA%FD%BE%DD">資料</SPAN>
024 */
025 public function setCookie($data)
026 {
027 if (is_array($data)) {
028 $string = '';
029 foreach ($data as $v) $string .= $v;
030 $data = $string;
031 }
032 setcookie('captcha',$data,time()+60,'/');
033 }
034 /**
035 * setCaptcha
036 *
037 * 設定輸出<SPAN class=t_tag onclick=tagshow(event) href="tag.php?name=%D1%E9%D6%A4">驗證</SPAN>碼
038 *
039 * @param integer $width 寬
040 * @param integer $height 高
041 * @param integer $fontSize 字型大小
042 * @param string $font 字型<SPAN class=t_tag onclick=tagshow(event) href="tag.php?name=%CE%C4%BC%FE">檔案</SPAN>位置
043 * @param integer $length 驗證<SPAN class=t_tag onclick=tagshow(event) href="tag.php?name=%D7%D6%B7%FB">字元</SPAN>長度
044 * @param integer $type 驗證字元類型
045 * 1:只數字,2:只小寫字母,3:只大寫字母,
046 * 4:小寫字母數字混合,5:大寫字母數字混合,6:大小寫字母數字混合,7:漢字
047 * @param array $about 驗證碼配置
048 */
049 public function setCaptcha($width=80,$height=30,$fontSize=13,$font='code.ttf',$length=4,$type=3,$about=array())
050 {
051 is_array($about) || exit('參數出錯!');
052 foreach ($about as $key=>$value) {
053 if (array_key_exists($key,$this->_about)) {
054 $this->_about[$key] = $value;
055 }
056 }
057
058 extract($this->_about,EXTR_OVERWRITE);
059 $im = imagecreatetruecolor($width,$height);
060 // 背景顏色
061 $bgC_Arr = $this->getColor($bgColor);
062 $imgBgColor = imagecolorallocate($im,$bgC_Arr[0],$bgC_Arr[1],$bgC_Arr[2]);
063 // 邊框顏色
064 $borC_Arr = $this->getColor($borColor);
065 $imgBorderColor = imagecolorallocate($im,$borC_Arr[0],$borC_Arr[1],$borC_Arr[2]);
066 // 填充
067 imagefill($im,0,0,$imgBgColor);
068 imagerectangle($im,0,0,$width-1,$height-1,$imgBorderColor);
069
070 // 畫線
071 if ($imageLine) {
072 // 線條顏色
073 $lineC_Arr = $this->getColor($lineColor);
074 $imgLineColor = imagecolorallocate($im,$lineC_Arr[0],$lineC_Arr[1],$lineC_Arr[2]);
075 for ($i=0;$i<$imageLine;$i++) {
076 imageline($im,0,mt_rand(0,$height),$width,mt_rand(0,$height),$imgLineColor);
077 }
078 }
079 // 像素幹擾
080 if ($imagePixel) {
081 // 像素顏色
082 $pixelC_Arr = $this->getColor($pixelColor);
083 $imgPixelColor = imagecolorallocate($im,$pixelC_Arr[0],$pixelC_Arr[1],$pixelC_Arr[2]);
084 for ($i=0;$i<$imagePixel;$i++) {
085 imagesetpixel($im,mt_rand(2,$width-2),mt_rand(2,$height-2),$imgPixelColor);
086 }
087 }
088
089 // 擷取字串
090 if (!$text = $this->getText($type,$length)) exit('驗證碼沒有尋找到指定字元類型!');
091 // 檢查字型檔
092 is_file($font) || exit('驗證碼未尋找到指定字型檔!');
093 $y = ceil($height / 2)+ceil($fontSize/2)*0.9;
094 $pitch = ceil($width / $length);
095 $text = ctype_alnum($text)?$text:str_split($text,3);
096 $pad = 0;
097 for ($i=0;$i<$length;$i++) {
098 if (!empty($textColor)) {
099 // 文本顏色
100 $txtC_Arr = $this->getColor($textColor);
101 $imgTextColor = imagecolorallocate($im,$txtC_Arr[0],$txtC_Arr[1],$txtC_Arr[2]);
102 } else {
103 $imgTextColor = imagecolorallocate($im,mt_rand(0,255),mt_rand(0,255),mt_rand(0,255));
104 }
105 if (false === $location) {
106 $fontSizePad = ctype_alnum($text[$i]) ? $fontSize*1.4 : $fontSize*1.7;
107 $x = $pad + $fontSize + (ceil($pitch/2) - $fontSizePad);
108 imagettftext($im,$fontSize,0,$x,$y,$imgTextColor,$font,$text[$i]);
109 $pad += $pitch;
110 } else {
111 $d = $pad += $pitch;
112 $d += $fontSize*0.5;
113 imagettftext($im,$fontSize,mt_rand(-20,20),mt_rand($d-=$pitch,$pad-$fontSize*1.4),$y,$imgTextColor,$font,$text[$i]);
114 }
115 }
116 // 寫入<SPAN class=t_tag onclick=tagshow(event) href="tag.php?name=session">session</SPAN>
117 $this->setCookie($text);
118 $this->getCaptcha($im);
119 }
120
121 /**
122 * getText
123 *
124 * 擷取字串
125 *
126 * @param integer $type 字串類型
127 * @param integer $length 長度
128 * @return string $result 字串結果
129 */
130 public function getText($type,$length)
131 {
132 $result = '';
133 $range = array();
134 switch ($type) {
135 case 1 :
136 for ($i=0;$i<$length;$i++) $result .= mt_rand(0,9);
137 break;
138 case 2 :
139 $range = range('a','z');
140 break;
141 case 3 :
142 $range = range('A','Z');
143 break;
144 case 4 :
145 $range = array_merge(range(0,9),range('a','z'));
146 break;
147 case 5 :
148 $range = array_merge(range(0,9),range('A','Z'));
149 break;
150 case 6 :
151 $range = array_merge(range(0,9),range('a','z'),range('A','Z'));
152 break;
153 case 7 :
154 // for ($i=0;$i<$length;$i++) $result .= iconv('gb2312','utf-8',chr(rand(0xB0,0xF7)).chr(rand(0xA1,0xFE)));
155 $range = array(
156 '佟','愛','菲','可','天','一','新','他','策','韻','年','明','禮','傑','雅','詩','忍','子',
157 '好','快','樂','半','美','拜','亮','臣','香','中','國','開','心','阿','笑','圖','成','虎'
158 );
159 break;
160 default : return false;
161 }
162 if (!empty($range)) {
163 shuffle($range);
164 $result = mb_substr(implode('',$range),0,$length,'utf-8');
165 }
166 return $result;
167 }
168
169 /**
170 * getColor
171 *
172 * 十六進位顏色轉為十進位
173 */
174 public function getColor($string)
175 {
176 $string = str_replace('#','',$string);
177 if (!ctype_alnum($string)) {
178 return false;
179 }
180 $rgb_Arr = array();
181 if (strlen($string) == 3) {
182 for ($i=0;$i<3;$i++) {
183 $rgb_Arr[$i] = hexdec(str_repeat($string{$i},'2'));
184 }
185 } else if (strlen($string) == 6) {
186 $colorSp = str_split($string,2);
187 foreach ($colorSp as $v) {
188 $rgb_Arr[] = hexdec($v);
189 }
190 } else {
191 return false;
192 }
193 return $rgb_Arr;
194 }
195
196 public function getCaptcha($im)
197 {
198 header('Content-type: image/gif');
199 imagegif($im);
200 imagedestroy($im);
201 }
202 }
203
204 $about = array(
205 'imageLine'=>0, // 線條幹擾,為0正常
206 'imagePixel'=>300, // 像素幹擾,為0正常
207 'location'=>false, // 字型隨機位置,false正常
208 'bgColor'=>'#ffffff', // 背景顏色
209 'textColor'=>'', // 文本顏色,預設隨機顏色
210 'borColor'=>'#e1e1e1', // 邊框顏色
211 'lineColor'=>'#ff0000', // 線條顏色
212 'pixelColor'=>'#a13e3e' // 像素顏色
213 );
214 error_reporting(0);
215 $a = new Captcha();
216 $a->setCaptcha(100,30,13,'font.ttf',4,1,$about);