# 筆記_工作_圖形驗證碼
---
###### tags: `Captcha` `PHP` `驗證碼`
筆記內成就皆不來自我
---
[Mac缺少freetype解决方案](https://blog.si-yee.com/2019/03/19/Mac%E7%BC%BA%E5%B0%91freetype%E8%A7%A3%E5%86%B3%E6%96%B9%E6%A1%88/)
[php 安装 freetype 支持](https://blog.csdn.net/coolpan123/article/details/79893668)
MacOS上無法直接使用freetype擴展庫
[Tutorial on creating image captcha in PHP using GD library](https://perials.com/tutorial-creating-image-captcha-php-using-gd-library/)
帶你一步步看GD怎麼產生驗證碼的
---
圖形驗證,就是使用PHP語言將文本(腳本)轉成圖片輸出
而基本上很多語言都有相對應的方法
PHP種可以分成大致兩種來做出文本輸出圖像方法
原理是一樣的
只是一個有使用外部文字的字體引擎
一個沒有但都是使用GD庫
目錄
- GD庫
- 什麼是GD庫
- GD庫使用
- Freetype
- 不需Freetype驗證碼
- GD教學
## GD庫
---
## 什麼是GD庫
引用:
PHP 在 Web 开发领域被广泛应用的原因在于,PHP 不仅可以生成 HTML 页面,还可以创建和操作二进制形式的数据,例如图像、文件等等。其中,使用 **PHP 处理图像就需要 GD 库的支持**
本节我们就来介绍一下 GD 库,以及如何启用 GD 库。
1. ***GD库是什么***
GD 库(也可以称为 GD2 函数库)是一个开源的用于创建图形图像的函数库,该函数库由C语言编写,可以在 Perl,PHP 等多种语言中使用。GD 库中提供了一系列用来处理图片的 API(接口),使用 GD 库可以处理图片、生成图片,也可以给图片加水印等。
另外,很多开源项目都对 GD 库提供了很好的技术支持,如 Jpgraph 类库就是基于 GD 库开发的用于制作复杂统计图的类库。
2. ***使用GD库可以做什么***
在 PHP 中使用 GD 库可以在页面中绘制各种图形图像,以及统计图,如果与 Ajax 技术相结合还可以制作出各种强大的动态图表。还有就是在网站登陆页面中使用的验证码,也可以使用 GD 库来实现。
需要注意的是,GD 库开始时是支持 GIF 格式的,但由于 GIF 使用了有版权争议的 LZW 算法,会引起法律问题,于是从 GD 库 1.6 版起所有的 GIF 支持都移除了,但是又在 GD 库 2.0.28 版起又加了回来。如果使用了二者之间版本的 GD 库时,有关 GIF 相关函数是不可用。



[C语言中文网](http://c.biancheng.net/view/7938.html)
---
## GD庫使用
[GD 和图像处理 函数](https://www.php.net/manual/zh/ref.image.php)
---
## Freetype
Freetype在百度上解釋的比較好懂


---
## 不需Freetype驗證碼
[【PHP原生】數字和字母驗證碼](https://www.cnblogs.com/php99/p/9796211.html)
[好讀版](https://www.itdaan.com/tw/bafb988f2174f4688e9e24fa24624429)
使用以下方式,可以在不使用freetype字體引擎下做出驗證碼
但這樣有個缺點
就是字體很小
*設置字體大小中默認值只有1-5*
所以出來圖片即使圖片實體很大
但字大小依然會給使用者帶來不便
要完全控制字體大小
[imagettftext()](https://www.php.net/manual/zh/function.imagettftext.php)
講解使用imagettftext()與imagestring()
[Can't change font size for GD imagestring()](https://stackoverflow.com/questions/10954652/cant-change-font-size-for-gd-imagestring)
大小字體很小

```php=
//設置session,必須處於腳本最頂部
session_start();
$image = imagecreatetruecolor(100, 30);
//1>設置驗證碼圖片大小的函數
//設置驗證碼顏色 imagecolorallocate(int im, int red, int green, int blue);
$bgcolor = imagecolorallocate($image, 255, 255, 255);
//#ffffff
//區域填充 int imagefill(int im, int x, int y, int col) (x,y) 所在的區域着色,col 表示欲塗上的顏色
imagefill($image, 0, 0, $bgcolor);
//設置變量
$captcha_code = "";
//生成隨機的字母和數字
for ($i = 0; $i < 4; $i++) {
//設置字體大小
$fontsize = 8;
//設置字體顏色,隨機顏色
$fontcolor = imagecolorallocate($image, rand(0, 120), rand(0, 120), rand(0, 120));
//0-120深顏色
//設置需要隨機取的值,去掉容易出錯的值如0和o
$data = 'abcdefghigkmnpqrstuvwxy3456789';
//取出值,字符串截取方法 strlen獲取字符串長度
$fontcontent = substr($data, rand(0, strlen($data)), 1);
// .=連續定義變量
$captcha_code .= $fontcontent;
//設置坐標
$x = $i * 100 / 4 + rand(5, 10);
$y = rand(5, 10);
imagestring($image, $fontsize, $x, $y, $fontcontent, $fontcolor);
}
//存到session
$_SESSION['authcode'] = $captcha_code;
//增加干擾元素,設置雪花點
for ($i = 0; $i < 200; $i++) {
//設置點的顏色,50-200顏色比數字淺,不干擾閱讀
$pointcolor = imagecolorallocate($image, rand(50, 200), rand(50, 200), rand(50, 200));
//imagesetpixel — 畫一個單一像素
imagesetpixel($image, rand(1, 99), rand(1, 29), $pointcolor);
}
//增加干擾元素,設置橫線
for ($i = 0; $i < 4; $i++) {
//設置線的顏色
$linecolor = imagecolorallocate($image, rand(80, 220), rand(80, 220), rand(80, 220));
//設置線,兩點一線
imageline($image, rand(1, 99), rand(1, 29), rand(1, 99), rand(1, 29), $linecolor);
}
//設置頭部,image/png
header('Content-Type: image/png');
//imagepng() 建立png圖形函數
imagepng($image);
//imagedestroy() 結束圖形函數 銷毀$image
imagedestroy($image);
```
方法二
大小字體很大~

```php=
$ImageText1Small = imagecreate( 148, 16 );
$ImageText1Large = imagecreate( 148, 16 );
$ImageText2Small = imagecreate( 308, 40 );
$ImageText2Large = imagecreate( 308, 40 );
$ImageFinal = imagecreate( 500, 100 );
$backgroundColor1 = imagecolorallocate($ImageText1Small, 255,255,255);
$textColor1 = imagecolorallocate($ImageText1Small, 0,0,0);
$backgroundColor2 = imagecolorallocate($ImageText2Small, 255,255,255);
$textColor2 = imagecolorallocate($ImageText2Small, 0,0,0);
imagestring( $ImageText1Small, 1, 1, 0, 'Stack Overflow', $textColor1 );
imagestring( $ImageText2Small, 5, 1, 0, 'Harry Harry Harry', $textColor2 );
imagecopyresampled($ImageText1Large, $ImageText1Small, 0, 0, 0, 0, 148, 16, 74, 8);
imagecopyresampled($ImageText2Large, $ImageText2Small, 0, 0, 0, 0, 308, 40, 154, 20);
$ImageText1Large = imagerotate ( $ImageText1Large, 20, $backgroundColor1 );
$ImageText2Large = imagerotate ( $ImageText2Large, -5, $backgroundColor2 );
$ImageText1W = imagesx($ImageText1Large);
$ImageText1H = imagesy($ImageText1Large);
$ImageText2W = imagesx($ImageText2Large);
$ImageText2H = imagesy($ImageText2Large);
imagecopymerge($ImageFinal, $ImageText1Large, 350, 20, 0, 0, $ImageText1W, $ImageText1H, 100);
imagecopymerge($ImageFinal, $ImageText2Large, 20, 20, 0, 0, $ImageText2W, $ImageText2H, 100);
// header( "Content-type: image/png" );
header('Content-Type: image/png');
imagepng($ImageFinal);
imagecolordeallocate( $ImageText1, $textColor1 );
imagecolordeallocate( $ImageText2, $textColor2 );
imagedestroy($ImageText1);
imagedestroy($ImageText2);
```
---
---
## GD教學
原文 [Render Text and Shapes on Images in PHP](https://code.tutsplus.com/tutorials/rendering-text-and-basic-shapes-using-gd--cms-31767)
翻譯 [在PHP中渲染图像上的文本和形状](https://blog.csdn.net/cunjie3951/article/details/106905597)