
В этом топике я хочу вам рассказать о создании т.н. "матан-капчи" с использованием только PHP и GD. Для отрисовки формул будем использовать PhpMathPublisher — свободно распространяемую библиотеку, использующую только расширение GD.
Немного теории
В качестве задания мы будем использовать не предел, как на Луркморе, а простой определенный интеграл от функции-многочлена. При желании его можно посчитать даже в уме. Вот пример решения для картинки из начала статьи:

Собственно, разработка
PhpMathPublisher должен лежать в папке phpmathpublisher.
Инициализируем:
include("phpmathpublisher/mathpublisher.php"); // Подключаем рисовалку формул $upper=rand(0, 10); // Верхний предел интеграла $lower=rand(-10, 0); // Нижний предел интеграла $num=4; // Количество слагаемых в функции
Теперь нужно создать строку с формулой, можно одновременно посчитать ответ:
$text="int{".$lower."}{".$upper."}{"; for($i=0;$i<$num;$i++){ $k=rand(1, 5); // Коэффициент перед x $p=rand(1, 5); // Показатель степени x $sign=rand(0, 2)==0?0:1; // Знак, плюс будет в 2 раза чаще $tt=$k>1?$k:""; // Временная переменная для хранения слагаемого $tt.="x"; if($p>1)$tt.="^".$p; if($i==0){ if($sign==1)$text.="({-}".$tt.")"; else $text.=$tt; }else $text.=($sign==1?"-":"+").$tt; if($sign==1)$k=-$k; $answer+=($k*pow($upper, $p+1)/($p+1))-($k*pow($lower, $p+1)/($p+1)); // И заодно считаем ответ. } $text.="dx}";
В итоге у нас получится строка такого вида:
int{-4}{4}{3x^5-4x^5+3x^2+x^2dx}
Теперь осталось отрисовать всё это на картинке — с помощью PhpMathPublisher это займёт всего несколько строк:
$formula=new expression_math(tableau_expression(trim($text))); $formula->dessine(24); // 24 - размер символов $w=imagesx($formula->image)+20; // Отступы по 10 пикселей с каждой стороны, иначе при применении искажений пределы у интеграла съезжают за край изображения $h=imagesy($formula->image)+20; $fi=imagecreatetruecolor($w, $h); imagefill($fi, 0, 0, 0xFFFFFF); imagecopy($fi, $formula->image, 10, 10, 0, 0, $w-20, $h-20);
Дальше неплохо применить нелинейные искажения — для этого я использовал алгоритм MultiWave. По ссылке полный код и пример использования.
А дальше нам ничего не остается, кроме как вывести полученную картинку в браузер:
header("Content-type: image/png"); imagepng($im);
Вместо заключения
Ещё несколько капч, сгенерированных этим скриптом:



И страничка с примером использования.
Надеюсь, мой сервер не ляжет под хабраэффектом
