Повороот PNG картинки на задангый угол

Ниже приведен код с подробными комментариями:

/*
* Поворот PNG картинки на заданный угол
*
* @var string $img - картинка
* @var string $degree - угол поворота
* @var string $path - путь для сохранения картинки
*
* @return string $path - путь к новой картинке
*/
function rotatePhotoPNG($img, $degree, $path){
    // загружаем картинку
    $simage = imagecreatefrompng($img); 
    // задаем ей прозрачность
    imagealphablending($simage, true); 
    imagesavealpha($simage, true); 
    // создаем прозрачный фон
    $bg = imagecolorallocatealpha($simage, 0, 0, 0, 127); 
    // поворот на нужный угол
    $rotate = imagerotate($simage, $degree, $bg); 
    // задаем прозрачность для повернутой картинки
    imagealphablending($rotate, true); 
    imagesavealpha($rotate, true);      
    // сохраняем результат
    imagepng($rotate, $path);
    // очищаем память
    imagedestroy($rotate);
    // возвращаем путь к новой картинке
    return $path;
}

Добавлено: 02 Мая 2018 20:10:41 Добавил: Андрей Ковальчук

Рисуем плавную кривую в PHP с использованием GD

В данном уроке мы выведем график на PHP с использованием библиотеки GD. Кривая будет сглаживаться с помощью интерполяции кубическими сплайнами.

Шаг 1. Разметка HTML
Разметка для демонстрации достаточно проста.

<!DOCTYPE html>
<html lang="ru" >
    <head>
        <meta charset="utf-8" />
        <title>Плавная кривая на PHP и GD | Материалы сайта RUSELLER.COM</title>
 
        <link href="css/main.css" rel="stylesheet" type="text/css" />
    </head>
    <body>
        <div class="container">
            <img src="smooth_graph.php" alt="" />
        </div>
        <footer>
            <h2>Плавная кривая на PHP и GD</h2>
            <a href="http://www.ruseller.com" target="_blank" class="stuts">Материалы сайта <span>RUSELLER.COM</span></a>
        </footer>
    </body>
</html>

В качестве источника для элемента изображения выступает PHP файл, который генерирует график.

Шаг 2. CSS
Для демонстрации используются обычные правила:

css/main.css
*{
    margin:0;
    padding:0;
}
 
