Pull to refresh

Матановая капча на PHP — это просто!

Reading time2 min
Views25K

В этом топике я хочу вам рассказать о создании т.н. "матан-капчи" с использованием только 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);

Вместо заключения


Ещё несколько капч, сгенерированных этим скриптом:



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

Articles

Change theme settings