body {
    background-repeat:no-repeat;
    background-color:#bababa;
    background-image: -webkit-radial-gradient(600px 200px, circle, #eee, #bababa 40%);
    background-image: -moz-radial-gradient(600px 200px, circle, #eee, #bababa 40%);
    background-image: -o-radial-gradient(600px 200px, circle, #eee, #bababa 40%);
    background-image: radial-gradient(600px 200px, circle, #eee, #bababa 40%);
    color:#fff;
    font:14px/1.3 Arial,sans-serif;
    min-height:600px;
}
 
footer {
    background-color:#212121;
    bottom:0;
    box-shadow: 0 -1px 2px #111111;
    display:block;
    height:70px;
    left:0;
    position:fixed;
    width:100%;
    z-index:100;
}
 
footer h2{
    font-size:22px;
    font-weight:normal;
    left:50%;
    margin-left:-400px;
    padding:22px 0;
    position:absolute;
    width:540px;
}
 
footer a.stuts,a.stuts:visited{
    border:none;
    text-decoration:none;
    color:#fcfcfc;
    font-size:14px;
    left:50%;
    line-height:31px;
    margin:23px 0 0 110px;
    position:absolute;
    top:0;
}
 
footer .stuts span {
    font-size:22px;
    font-weight:bold;
    margin-left:5px;
}
 
.container {
    border:3px #111 solid;
    margin:20px auto;
    padding:20px;
    position:relative;
    width:550px;
    height:430px;
 
    border-radius:15px;
    -moz-border-radius:15px;
    -webkit-border-radius:15px;
}


Шаг 3. PHP
График генерируется серверной стороной:

smooth_graph.php
<?php
set_time_limit(100);
 
define('GRAPH_WIDTH',  500);
define('GRAPH_HEIGHT', 400);
 
include_once ('classes/Plot.php');
include_once ('classes/CubicSplines.php');
 
$iPoints = 15;
$dx = (GRAPH_WIDTH - 40) / ($iPoints - 1);
$x = 20;
 
for ($i = 0; $i < $iPoints; $i++) {
    $y = rand(20, GRAPH_HEIGHT - 20);
    $aCoords[$x] = $y;
    $x+= $dx;
}
 
$vImagegHeight = GRAPH_HEIGHT + 30;
$vImage = imagecreatetruecolor(GRAPH_WIDTH + 50, $vImagegHeight);
 
$vBgColor = imagecolorallocate($vImage, 160, 160, 160);
$vTextColor = imagecolorallocate($vImage, 0, 0, 0);
$vAxisColor = imagecolorallocate($vImage, 0, 0, 0);
$vDotColor  = imagecolorallocate($vImage, 192, 64, 64);
 
imagefill($vImage, 0, 0, $vBgColor);
 
$oPlot = new Plot($aCoords);
$oPlot->drawDots($vImage, $vDotColor, 10, GRAPH_HEIGHT, 8);
 
$oCurve = new CubicSplines();
$vColor = imagecolorallocate($vImage, 225, 64, 64);
 
$iStart = microtime(1);
if ($oCurve) {
    $oCurve->setInitCoords($aCoords, 1);
    $r = $oCurve->processCoords();
    if ($r)
        $curveGraph = new Plot($r);
    else
        continue;
} else {
    $curveGraph = $oPlot;
}
 
$curveGraph->drawLine($vImage, $vColor, 10, GRAPH_HEIGHT);
 
// unset($oCurve);
$sTime = sprintf("%1.4f", microtime(1) - $iStart);
 
imagefilledrectangle($vImage, 0, GRAPH_HEIGHT, GRAPH_WIDTH + 50, $vImagegHeight, $vBgColor);
$oPlot->drawAxis($vImage, $vAxisColor, 10, GRAPH_HEIGHT);
$iPanelY = GRAPH_HEIGHT;
 
imagefilledrectangle($vImage, 10, $iPanelY + 10, 20, $iPanelY + 20, $vColor);
imagerectangle($vImage, 10, $iPanelY + 10, 20, $iPanelY + 20, $vAxisColor);
imagettftext($vImage, 10, 0, 30, $iPanelY + 20, $vTextColor, 'Ds-digib.ttf', 'Кубические сплайны в PHP:         ' . $sTime . ' sec');
 
header("Content-type: image/png");
imagepng($vImage);
imagedestroy($vImage);
 
?>

Формируется массив $aCoords точек, который заполняется случайным образом. Затем данный массив используется для построения плавной кривой, которая проходит через все его точки.

В файле используются 2 класса, которые оформлены в отдельных файлах.

Класс для вывода элементов графики (линий, точек и осей):

classes/Plot.php
<?php
 
class Plot {
    private $aCoords;
 
    function __construct(&$aCoords) {
        $this->aCoords = &$aCoords;
    }
 
    public function drawLine($vImage, $vColor, $iPosX = 0, $iPosY = false) {
        if ($iPosY === false)
            $iPosY = imagesy($vImage);
 
        reset($this->aCoords);
        list($iPrevX, $iPrevY) = each($this->aCoords);
 
        while (list ($x, $y) = each($this->aCoords)) {
            imageline($vImage, $iPosX + round($iPrevX), $iPosY - round($iPrevY), $iPosX + round($x), $iPosY - round($y), $vColor);
            $iPrevX = $x;
            $iPrevY = $y;
        }
    }
 
    public function drawDots($vImage, $vColor, $iPosX = 0, $iPosY = false, $iDotSize = 1) {
        if ($iPosY === false)
            $iPosY = imagesy($vImage);
 
        $vBorderColor = imagecolorallocate($vImage, 0, 0, 0);
        foreach ($this->aCoords as $x => $y) {
            imagefilledellipse($vImage, $iPosX + round($x), $iPosY - round($y), $iDotSize, $iDotSize, $vColor);
            imageellipse($vImage, $iPosX + round($x), $iPosY - round($y), $iDotSize, $iDotSize, $vBorderColor);
        }
    }
 
    public function drawAxis($vImage, $vColor, $iPosX = 0, $iPosY = false) {
        if ($iPosY === false)
            $iPosY = imagesy($vImage);
 
        $vImageWidth = imagesx($vImage);
        imageline($vImage, $iPosX, $iPosY, $iPosX, 0, $vColor);
        imageline($vImage, $iPosX, $iPosY, $vImageWidth, $iPosY, $vColor);
 
        imagefilledpolygon($vImage, array($iPosX, 0, $iPosX - 3, 5, $iPosX + 3, 5), 3, $vColor);
        imagefilledpolygon($vImage, array($vImageWidth, $iPosY, $vImageWidth - 5, $iPosY - 3, $vImageWidth - 5, $iPosY + 3), 3, $vColor);
    }
}
 
?>

И класс для формирования плавной кривой с помощью кубических сплайнов:

classes/CubicSplines.php
<?php
 
class CubicSplines {
    protected $aCoords;
    protected $aCrdX;
    protected $aCrdY;
    protected $aSplines = array();
    protected $iMinX;
    protected $iMaxX;
    protected $iStep;
 
    protected function prepareCoords(&$aCoords, $iStep, $iMinX = -1, $iMaxX = -1) {
        $this->aCrdX = array();
        $this->aCrdY = array();
        $this->aCoords = array();
 
        ksort($aCoords);
        foreach ($aCoords as $x => $y) {
            $this->aCrdX[] = $x;
            $this->aCrdY[] = $y;
        }
 
        $this->iMinX = $iMinX;
        $this->iMaxX = $iMaxX;
 
        if ($this->iMinX == -1)
            $this->iMinX = min($this->aCrdX);
        if ($this->iMaxX == -1)
            $this->iMaxX = max($this->aCrdX);
 
        $this->iStep = $iStep;
    }
 
    public function setInitCoords(&$aCoords, $iStep = 1, $iMinX = -1, $iMaxX = -1) {
        $this->aSplines = array();
 
        if (count($aCoords) < 4) {
            return false;
        }
 
        $this->prepareCoords($aCoords, $iStep, $iMinX, $iMaxX);
        $this->buildSpline($this->aCrdX, $this->aCrdY, count($this->aCrdX));
    }
 
    public function processCoords() {
        for ($x = $this->iMinX; $x <= $this->iMaxX; $x += $this->iStep) {
            $this->aCoords[$x] = $this->funcInterp($x);
        }
 
        return $this->aCoords;
    }
 
    private function buildSpline($x, $y, $n) {
        for ($i = 0; $i < $n; ++$i) {
            $this->aSplines[$i]['x'] = $x[$i];
            $this->aSplines[$i]['a'] = $y[$i];
        }
 
        $this->aSplines[0]['c'] = $this->aSplines[$n - 1]['c'] = 0;
        $alpha[0] = $beta[0] = 0;
        for ($i = 1; $i < $n - 1; ++$i) {
            $h_i = $x[$i] - $x[$i - 1];
            $h_i1 = $x[$i + 1] - $x[$i];
            $A = $h_i;
            $C = 2.0 * ($h_i + $h_i1);
            $B = $h_i1;
            $F = 6.0 * (($y[$i + 1] - $y[$i]) / $h_i1 - ($y[$i] - $y[$i - 1]) / $h_i);
            $z = ($A * $alpha[$i - 1] + $C);
            $alpha[$i] = - $B / $z;
            $beta[$i] = ($F - $A * $beta[$i - 1]) / $z;
        }
 
        for ($i = $n - 2; $i > 0; --$i) {
            $this->aSplines[$i]['c'] = $alpha[$i] * $this->aSplines[$i + 1]['c'] + $beta[$i];
        }
 
        for ($i = $n - 1; $i > 0; --$i) {
            $h_i = $x[$i] - $x[$i - 1];
            $this->aSplines[$i]['d'] = ($this->aSplines[$i]['c'] - $this->aSplines[$i - 1]['c']) / $h_i;
            $this->aSplines[$i]['b'] = $h_i * (2.0 * $this->aSplines[$i]['c'] + $this->aSplines[$i - 1]['c']) / 6.0 + ($y[$i] - $y[$i - 1]) / $h_i;
        }
    }
 
    private function funcInterp($x) {
        $n = count($this->aSplines);
        if ($x <= $this->aSplines[0]['x'])  {
            $s = $this->aSplines[1];
        } else {
            if ($x >= $this->aSplines[$n - 1]['x']) {
                $s = $this->aSplines[$n - 1];
            } else {
                $i = 0;
                $j = $n - 1;
                while ($i + 1 < $j) {
                    $k = $i + ($j - $i) / 2;
                    if ($x <= $this->aSplines[$k]['x']) {
                        $j = $k;
                    } else {
                        $i = $k;
                    }
                }
 
                $s = $this->aSplines[$j];
            }
        }
 
        $dx = ($x - $s['x']);
        return $s['a'] + ($s['b'] + ($s['c'] / 2.0 + $s['d'] * $dx / 6.0) * $dx) * $dx;
    }
}
 
?>

Добавлено: 02 Мая 2018 18:52:41 Добавил: Андрей Ковальчук

Загрузка изображений с изменением размера

Немного теории
Вы не можете сразу загрузить файл в свою папку. Вначале он загружается во временную директорию сервера, а затем обрабатывается с помощью PHP интерпритатора. По окончанию сессии временный файл автоматически удаляется. То есть, мы вначале забрасываем файл во временную папку, а затем перекладываем в нужную.


$_FILES это массив загруженных файлов. Он имеет параметры (на примере файла picture):

$_FILES[' picture ']['name'] – настоящее имя файла. Например: image.jpg.

$_FILES[' picture ']['size'] – размер файла в байтах.

$_FILES[' picture ']['type'] – MIME-тип загруженного файла. Например: image/gif, image/png, image/jpeg.

$_FILES[' picture ']['tmp_name'] – содержит имя файла во временном каталоге, например: /tmp/phpV3b3qY. Именно этот параметр и используется для перемещения файлов после загрузки.

$_FILES[' picture ']['error'] – код ошибки.

Подготовка
Для начала нам нужна форма для загрузки. Возьмём простейшую форму.

<form enctype="multipart/form-data" method="post">
<input name="picture" type="file" />
<input type="submit" value="Загрузить" />
</form>

Параметр enctype="multipart/form-data" обязателен для такой формы. Тег <input type="file" name="picture"> отвечает за поле для ввода имени файла, который загружается на сервер.

Также нам потребуется обработчик события – загрузки файла. Вначале у нас будет одна настройка – путь сохранения изображения. Можно указывать как прямой, так и относительный путь. В случае POST запроса обработчик попробует осуществить загрузку файла по указанному пути. Скрипт сообщит о результате загрузки – удачна она или нет.
<?php
 
$path = 'i/';
 
if ($_SERVER['REQUEST_METHOD'] == 'POST')
{
if (!@copy($_FILES['picture']['tmp_name'], $path . $_FILES['picture']['name']))
echo 'Что-то пошло не так';
else
echo 'Загрузка удачна';
}
 
?>

Функция copy, как вы наверно догадались, отвечает за копирование файла из одного место в другое. Мы копируем файл из временной папки сервера в нужную, сохранив имя файла.

Договоримся, что и форма и её обработчик будут находиться в одном файле – upload.php.

Итого имеем простой, но рабочий скрипт. Его можно забросить на хостинг, создать папку i и потренироваться с загрузкой файлов.
<?php
 
// Путь загрузки
$path = 'i/';
 
// Обработка запроса
if ($_SERVER['REQUEST_METHOD'] == 'POST')
{
// Загрузка файла и вывод сообщения
if (!@copy($_FILES['picture']['tmp_name'], $path . $_FILES['picture']['name']))
echo 'Что-то пошло не так';
else
echo 'Загрузка удачна';
}
 
?>

<!DOCTYPE HTML PUBLIC  "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<title>Загрузка изображения с изменением размеров</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
</head>
<body>
<h1>Загрузка изображения с изменением размеров</h1>
<form method="post" enctype="multipart/form-data">
<input type="file" name="picture">
<input type="submit" value="Загрузить">
</form>
</body>
</html>


Проверки
Любая форма представляет для сайта опасность. И особенно форма загрузки файлов. Злоумышленник может загрузить скрипт и выполнить его на сервере. Поэтому необходимо озаботиться безопасностью.

Самые простые и обязательные проверки – на размер и тип файла. Для этого укажем допустимые типы и размер.

Тип файла укажем в виде массива:
$types = array('image/gif', 'image/png', 'image/jpeg');

а размер файла в байтах:
$size = 1024000;
Проверяем тип файла. В случае недопустимого типа прекращаем работу скрипта и выводим соответствующее уведомление. Функция in_array проверяет присутствие значения в массиве.
// Проверяем тип файла
if (!in_array($_FILES['picture']['type'], $types))
die('Запрещённый тип файла. <a href="?">Попробовать другой файл?</a>');

Проверяем размер файла. В случае недопустимого размера прекращаем работу скрипта и выводим соответствующее уведомление.
// Проверяем размер файла
if ($_FILES['picture']['size'] > $size)
die('Слишком большой размер файла. <a href="?">Попробовать другой файл?</a>');


Итого получаем такой скрипт. Скрипт рабочий, можно баловаться. Немного забегая вперёд, добавим также параметр $tmp_path – путь к папке временных файлов.
<?php
 
// Пути загрузки файлов
$path = 'i/';
$tmp_path = 'tmp/';
// Массив допустимых значений типа файла
$types = array('image/gif', 'image/png', 'image/jpeg');
// Максимальный размер файла
$size = 1024000;
 
// Обработка запроса
if ($_SERVER['REQUEST_METHOD'] == 'POST')
{
// Проверяем тип файла
if (!in_array($_FILES['picture']['type'], $types))
die('Запрещённый тип файла. <a href="?">Попробовать другой файл?</a>');
 
// Проверяем размер файла
if ($_FILES['picture']['size'] > $size)
die('Слишком большой размер файла. <a href="?">Попробовать другой файл?</a>');
 
// Загрузка файла и вывод сообщения
if (!@copy($_FILES['picture']['tmp_name'], $path . $_FILES['picture']['name']))
echo 'Что-то пошло не так';
else
echo 'Загрузка удачна <a href="$path . $_FILES['picture']['name'] . '">Посмотреть</a> ' ;
}
 
?>

<!DOCTYPE HTML PUBLIC  "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<title>Загрузка изображения с изменением размеров</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
</head>
<body>
<h1>Загрузка изображения с изменением размеров</h1>
<form method="post" enctype="multipart/form-data">
<input type="file" name="picture">
<input type="submit" value="Загрузить">
</form>
</body>
</html>

Изменение размеров
Приступим к самому интересному. К изменению параметров изображения. Для этого напишем функцию resize. Сделаем также возможным изменять качество изображения и поворачивать его.

Размер изображения будем подставлять исходя из параметра. Это будет либо эскиз ($type = 1), либо большое изображение ($type = 2).

Итак, шапка функции у нас получилась такая:
function resize($file, $type = 1, $rotate = null, $quality = null)

По умолчанию подставляем размеры эскиза, а поворот и качество по умолчанию не используются. Пойдём дальше.

Устанавливаем ограничение размера изображения по ширине. Функцию можно сделать более абстрактной, если задавать эти значения в параметрах, а также сделать возможным ограничение и по высоте. Однако в данном случае нам не нужна такая универсальность.
$max_thumb_size = 200;
$max_size = 800;

Устанавливаем качество изображения по умолчанию (при $quality = null) равным 75%.
if ($quality == null)
$quality = 75;

Далее создаём изображение для дальнейших преобразований. Для создания используем функцию в зависимости от типа файла (jpg, png или gif). Функции создания называются очень лаконично imagecreatefrom + тип файла.
if ($file['type'] == 'image/jpeg')
$source = imagecreatefromjpeg ($file['tmp_name']);
elseif ($file['type'] == 'image/png')
$source = imagecreatefrompng ($file['tmp_name']);
elseif ($file['type'] == 'image/gif')
$source = imagecreatefromgif ($file['tmp_name']);
else
return false;

Если указан параметр $rotate, выполняем поворот изображения. Делаем это с помощью функции rotate(), параметрами которой являются: изображение, градусы, фон изображения для закрашивания пустых областей, образованных при повороте. Для того чтобы пустые области не возникали, поворачиваем изображение на угол в 90, 180, 270 градусов.
if ($rotate != null)
$src = imagerotate($source, $rotate, 0);

Далее определяем высоту и ширину изображения с помощью функций imagesx и imagesy.
$w_src = imagesx($src);
$h_src = imagesy($src);

В зависимости от типа (эскиз или большое изображение) устанавливаем ограничение по ширине.
if ($type == 1)
$w = $max_thumb_size;
elseif ($type == 2)
$w = $max_size;

Далее, если ширина изображения больше максимальной, проводим преобразования. Иначе просто сохраняем изображение и очищаем память. Сохраняем изображение с помощью функции imagejpeg. В данном примере, рассмотрено сохранение только в формате jpg, однако функционал всегда можно расширить. Удаляем изображения из памяти с помощью функции imagedestroy.

В качестве результата работы функции возвращаем имя файла. Оно нам ещё понадобится.
if ($w_src > $w)
{
// преобразования
}
else
{
imagejpeg($src, $tmp_path . $file['name'], $quality);
imagedestroy($src);
 
return $file['name'];
}

Вернёмся к преобразованию. Вначале вычисляем пропорции изображения и размеры преобразованного изображения.
$ratio = $w_src/$w;
$w_dest = round($w_src/$ratio);
$h_dest = round($h_src/$ratio);

Далее создаём пустую картинку (функция imagecreatetruecolor) с шириной и высотой, полученными на прошлом шаге.
$dest = imagecreatetruecolor($w_dest, $h_dest);

И копируем исходное изображение ($src) в только что созданное ($dest), изменяя его размеры. Функция imagecopyresampled делает это с пересэмплированием, что улучшает качество.
imagecopyresampled($dest, $src, 0, 0, 0, 0, $w_dest, $h_dest, $w_src, $h_src);

И наконец, сохраняем полученное изображение и очищаем память.
imagejpeg($src, $tmp_path . $file['name'], $quality);
imagedestroy($dest);
imagedestroy($src);

Итого, функция получает исходное изображение и параметры преобразования, выполняет преобразования, сохраняет полученный файл во временную папку и возвращает имя изображения. Теперь нам осталось только переложить файл в конечную папку.

Отвечу заранее на вопрос «Почему мы не можем сразу положить изменённый файл в конечную папку?». Можем. Однако не делаем для увеличения глубины абстракции, то есть, чтобы придать определённую универсальность функции. Вы же сможете её использовать на разных сайтах.

Совсем забыл. Добавляем в начало функции строку:
global $tmp_path;

Она обозначает, что в функции будет использована глобальная переменная $tmp_path – путь к временной папке.

Вызов функции
Функцию нужно вызывать сразу после проверок. А также следует изменить ту часть скрипта, где мы копируем изображение в конечную папку. Вы ведь теперь работаем с новым изображением. Теперь схема загрузки такова: компьютер → временная папка сервера → наша временная папка → конечная папка. То есть, добавился ещё один промежуточный пункт.

Для пущего веселья добавим в нашу форму выпадающий список, чтобы мы устанавливать тип загрузки и поля для ввода градуса поворота.

В таком случае вызов функции будет такой:
$name = resize($_FILES['picture'], $_POST['file_type'], $_POST['file_rotate']);

Конечный результат
И наконец, конечный результат.
<!DOCTYPE HTML PUBLIC  "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<title>Загрузка изображения с изменением размеров</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
</head>
<body>
<h1>Загрузка изображения с изменением размеров</h1>
<?php
 
// Пути загрузки файлов
$path = 'i/';
$tmp_path = 'tmp/';
// Массив допустимых значений типа файла
$types = array('image/gif', 'image/png', 'image/jpeg');
// Максимальный размер файла
$size = 1024000;
 
// Обработка запроса
if ($_SERVER['REQUEST_METHOD'] == 'POST')
{
// Проверяем тип файла
if (!in_array($_FILES['picture']['type'], $types))
die('<p>Запрещённый тип файла. <a href="?">Попробовать другой файл?</a></p>');
 
// Проверяем размер файла
if ($_FILES['picture']['size'] > $size)
die('<p>Слишком большой размер файла. <a href="?">Попробовать другой файл?</a></p>');
 
// Функция изменения размера
// Изменяет размер изображения в зависимости от type:
//  type = 1 - эскиз
//  type = 2 - большое изображение
//  rotate - поворот на количество градусов (желательно использовать значение 90, 180, 270)
//  quality - качество изображения (по умолчанию 75%)
function resize($file, $type = 1, $rotate = null, $quality = null)
{
global $tmp_path;
 
// Ограничение по ширине в пикселях
$max_thumb_size = 200;
$max_size = 600;
 
// Качество изображения по умолчанию
if ($quality == null)
$quality = 75;
 
// Cоздаём исходное изображение на основе исходного файла
if ($file['type'] == 'image/jpeg')
$source = imagecreatefromjpeg($file['tmp_name']);
elseif ($file['type'] == 'image/png')
$source = imagecreatefrompng($file['tmp_name']);
elseif ($file['type'] == 'image/gif')
$source = imagecreatefromgif($file['tmp_name']);
else
return false;
 
// Поворачиваем изображение
if ($rotate != null)
$src = imagerotate($source, $rotate, 0);
else
$src = $source;
 
// Определяем ширину и высоту изображения
$w_src = imagesx($src);
$h_src = imagesy($src);
 
// В зависимости от типа (эскиз или большое изображение) устанавливаем ограничение по ширине.
if ($type == 1)
$w = $max_thumb_size;
elseif ($type == 2)
$w = $max_size;
 
// Если ширина больше заданной
if ($w_src > $w)
{
// Вычисление пропорций
$ratio = $w_src/$w;
$w_dest = round($w_src/$ratio);
$h_dest = round($h_src/$ratio);
 
// Создаём пустую картинку
$dest = imagecreatetruecolor($w_dest, $h_dest);
 
// Копируем старое изображение в новое с изменением параметров
imagecopyresampled($dest, $src, 0, 0, 0, 0, $w_dest, $h_dest, $w_src, $h_src);
 
// Вывод картинки и очистка памяти
imagejpeg($dest, $tmp_path . $file['name'], $quality);
imagedestroy($dest);
imagedestroy($src);
 
return $file['name'];
}
else
{
// Вывод картинки и очистка памяти
imagejpeg($src, $tmp_path . $file['name'], $quality);
imagedestroy($src);
 
return $file['name'];
}
}
 
$name = resize($_FILES['picture'], $_POST['file_type'], $_POST['file_rotate']);
 
// Загрузка файла и вывод сообщения
if (!@copy($tmp_path . $name, $path . $name))
echo '<p>Что-то пошло не так.</p>';
else
echo '<p>Загрузка прошла удачно <a href="' . $path . $_FILES['picture']['name'] . '">Посмотреть</a>.</p>';
 
// Удаляем временный файл
unlink($tmp_path . $name);
}
 
?>
<form method="post" enctype="multipart/form-data">
<input type="file" name="picture">
<br>
<label>Тип загрузки</label>
<br>
<select name="file_type">
<option value="1">Эскиз</option>
<option value="2">Большое изображение</option>
</select>
<br>
<label>Поворот</label>
<br>
<input type="text" name="file_rotate">
<br>
<input type="submit" value="Загрузить">
</form>
</body>
</html>

Добавлено: 01 Мая 2018 18:21:09 Добавил: Андрей Ковальчук

Уменьшаем размер картинок

У меня на компьютере сохранено 1000 картинок большого размера. Можно сделать программу, которая автоматически уменьшит их размер, не хочется мучиться в Фотошопе, их учменьшая?

Это практическая задача, библиотека GD предоставляет возможность сделать такой скрипт. Итак, есть папка prikol, в ней лежат картинки в формате .jpeg (скрипт сделан для работы только с этим форматом), мы автоматически уменьшим размер картинок и сохраним их в той же папке.

<?php
    // имя папки, где лежат картинки
$papka = "prikol";

    // время выполнения сценария не ограничено
    // если не сделать так, то при большом количестве
    // картинок время одного процесса истечёт, что
    // нам не надо, поэтому ставим set_time_limit (0);
set_time_limit (0);

    // качество сохраняемой картинки в процентах от 
    // оригинала можете ставить от 0 до 100, это проценты. 
    // чем больше это число, тем с большим качеством 
    // сохранится новая картинка
$qulity = 70;

    // максимальный размер стороны нового фото в пикселях
    // все картинки приведёт к этому размеру, то есть 
    // сони все танут одинаковыми 
$size_max = 600;

    // подключает модуль GD динамически, если она не подключена
    // если выдаст Нет файла библиотеки, то нет у вас модуля GD
$bibl_ext = dirname ($_SERVER['SCRIPT_FILENAME']).'/extensions/php_gd.dll';
if ( !extension_loaded ('gd') and is_file ($bibl_ext)){ dl ("extensions/php_gd.dll"); }
if ( !extension_loaded ('gd')) { print "Нет файла библиотеки $bibl_ext"; exit ;}

    // вспомогательная функция, определяет тип файла
function TypeFile ($img_name){
$arr = GetImageSize ($img_name);
return $arr[2]; 
}

    // вспомогательная функция, выводим в программу из 
    // фотографии графический объект
function LoadImage ($img_name){
if (TypeFile($img_name)==2) { 
$im = ImageCreateFromJpeg($img_name); 
return $im; 
}
return false; 
}

    // основная функция, которая уменьшит все фото в папке $path
function open_dir_and_small ( $path ) { 
global $qulity, $size_max;
$dh = opendir ($path);
while ($entry = readdir ($dh)){
if ($entry != "." and $entry != ".."){
$file = $path."/".$entry;
$old = LoadImage($file);
if ($old=='false' or preg_match ("~new~",$entry)){ continue; }
$w = ImageSX ($old); 
$h = ImageSY ($old);
if ( preg_match ("/(.+)(\..+)/",$file,$arr)){
$path_new = $arr[1].'_new'.$arr[2];
if ($w > $h){ $w_new = $size_max; $h_new = ceil ($w_new * $h/$w); }
else { $h_new = $size_max; $w_new = ceil ($h_new * $w/$h); } 
$new = imageCreate ($w_new, $h_new);
ImageCopyResized($new, $old, 0, 0, 0, 0, $w_new, $h_new, $w, $h);
imageJpeg ($new, $path_new, $qulity); 
imageDestroy ($new); 
print $path_new."<br>\n";
}
imageDestroy ($old); 
clearstatcache ();
}
} 
closedir ($dh);
}

    // применим функции и уменьшим все картинки в папке "prikol"
open_dir_and_small ( $papka );
?>

После применения этого скрипта в папке prikol появятся новые уменьшенные картинки с теми же названиями, что и старые. В середине имён файлов будет стоять слово _new. Это и есть новые картинки, размер их Вы сами можете менять и сами можете менять их качество. Имена новых картинок будут выведены в окно броузера, это означает, что программа работает.

Добавлено: 29 Апреля 2018 12:42:05 Добавил: Андрей Ковальчук

Изменение размеров изображения на лету

Вот модификация того скрипта (по ссылке, приведенной Саней) для масштабирования на лету.
Файл img.php содержит код, масштабирующий изображение.
img.php

<?  
   // Здесь можно и нужно добавить код, проверяющий  
   // содержимое переменной $_GET["file"]  
   // Вдруг вам хакер или просто любопытствующий туда  
   // что-нибудь не то передаст  
  $filename = $_GET["file"];  
  // Вызываем функцию масштабирования  
  resizeimg($filename, 100,100);  

  // Функция масштабирования  
  function resizeimg($filename, $w, $h)  
  {  
    // определим коэффициент сжатия изображения, которое будем генерить  
    $ratio = $w/$h;  
    // получим размеры исходного изображения  
    $size_img = getimagesize($filename);  
    // Если размеры меньше, то масштабирования не нужно  
    if (($size_img[0]<$w) && ($size_img[1]<$h)) return true;  
    // получим коэффициент сжатия исходного изображения  
    $src_ratio=$size_img[0]/$size_img[1];  

    // Здесь вычисляем размеры уменьшенной копии,  
    // чтобы при масштабировании сохранились  
    // пропорции исходного изображения  
    if ($ratio<$src_ratio)  
    {  
      $h = $w/$src_ratio;  
    }  
    else  
    {  
      $w = $h*$src_ratio;  
    }  
    // создадим пустое изображение по заданным размерам  
    $dest_img = imagecreatetruecolor($w, $h);     
    $white = imagecolorallocate($dest_img, 255, 255, 255);          
      
    if ($size_img[2]==2)  $src_img = imagecreatefromjpeg($filename);                         
    else if ($size_img[2]==1) $src_img = imagecreatefromgif($filename);                         
    else if ($size_img[2]==3) $src_img = imagecreatefrompng($filename);  

    // масштабируем изображение     функцией imagecopyresampled()  
    // $dest_img - уменьшенная копия  
    // $src_img - исходной изображение  
    // $w - ширина уменьшенной копии  
    // $h - высота уменьшенной копии           
    // $size_img[0] - ширина исходного изображения  
    // $size_img[1] - высота исходного изображения  
    imagecopyresampled($dest_img, $src_img, 0, 0, 0, 0, $w, $h, $size_img[0], $size_img[1]);                   

    // Выводим уменьшенную копию в поток вывода  
    if ($size_img[2]==2)  header('Content-type: image/jpg');                         
    else if ($size_img[2]==1) header('Content-type: image/gif');                         
    else if ($size_img[2]==3) header('Content-type: image/png');  
    // Выводим уменьшенную копию в поток вывода  
    if ($size_img[2]==2)  imagejpeg($dest_img);                         
    else if ($size_img[2]==1) imagegif($dest_img);                         
    else if ($size_img[2]==3) imagepng($dest_img);  

    // чистим память от созданных изображений  
    imagedestroy($dest_img);  
    imagedestroy($src_img);  
    return true;            
  }     
?>


Этот файл (img.php) нужно подставлять в параметр src тега <img> на страницу, где используются изображения.

<img src="img.php?file=img.jpg" border="0"  alt="">


Имя файла, который необходимо преобразовать, передается в параметре ?file=img.jpg. И на странице отображается уже измененное изображение.

Добавлено: 20 Апреля 2018 09:32:30 Добавил: Андрей Ковальчук

Простенькая капча

Как то для одного простенького проекта мне понадобилась капча, готовые решения типа KCAPTCHA использовать не захотелось, а по тому слегка полистав мануалы я написал ( половину слизал ) свою капчу.

«Для тех кто не в курсе:

Captcha — простейшая система проверки «компьютер или человек». Используется этот тест для защиты от спама или авторегистрации на сайте.»

Капчу я решил написать на PHP, и готовый вариант будет выглядеть примерно так

Создаем captcha.php, обратите внимание на кодировку желательно использовать «UTF-8 без BOM» иначе может не работать.

<?php
session_start();
session_register('code');
$height = 20;//Высота картинки
$width = 100;//Ширина картинки
/*Генерируем случайное число, для кода*/
$_SESSION['code'] = rand(10000, 99999);//генерируем 5-ти значное число
for($i = 0; $i &lt; 5; $i++)
{
    $m[$i] = substr($_SESSION['code'], $i, 1);
}
$image = imagecreate($width, $height); //Создаем изображение 100x20
$backgroundColor = imagecolorallocate($image, 204, 216, 6); //Задаем цвет для фона
$noiseColor = imagecolorallocate($image, 100, 120, 180);//Задаем цвет помех
$color = imagecolorallocate($image, 0, 0, 0);//Задаем цвет для чисел
for( $i = 0; $i &lt; ($width*$height)/3; $i++ )
{
  imagefilledellipse($image, mt_rand(0,$width), mt_rand(0,$height), 1, 1, $noiseColor);
}
/* Рисуем линии*/
for( $i = 0; $i &lt; ($width * $height)/150; $i++ )
{
  imageline($image, mt_rand(0, $width), mt_rand(0, $height), mt_rand(0, $width), mt_rand(0, $height), $noiseColor);
}

for($i = 0; $i &lt; 5;$i++)
{
    imagestring($image, 3, $y += 15, 3, $m[$i], $color);
}
header('Content-Type: image/jpeg');
imagejpeg($image);
?>

Этим файлом мы создаем само изображение, тут же задаем для него такие параметры как цвет шрифта, фона и полосок.

Далее в нужной вам форме нужно вставить следующий код:

// В самом начале документа начинаем сессию.
<?php
session_start();
?>
// В нужном для вас месте создаем форму или используем уже существующею.
<img src="captcha.php">
<form method="post">
Введите число: <input type="text" name="getСode">
<input name="sub" type="submit" value="Ввод">
</form>
<?php
if($_POST['sub'])
{
    if($_POST['getСode'] == $_SESSION['code'])
    {
        echo "Число введено верно";
    } else {
        echo "Число введено неверно";
    }
}
?>

Собственно на этом все, ничего сложного.

Добавлено: 15 Апреля 2018 07:22:33 Добавил: Андрей Ковальчук

Изменяем размер изображения сохраняя пропорции.

В предыдущем посте я уже писал о том как можно изменить изображения сохранив его пропорции, но было несколько нюансов: можно было изменить только jpg картинку и хоть пропорции и сохранялись но миниатюры было не удобно делать т.к. формат миниатюры оставался тем же. Дальше я расскажу как избежать все эти подводные камни и сделать хорошие миниатюры.Во первых я сразу буду использовать форму для загрузки картинки ( так проще тестировать скрипт ).

<form action="" method="post" name="img_folder_edit" enctype="multipart/form-data">
<input name="userfile" type="file" style="width: 200px;" >
<input type="submit" name="image_upload" value="UPLOAD" style="margin-left:20px;" >
</form>

<?php
if ($_POST['image_upload']){
  $uploaddir = 'image/tmp_image/'; # Папка загрузки
  $extentions = array('1','2','3','6'); # определяем типы разрешенных файлов
  $userfilesize = $_FILES['file']['size']; 
  $maxfilesize = 1024*1024*7; # Максимальный размер файла в данный момент 7Мб
  $width = 200; # Максимальная ширина миниатюры
  $height = 160;  # Максимальная высота миниатюры
  $file_type = exif_imagetype($_FILES['userfile']['tmp_name']); # определяем тип файла
  if (in_array($file_type, $extentions) &amp;&amp; ($maxfilesize >= $userfilesize)){
    switch ($file_type) {
      case '2': $file_type = '.jpg'; break;
      case '3': $file_type = '.png'; break;
      case '1': $file_type = '.gif'; break;     
      case '6': $file_type = '.bmp'; break;
      default: print 'Неизвестная ошибка в определении типа файла<br />';
    }
    $new_image = 'two'.$file_type;
    $basename = 'one'.$file_type;
    move_uploaded_file($_FILES['userfile']['tmp_name'], $uploaddir.$basename); #загружаем картинку
    $ext = $file_type; # Получаем формат уменьшаемого изображения
    list($width_orig, $height_orig) = getimagesize($uploaddir.$basename); # получаем размеры изображения
    $ratio_orig = $width_orig/$height_orig;   
    if ($width/$height > $ratio_orig) {
      $width = $height*$ratio_orig;
    } else {
      $height = $width/$ratio_orig;
    }
    $image_p = imagecreatetruecolor($width, $height);
    switch ($ext) {
            case '.jpg': $source = imagecreatefromjpeg($uploaddir.$basename); break;
            case '.gif': $source = imagecreatefromgif($uploaddir.$basename); break;
            case '.png': $source = imagecreatefrompng($uploaddir.$basename); break;     
            case '.bmp': $source = imagecreatefromwbmp($uploaddir.$basename); break;
        }
    imagecopyresampled($image_p, $source, 0, 0, 0, 0, $width, $height, $width_orig, $height_orig);
        switch ($ext) {
            case '.jpg': imagejpeg($image_p, $uploaddir.$new_image, 100); break;                
            case '.gif': imagegif($image_p, $uploaddir.$new_image);  break;                
            case '.png': imagepng($image_p, $uploaddir.$new_image); break;                
            case '.bmp': imagewbmp($image_p, $uploaddir.$new_image); break;
        }
 
    # выводы текста   
    print 'Upload comlete <br />';
    print $width_orig.'x'.$height_orig. '<br />';
    print 'new size'.$width.'x'.$height.'<br />';
    print '<img src="'.$uploaddir.$new_image.'"</a>';
    # освобождаем память
    imagedestroy($image_p);
      imagedestroy($source);
  } else {
    
    print 'Размер файла слишком большой или файл имеет не поддерживаемое расщирение';
  }
  
}
?>

Для начала мы задаем параметры для работы: папку загрузки, типы файлов (jpg, png, gif, bmp), определяем размер файла и максимальный разрешенный размер файла, а так же ширину и высоту (максимальную) миниатюры. Выходное изображение будет не больше 200×160 пикселей при этом сохранит формат (16:9, 16:10, 4:3 и т.д.) и не будет пиксилизированно!

Добавлено: 14 Апреля 2018 07:10:57 Добавил: Андрей Ковальчук

Водяной знак на PHP+GD

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

function watermark($_source_path, $_watermark_path, $_file='') {
/* Проверка - подключена ли библиотека GD - если её нет, вам необходимо либо самому подключить эту библиотеку * (В файле php.ini, секция extensions, необходимо прописать либо раскомментировать * extension=php_gd2.dll - в windows. */
if (!extension_loaded('gd')) {
return false;
}
if (!empty($_source_path) && !empty($_watermark_path)) {
$i_source = imagecreatefrompng($_source_path);
$i_watermark = imagecreatefrompng($_watermark_path);
$result = imagecreatetruecolor(imagesx($i_source), 
imagesy($i_source));
/* Координаты 0,0,0,0 - задают координаты соединения изображений. * Поигравшись с ними можно изменить положение водяного знака (да и исходного изображения) */
imagecopy($result, $i_source, 0, 0, 0, 0, imagesx($i_source), imagesy($i_source));
imagecopy($result, $i_watermark, 0, 0, 0, 0, imagesx($i_watermark), imagesy($i_watermark));
imagedestroy($i_source);
imagedestroy($i_watermark);
if (!empty($_file)) {
imagepng($result, $_file, 4);
}else{
return $result;
}
}
}

Добавлено: 13 Апреля 2018 18:29:25 Добавил: Андрей Ковальчук

CAPTCHA, по которой надо просто кликнуть мышью

(CAPTCHA - это полностью автоматический тест Тьюринга для различения компьютеров и людей)

Устали от кодов, которые нужно каждый раз вводить? Если так и есть, пора научиться создавать CAPTCHA, на который надо лишь кликнуть мышью. Именно этому и будет посвящен наш сегодняшний урок.

Введение

Мы реализуем очень уникальный способ приведения в исполнение теста CAPTCHA. Одно из больших преимуществ подобного способа это отсутствие необходимости хранить на сервере сайта несколько сотен, а то и тысяч изображений.

Цель урока

Данный урок нацелен на создание CAPTCHA, по которому достаточно кликнуть курсором мыши. Давайте назовем его клик- CAPTCHA.

Изображение CAPTCHA будет отображаться в форме, тогда как маска будет храниться на сервере сайта. Маска на самом деле всего лишь копия изображения CAPTCHA, только без орнамента. Дело в том, что маска позволит нам распознать цвет каждого пикселя. Вы все поймете сами дальше.

Шаг 1: Создайте свой captcha.php

Сразу же хочу сказать, что мы не будем использовать шрифты в этом уроке, мы лишь воспользуемся GD библиотекой, чтобы представить тест CAPTCHA.

Итак, давайте создадим captcha.php.

В нашем скрипте, мы запустим сеанс соединения с сервером с помощью свойства session_start() и укажем параметры переменных $width и $height.

<?php 
// запуск сеанса
session_start(); 
// параметры переменных
$width = 180;
$height = 90;
$blob_width = 40;
$blob_height = 40; 
?>

Шаг 2: Содержимое изображения

На этом этапе, мы создадим содержимое изображения, а именно красный круг с орнаментом. Это задача выполняется с помощью функции imagecreatetruecolor().
// содержимое изображения
$image = imagecreatetruecolor($width, $height);
Привяжем параметры переменной цвета к элементу $image:

// фоновый цвет изображения
$white = imagecolorallocate($image, 230, 230, 230);
$red  = imagecolorallocate($image, 255, 0, 0);
$blue  = imagecolorallocate($image, 0, 0, 230);
Теперь закрасим белым цветом:

// наполняем изображение
imagefilledrectangle($image, 0, 0, $width, $height ,$white);

И наконец, создаем орнамент в виде спирали для фона нашего изображения.
// создаем орнамент в форме спирали
$theta    = 1;
$thetac   = 7;
$radius   = 16;
$circles  = 20;
$points   = 32; 
for ($i = 0; $i < ($circles * $points) - 1; $i++)
{
$theta = $theta + $thetac;
$rad = $radius * ($i / $points );
$x = ($rad * cos($theta)) + $x_axis;
$y = ($rad * sin($theta)) + $y_axis;
$theta = $theta + $thetac;
$rad1 = $radius * (($i + 1) / $points);
$x1 = ($rad1 * cos($theta)) + $x_axis;
$y1 = ($rad1 * sin($theta )) + $y_axis;
imageline($image, $x, $y, $x1, $y1, $blue);
$theta = $theta - $thetac;
}

Шаг 3: Кружок и Маска

Теперь мы нарисуем красный круг и создадим его маску-копию.

Кружок:

Сперва выберем местоположение кружка на создаваемом шаблоне, а затем выведем его на изображении нашего CAPTCHA с помощью свойства imagefilledellipse().
// указываем расположение кружка
$x_axis = rand($blob_width, $width) - ($blob_width / 2);
$y_axis = rand($blob_height, $height)  - ($blob_height / 2);
Укажем, что цвет будет красный (как было оговорено ранее).

// выводим кружок на изображение
imagefilledellipse ($image, $x_axis, $y_axis, $blob_width, $blob_height, $red);

Маска:

Почти так же как и в шаге 2 с помощью свойства imagecreatetruecolor() мы создаем маску-копию.
// создаем маску
$mask_image = imagecreatetruecolor($width, $height);
Снова задаем цветовые параметры переменной color для кружка и для фона изображения. Размещая красный кружок, указываем те же самые координаты что и для круга на изображении CAPTCHA.

// фоновый цвет маски
$mask_white = imagecolorallocate($mask_image, 255, 255, 255);
$mask_red  = imagecolorallocate($mask_image, 255, 0, 0); 

// заполняем содержимым изображение
imagefilledrectangle($mask_image, 0, 0, $width, $height ,$mask_white); 
// размещаем кружок на изображении
imagefilledellipse ($mask_image, $x_axis, $y_axis, $blob_width, $blob_height, $mask_red);

Шаг 4: Сохраняем созданную маску на сервере

Чтобы наш тест работал, необходимо сохранить маску в данную сессию сервера. Для этого нужно сначала вывести слой-маску куда-нибудь, а прежде, чем сохранить в нашу сессию, нужно извлечь его в виде первичных данных.

Итак воспользуемся свойством ob_start(), чтобы активизировать буферизацию на выходе и записать данные случайным образом/виртуально.
// сохраняем маску в буфер
ob_start();

Теперь выводим маску используя свойство imagepng().
imagepng($mask_image);

Возвращаем маску в виде первичных данных с помощью свойства ob_get_contents(), которое извлекает содержимое буфера уже в виде одной строки.

$mask_image_data = ob_get_contents();  // извлекаем то, что сохранили в буфер

Преобразовываем полученные из буфера данные в Base64, так как нам нужно создать код понятный серверу.
// преобразуем данные в Base64
$mask_image_data_b64 =  base64_encode($mask_image_data);

И наконец, сохраняем полученное в сессии.

Шаг 5: Выведем полученное в браузер!

На этом этапе мы выведем CAPTCHA в браузер. Для этого нам необходимо указать тип содержимого, так чтобы браузер распознал и отобразил все должным образом.
// Указываем тип
header('Content-type: image/jpeg');
header('Cache-control: no-cache'); 
// вывод изоражения
imagejpeg($image); 
imagedestroy($image);

Давайте, наконец, все сохраним и откроем в браузере!

Шаг 6: Создаем форму

Давайте создадим новый PHP script и назовем его index.php. Страница будет содержать форму, которую мы подтвердим используя созданный нами CAPTCHA.

HTML код:

Замените кнопку Submit кнопкой с Image. В примере я дам ей имя ’submit’, но вы можете назвать ее как душе угодно.
<form action="<?php echo $_SERVER['PHP_SELF']; ?>" method="post" enctype="multipart/form-data">
  <p>Name<br/><input type="text" name="name" /></p>
  <p>Comment<br/><textarea name="message"></textarea></p>
   <p>
   Click the Red Circle to continue:<br/>
   <input type='image' name='submit' src='captcha.php' alt='Captcha Security'  />
   </p>
   </form>

В браузере код должен выглядеть следующим образом:

Шаг 7: Подтвердим форму!

Раз все работает и CAPTCHA отображается как положено, требуется задать функцию подтверждения формы.

Ключевые параметры PHP кода для подтверждения формы следующие:

1. session_start()
2. $_POST['submit_x'] and $_POST['submit_y']
3. Распознавание цвета точки –клика.

В этот же код мы добавим контроль правильности заполнения полей формы. И уточним X и Y координаты области рисунка, в которую нужно попасть :) курсором.
session_start(); 
if(isset($_POST['submit_x']) && isset($_POST['submit_y'])) { 
if(!empty($_POST['name']) && !empty($_POST['message'])) { 
// retrive the image captcha data
$data = base64_decode($_SESSION['captcha_image_code']); 
$captcha_image = imagecreatefromstring($data);
$x = $_POST['submit_x'];
$y = $_POST['submit_y']; 
// get the pixel color of the clicked x and y coordinate
$rgb = imagecolorat($captcha_image, $x, $y);

$color_tran = imagecolorsforindex($captcha_image, $rgb); 
// check if the color is red and red only
$captcha_ok = ($color_tran['red'] == 255 && $color_tran['green'] == 0 && $color_tran['blue'] == 0 && $color_tran['alpha'] == 0) ; 
if($captcha_ok) { 
$result = "Thank you for submitting your comment."; 
} else { 
$result = "Please make sure you click the red circle!";  } 
 } else { 
$result = "Please fill out the entire form."; 
} 
}

Чтобы установить цвет и координаты кликнутого пикселя, необходимо сперва извлечь изображение маски из сохраненной сессии, а затем декодировать его как показано ниже:
// извлекаем данные изображения CAPTCHA
$data = base64_decode($_SESSION['captcha_image_code']);

Преобразуем его обратно в изображение используя функцию imagecreatefromstring().
$captcha_image = imagecreatefromstring($data);

Теперь извлекаем X и Y координаты клика и цвет кликнутого пикселя с помощью imagecolorsforindex(). Нужно убедиться, что цвет точки именно красный.

// получаем цвет точки клика
$rgb = imagecolorat($captcha_image, $x, $y);
$color_tran = imagecolorsforindex($captcha_image, $rgb); 

// проверка действительно ли цвет точки именно красный
$captcha_ok = ($color_tran['red'] == 255 && $color_tran['green'] == 0 && $color_tran['blue'] == 0 && $color_tran['alpha'] == 0) ;

Свойство $captcha_ok помогает понять в то ли место кликнул пользователь.

ГОТОВО!!! Теперь у вас есть уникальный тест CAPTCHA. Надеюсь вам понравился урок

Добавлено: 07 Апреля 2018 07:11:41 Добавил: Андрей Ковальчук

функция проверки изображения на валидность (защита от XSS-атак)

<?php
 
// функция проверки изображения на валидность (защита от XSS-атак)
function verify_image ($file) {
    // защита от Null-байт уязвимости PHP
    $file = preg_replace('/\0/uis', '', $file);
    // проверка изображения
    $txt = file_get_contents($file);
    if (preg_match('#&(quot|lt|gt|nbsp|amp);#i', $txt)) return false;
    elseif (preg_match("#&\#x([0-9a-f]+);#i", $txt)) return false;
    elseif (preg_match('#&\#([0-9]+);#i', $txt)) return false;
    elseif (preg_match("#([a-z]*)=([\`\'\"]*)script:#iU", $txt)) return false;
    elseif (preg_match("#([a-z]*)=([\`\'\"]*)javascript:#iU", $txt)) return false;
    elseif (preg_match("#([a-z]*)=([\'\"]*)vbscript:#iU", $txt)) return false;
    elseif (preg_match("#(<[^>]+)style=([\`\'\"]*).*expression<span class="MathJax_Preview"><img src="http://blogfigaroo.ru/wp-content/plugins/latex/cache/tex_4bce412ebac80101838e364f858e1d07.gif" style=" " class="tex" alt="[^>]*>#iU" ,="" $txt))="" return="" false;="" elseif="" (preg_match("#(<[^="">]+)style=([\`\'\"]*).*behaviour" /></span>[^>]*>#iU", $txt)) return false;
    elseif (preg_match("#</*(applet|link|style|script|iframe|frame|frameset)[^>]*>#i", $txt)) return false;
    return true;
}

Добавлено: 04 Апреля 2018 11:48:23 Добавил: Андрей Ковальчук

Php TTF шрифты

TTF шрифтами можно воспользоваться для создания и вывода динамических картинок, с использованием функции ImageTtfText. Здесь приведен скрипт создающий и выводящий вот такой банер. Этот банер в Png формате, чересстрочный и прозрачный.

<?php
/*
назовите этот файл любым именем, 
и папка '/fonts', в которой должен лежать TTF шрифт
нашем случае 'verdana.ttf'
$user_online - в онлайне 
$host_stat_day - хостов за день
$hit_stat_day - хитов за день
*/
    // эти переменные вам надо брать в скрипте, 
    // а мы просто их поставили
$user_online = 4;
$host_stat_day = 2724;
$hit_stat_day = 22476;

$font_size = 14;
    // ширина банера
$width = '150';
    // высота банера
$height = '50';
    // имя файла, где лежит ttf шрифт
$font = str_replace ( "\\", "/", getcwd () )."/fonts/verdana.ttf";
    // имя файла, в котором сохраняется банер
$img_new = "banner_ttf.png";
    // насколько делать отступ текста в банере
$one_point = '5';
    // уменьшает или увеличивает шрифт, меняйте значение
$korr_type = '0.7';
    // уменьшает или увеличивает отступ в конце строки, тоже меняйте
$korr_line = '1.6';

$bibl_ext = dirname ($_SERVER['SCRIPT_FILENAME']).'/extensions/php_gd.dll';
if ( ! extension_loaded ('gd') and @is_file ($bibl_ext)){ dl ("extensions/php_gd.dll");}
if ( ! extension_loaded ('gd')){ print "Нет файла библиотеки $bibl_ext";}


function replace_cyr($path){
$search = array ("'Ё'", "'А'", "'Б'", "'В'", "'Г'", "'Д'", "'Е'", "'Ж'", "'З'", "'И'", "'Й'", "'К'", "'Л'", "'М'", "'Н'", "'О'", "'П'", "'Р'", "'С'", "'Т'", "'У'", "'Ф'", "'Х'", "'Ц'", "'Ч'", "'Ш'", "'Щ'", "'Ъ'", "'Ы'", "'Ь'", "'Э'", "'Ю'", "'Я'", "'а'", "'б'", "'в'", "'г'", "'д'", "'е'", "'ж'", "'з'", "'и'", "'й'", "'к'", "'л'", "'м'", "'н'", "'о'", "'п'", "'р'", "'с'", "'т'", "'у'", "'ф'", "'х'", "'ц'", "'ч'", "'ш'", "'щ'", "'ъ'", "'ы'", "'ь'", "'э'", "'ю'", "'я'", "'ё'", "'0'e");
$replace= array ('&#1025;', '&#1040;', '&#1041;', '&#1042;', '&#1043;', '&#1044;', '&#1045;', '&#1046;', '&#1047;', '&#1048;', '&#1049;', '&#1050;', '&#1051;', '&#1052;', '&#1053;', '&#1054;', '&#1055;', '&#1056;', '&#1057;', '&#1058;', '&#1059;', '&#1060;', '&#1061;', '&#1062;', '&#1063;', '&#1064;', '&#1065;', '&#1066;', '&#1067;', '&#1068;', '&#1069;', '&#1070;', '&#1071;', '&#1072;', '&#1073;', '&#1074;', '&#1075;', '&#1076;', '&#1077;', '&#1078;', '&#1079;', '&#1080;', '&#1081;', '&#1082;', '&#1083;', '&#1084;', '&#1085;', '&#1086;', '&#1087;', '&#1088;', '&#1089;', '&#1090;', '&#1091;', '&#1092;', '&#1093;', '&#1094;', '&#1095;', '&#1096;', '&#1097;', '&#1098;', '&#1099;', '&#1100;', '&#1101;', '&#1102;', '&#1103;', '&#1105;', '0');
return preg_replace ($search,$replace,$path);
}

function x_size ($path,$width,$font_size,$one_point){ 
global $korr_line;
$font_size = $font_size/$korr_line; 
return $width-$one_point-strlen($path)*$font_size; 
}
function Create_images ($width,$height,$font,$font_size,$img_new,$one_point){
global $user_online, $host_stat_day, $hit_stat_day, $korr_type;
$im = ImageCreate ($width,$height);
ImageInterlace ($im, 1);
$bgcolor = ImageColorAllocate($im, 255, 255, 255);
$bgcolortrans = ImageColorTransparent($im, $bgcolor);

    // если закомментировать эту строку '#', то не будет рамки 
$blue = ImageColorAllocate($im, 20, 93, 233);
    // красный цвет
$red = ImageColorAllocate($im, 255, 0, 0);
    // цвет слов 
$black = ImageColorAllocate($im, 0, 0, 0);
    // что написано в 1 строке
$stroka1 = replace_cyr("Статистика сайта...");
    // что написано во 2 строке
$stroka2 = replace_cyr("Онлайн:");
    // что написано в 3 строке
$stroka3 = replace_cyr("Хостов:");
    // что написано в 4 строке
$stroka4 = replace_cyr("Хитов:");

$font_size = round ($height/4.5);
$point = $font_size;
$font_size_c = round ($font_size*$korr_type);
$width_a = $width-1;
$height_a = $height-1;
ImageRectangle ($im, 0, 0, $width_a, $height_a, $blue);
$point=$font_size;
ImageTtfText ($im, $font_size_c, 0, $one_point, $point, $black, $font, $stroka1); 
$point=2*$font_size;
ImageTtfText ($im, $font_size_c, 0, $one_point, $point, $black, $font, $stroka2); 
$x_size = x_size ($user_online,$width,$font_size, $one_point);
ImageTtfText ($im, $font_size_c, 0, $x_size, $point, $red, $font, $user_online); 
$point=3*$font_size;
ImageTtfText ($im, $font_size_c, 0, $one_point, $point, $black, $font, $stroka3); 
$x_size = x_size ($host_stat_day,$width,$font_size, $one_point);
ImageTtfText ($im, $font_size_c, 0, $x_size, $point, $red, $font, $host_stat_day); 
$point=4*$font_size;
ImageTtfText ($im, $font_size_c, 0, $one_point, $point, $black, $font, $stroka4); 
$x_size = x_size ($hit_stat_day,$width,$font_size, $one_point);
ImageTtfText ($im, $font_size_c, 0, $x_size, $point, $red, $font, $hit_stat_day); 
ImagePng ($im,$img_new);
ImageDestroy ($im);
return true;
}
    // эта строка запишет в файл 'banner_ttf.png' картинку
Create_images ($width,$height,$font,$font_size,$img_new,$one_point);

    // печатаем html
print"
<!DOCTYPE HTML PUBLIC '-//W3C//DTD HTML 4.0 Transitional//EN'>
<HTML><HEAD><TITLE></TITLE></HEAD>
<BODY>

<p>&nbsp;</p><img src='banner_ttf.png'>

</BODY></HTML>";
?>

Добавлено: 02 Апреля 2018 21:39:12 Добавил: Андрей Ковальчук

Проверка формата картинки

Прежде чем, начать работу с картинками, стоит определить ее формат. Убедиться в том, что данное изображение возможно редактировать. Поэтому раздел по работе с графикой, стоит начать именно с этой темы. Ниже приведена функция, которая определяет расширение файла и сравнивает с массивом форматов. Которые удовлетворяют условия, при которых код обработки картинок будет выполнен без ошибок.
Пример:

// файл, который будет проверен 
$file = "./test.png"; 
// массив валидных форматов 
$validFormat = array('jpg', 'jpeg', 'gif', 'png'); 
// проверка файла на корректный формат 
$resultFormat = checkValidFormat($file, $validFormat); 
if($resultFormat){ 
  echo "Корректный формат"; 
}else{ 
  echo "Не корректный формат"; 
} 
 
/** 
* Проверка корректности формата файла 
*  
* @param string $file - имя файла или путь до файла 
* @param array $validFormat - массив с  
* корректными форматами 
* 
* @return boolean - результат проверки 
*/ 
function checkValidFormat($file, $validFormat){ 
    // определяем формат файла 
    $format = end(explode(".", $file));  
    if(in_array(strtolower($format), $validFormat)){ 
        return true; 
    } 
    return false; 
} 

В приведенном примере, использовались ранее не описанная функция - strtolower. Она осуществляет перевод текста в нижний регистр. Это сделано с целью привести полученный формат файла к одному виду с теми, что заданы в массиве корректных форматов.

Добавлено: 29 Марта 2018 19:51:05 Добавил: Андрей Ковальчук

Проверка размера картинки

Еще одним немаловажным критерием при работе с картинками является их размер. В зависимости от большого или маленького размера, могут быть выполнены различные действия. Например, отказ от обработки изображения с выводом соответствующего сообщения или же будет выполнено уменьшение изображения до
допустимых пределов. В приведенном ниже рецепте, осуществляется получение размера картинки и сравнение их с максимально допустимыми.

Пример:

// файл, который будет проверен 
$file = "./test.jpg"; 
// массив валидных размеров 
$validSize = array( 
    'width' => 100, // ширина в пикселях 
    'height' => 100 // высота в пикселях 
); 
// проверка 
$resultSize = checkValidSize($file, $validSize); 
if($resultSize){ 
  echo "Корректный размер файла"; 
}else{ 
  echo "Не корректный размер файла"; 
} 
 
/** 
* Проверка корректности размера файла 
*  
* @param string $file - имя файла или путь до файла 
* @param array $validSize - массив с  
* корректными размерами.  
 
* array( 
*   // максимально допустимая ширина 
*   'width' => $width,   
*   // максимально допустимая высота 
*   'heigth' => $heigth 
* ) 
* 
* @return boolean - результат проверки 
*/ 
function checkValidSize($file, $validSize){ 
    // получаем массив размеров картинки 
    $sizeImg = @getimagesize($file);  
    // если не удалось обработать картинку 
    if(!$sizeImg) return false; 
    // сравнение размеров картинки с валидными 
    if($validSize['width'] >= $sizeImg[0] &&  
$validSize['height'] >= $sizeImg[1]){ 
        return true; 
    } 
    return false; 
} 

В примере была использована не описанная ранее функция –
getimagesize. Она позволяет получать размер картинки – ширину
и высоту. Данные возвращает в виде массива.

Добавлено: 29 Марта 2018 19:49:32 Добавил: Андрей Ковальчук

Проверка наличия библиотеки GD

В двух предыдущих рецептах осуществлялась проверка корректности изображений, с которыми в последствии предстоит работать. Но прежде чем, начать их обрабатывать стоит проверить наличие самой библиотеки GD, с помощью которой и производятся все манипуляции с изображениями. Хочу обратить внимание, что это не единственная библиотека, для работы с изображениями, но в этом сборнике рецептов все примеры будут использовать только GD.
Пример:

if(isset GD()){
echo "Библиотека установлена!";
}else{
echo "Библиотека НЕ установлена!";
}
function isset GD(){
if (!extension_loaded('gd'))	{
if (!dl('gd.so'))	{
return false;
}
}
return true;
}

В приведенном примере использовались ранее не описанные функции - extension_loaded и dl. Первая функция определяет, загружено расширение или нет, вторая загружает расширение.

Добавлено: 29 Марта 2018 19:48:05 Добавил: Андрей Ковальчук

Изменение размера картинки

Теперь все приготовления окончены и можно приступать непосредственно к работе с картинками. Первый рецепт покажет, как можно изменять размер картинки. Пропорционально увеличивать или уменьшать. Если новый размер картинки будет задан не пропорционально, то холст создастся по новым размерам, а картинка изменится до максимально допустимого, без потери пропорций.

Пример:

// исходное изображение 
$source = "test.jpg";  
// путь для сохранения новой картинки 
$new_file = "test_new.jpg";  
97 
 
$width = 200; // новая ширина 
$height = 200; // новая высота 
 
// цвет заливки фона 
$rgb = 0xffffff;  
//узнаем размеры исходной картинки 
$size = getimagesize($source); 
//пропорция ширины 
$x_ratio = $width / $size[0];  
//пропорция высоты 
$y_ratio = $height / $size[1];  
// определяем соотношения ширины к высоте 
$ratio = min($x_ratio, $y_ratio); 
$use_x_ratio = ($x_ratio == $ratio);  
// высчитываем новую ширину картинки 
$new_width   = $use_x_ratio  ? $width  :    
  floor($size[0] * $ratio); 
// высчитываем новую высоту картинки 
$new_height  = !$use_x_ratio ? $height :  
  floor($size[1] * $ratio); 
// расхождение с заданными параметрами по ширине 
$new_left    = $use_x_ratio  ? 0 :  
floor(($width - $new_width) / 2); 
// расхождение с заданными параметрами по высоте 
$new_top     = !$use_x_ratio ? 0 :  
floor(($height - $new_height) / 2); 
// создаем холст пропорциональное сжатой картинке 
$img = imagecreatetruecolor($width,$height); 
// заливаем холст цветом $rgb 
imagefill($img, 0, 0, $rgb);  
// загружаем исходную картинку 
$photo = imagecreatefromjpeg($source);  
// копируем на холст сжатую картинку с учетом 
расхождений 
imagecopyresampled($img, $photo, $new_left, $new_top, 
  0, 0, $new_width, $new_height, $size[0], $size[1]);  
// сохраняем результат 
imagejpeg($img, $new_file);  
// очищаем память после выполнения скрипта 
imagedestroy($img); 
imagedestroy($photo);


В этом рецепте появилось много, ранее не используемых функций.
Обо всех по порядку:
Min – находит минимальное значение, из сравниваемых.
Imagecreatetruecolor – создает новое, пустое изображение заданного размера.
Imagefill – осуществляет заливку заданным цветом. В данном примере заливается все изображение.
Imagecreatefromjpeg – создает изображение из файла, работает
только с форматом jpeg.
Imagecopyresampled – копирует одно изображение на другое, с возможностью смещения и изменения размера копируемого. В данном случае, копируемое изображение меняет размер и центрируется, относительно пустого изображения.
Imagejpeg – Сохраняет или выводит в браузер изображение в
формате jpeg.
Imagedestroy – очищает память занятую изображением.

Добавлено: 29 Марта 2018 07:39:28 Добавил: Андрей Ковальчук