Php урок 9. Сжатие изображений

Автор: | 11.09.2015

PHP и GD library — работа с графикой

В этой статье рассмотрены вопросы работы в PHP c графической библиотекой GD library — открытие, вывод на экран и сохранение изображений.

Вступление

Обработка изображений сейчас очень востребована в скриптах языка программирования PHP. Рассмотрим наиболее частые случаи работы с графическими файлами.

Для начала убедитесь, что у вас установлена библиотека GD library — просто запустите скрипт с функцией phpinfo(); В результате выполнения скрипта будет выведена информация об этой библиотеке (содержится в блоке gd):

Чтение изображений

Нашими первыми функциями будут создание нового изображения или открытие уже существующего. Пока рассмотрим лишь открытие существующего изображения:

// переменная, которая указывает на путь к нашему изображению
$im = @imagecreatefromjpeg('test.jpg'); 
if ($im === false) {   
 die ('Не удается открыть изображение');
}
echo 'Изображение успешно открыто';

Как видите, функция imagecreatefromjpeg() используется просто для открытия изображения типа JPEG, но не вывода его на дисплей. Переменная $im содержит путь к изображению. Если указанного файла не существует, то выдается сообщение «Не удается открыть изображение».

Если же вы хотите открыть изображение не JPEG, а, к примеру, GIF, то нужно вызвать другую функцию:

// переменная, которая указывает на путь к нашему изображению
$im = @imagecreategif('test_gif.gif'); 
if ($im === false) {
    die ('Не удается открыть изображение');
}
echo 'Изображение успешно открыто';

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

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

Открытие файлов разных типов

Наша универсальная функция может открывать разные типы графических файлов путем определения расширения файла:

$image = open_image('test_jpg.jpg'); 
if ($image === false) {
    die ('Не удается открыть изображение');
}
echo 'Изображение успешно открыто'; 
function open_image ($file) {
    // Получаем информацию об расширении файла
    $extension = strrchr($file, '.');
    $extension = strtolower($extension);
    switch($extension) {
        case '.jpg':
        case '.jpeg':
            $im = @imagecreatefromjpeg($file);
            break;
        case '.gif':
            $im = @imagecreategif($file);
            break;
         // ... и так далее
         default:
            $im = false;
            break;
    }
    return $im;
}

Но даже это решение не решает всех проблем: а что делать, если у файла расширение задано неправильно? Ведь JPG картинке можно запросто дать расширение GIF (test_jpg.gif) или GIF картинку назвать ‘test_gif.txt’.

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

Вот пример такого скрипта:

$image = open_image('test_jpg.jpg'); 
echo 'Изображение успешно открыто'; 
function open_image ($file) {
    # JPEG:
    $im = @imagecreatefromjpeg($file);
    if ($im !== false) { return $im; }
    # GIF:
    $im = @imagecreategif($file);
    if ($im !== false) { return $im; }
    # PNG:
    $im = @imagecreatepng($file);
    if ($im !== false) { return $im; }
    # GD File:
    $im = @imagecreategd($file);
    if ($im !== false) { return $im; }
    # GD2 File:
    $im = @imagecreategd2($file);
    if ($im !== false) { return $im; }
    # WBMP:
    $im = @imagecreatewbmp($file);
    if ($im !== false) { return $im; }
    # XBM:
    $im = @imagecreatexbm($file);
    if ($im !== false) { return $im; }
    # XPM:
    $im = @imagecreatexpm($file);
    if ($im !== false) { return $im; }
    # Попытка открыть со строки:
    $im = @imagecreatestring(file_get_contents($file));
    if ($im !== false) { return $im; }
    return false;
}

Как видите, идея довольно просто — мы просто по очереди вызываем функциюimagecreate() до тех пор, пока не определим тип графического файла.

Еще можно определить тип файла через функцию getimagesize() — она возвращает массив, который содержит информацию о файле — [width, height, imageType] (ширина, высота, тип файла) — более подробно об этой функции — getimagesize.

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

Вывод на экран и сохранение изображения

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

Вот пример их использования:

// Открываем изображение
$image = open_image('test_jpg.jpg');
// Некоторые манипуляции с изображением (изменение размера, цвета и т.п.) 
// Вывод изображения на экран
imagejpeg($image); 
function open_image ($file) {
    // полный листинг функции приведен выше
}

Если вы выполните этот скрипт по указанной выше ссылке, то результат вас удивит: вместо изображения вы можете увидеть лишь набор непонятных символов — это будет в браузере Opera и Mozilla Firefox, браузеры на движке IE (cам Internet Explorer, Avant и Maxton) умеют корректно определять тип открываемого файла.

Происходит это по той простой причине, что мы не отправили в браузер корректного поля заголовка Content-Type header. Ведь по умолчанию стоит тип ‘text/html‘, вот поэтому браузеры неправильно определили тип файла — вместо изображения вывели на экран текстовый файл. Что из этого получилось, вы уже видели.

Для решения этой проблемы необходимо задать формат данных явно с помощью поля заголовка Content-Type:

// Открываем изображение
$image = open_image('test_jpg.jpg'); 
// Некоторые манипуляции с изображением (изменение размера, цвета и т.п.) 
// Отправляем поле заголовкаheader ('Content-Type: image/jpeg'); 
// Выводим изображение на экранimagejpeg($image); 
function open_image ($file) {
    // полный листинг функции приведен выше
}

Если вы теперь запустите этот скрипт, то увидите, что изображение отображается корректно во всех браузерах. Также есть возможность сохранить картинку на жесткий диск. Еще можно явно задать имя сохраняемой картинки — для этого используется второй аргумент в функции imagejpeg().

Вот как это выглядит:

// Открываем изображение
$image = open_image('test_jpg.jpg');
if ($image === false) {
 die ('Не удается открыть изображение'); 
} 
// Некоторые манипуляции с изображением (изменение размера, цвета и т.п.) 
// Сохранение изображения в той же папке, что и файл test_jpg.jpg
imagejpeg($image, 'my_image.jpg'); 
function open_image ($file) {
    // полный листинг функции приведен выше
}

В результате выполнения скрипта в вашей папке появится файл my_image.jpg. Поскольку в данном случае мы не выводим изображение на дисплей, то и отправлять явно поле заголовка не обязательно.

Вот еще несколько практических примеров использования библиотеки GD library

Рисование полигонов

С помощью функции imagepolygon() можно создавать полигон (многоугольник).

Описание функции

bool imagepolygon (resource image, array points, int num_points, int color)

imagepolygon() создаёт многоугольник на изображении.

image — указывает на изображение, на котором будет нарисован многоугольник

points — это PHP-массив, содержащий вершины полигона, т.е. points[0] = x0, points[1] = y0, points[2] = x1, points[3] = y1, и т.д.

num_points это общее количество вершин.

color — цвет линий многоугольника, задается функцией imagecolorallocate()

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

Вот сам скрипт:

// создаем холст (чистое изображение)
$image = imagecreate(200, 110); 
// цвет фона
$bg = imagecolorallocate($image, 10, 129, 239); 
// цвет линий
$color = imagecolorallocate($image, 255, 255, 255); 
// рисуем многоугольник (полигон)
imagepolygon($image,array (0, 0,100, 90,180, 100,100,10 ),4,$color);
// выводим изображение на экран
header("Content-type: image/gif");
imagegif($image);

Поворот изображения

Используя библиотеку GD Library с помощью функции imagerotate () можно вращать изображение на заданный угол.

Описание функции

resource imagerotate (resource src_im, float angle, int bgd_color)

Осуществляет поворот изображение src_im на угол angle.

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

// Изображение, которое мы будем переворачивать
$image = 'ice_age.jpg'; 
// На какое количество градусов
// (положительные числа - против часовой, отрицательные - против нее)
$degrees = 90; 
// Указываем поле заголовка для типа файлов .jpg,
// если используются другие типы заменяем на png или gif
header('Content-type: image/jpeg'); 
// Создаем холст (пустую картинку)
$source = imagecreatefromjpeg($image); 
// Поворачиваем изображение
$rotate = imagerotate($source, $degrees, 0); 
// Выводим повернутое изображение в браузер
imagejpeg($rotate);

Конвертирование изображения в серый цвет (полутоновое)

Немного теории, чтобы были понятными алгоритмы преобразования изображения из цветного (RGB) в серое (YIQ):

Цветовая модель – Способ распределения и задания цвета в конкретной программе или системе. Наиболее используемые в компьютерной графике и видео цветовые модели: RGB (красный, зелёный, синий), YUV (Y – сигнал, определяющий полутон или яркость, U и V – сигналы, определяющие цветность) и YIQ (цветовая модель, применяемая в видеосигналах NTSC).

YIQ цветовая модель (YIQ color model)

Каждый цвет в модели YIQ задается с помощью установки значений трех параметров: Y — интенсивности (luminance,) и двух цветностей I и Q, позволяющих совместно управлять созданием цвета с помощью зеленого, синего, желтого и пурпурного цветов.

Так установка минимальных значений I и Q (0, 0) приводит к получению зеленого цвета, а установка их максимальных значений (255,255) дает пурпурный цвет. Каждая из компонент YIQ модели может изменяться в диапазоне от 0 до 255.

Подготавливаем холст

Первая часть скрипта выполняет функции подготовки изображения к конвертированию цвета:

//Файл, который мы будет конвертировать
$file = 'cat_1.jpg'; 
// Поле заголовка
header('Content-type: image/jpeg'); 
// Размеры изображения
list($width, $height) = getimagesize($file); 
// Создаем изображение JPEG из файла
$source = imagecreatefromjpeg($file); 
// Создаем холст
$bwimage= imagecreate($width, $height); 
// Создаем 256-цветную палитру
for ($c=0;$c<256;$c++){
  $palette[$c] = imagecolorallocate($bwimage,$c,$c,$c);
} 
//Функция yiq для преобразования в серый цвет
function yiq($r,$g,$b){
  return (($r*0.299)+($g*0.587)+($b*0.114));
}

Генерация черно-белой картинки

В коде присутствует два цикла for для обхода всего изображения по координатам Y и X.

С помощью функции imagecolorat () возвращаем индекс цвета пикселя в цветовой палитре, который находится на изображении (переменная $source) в точке с координатамиxy (переменные $x$y).

Далее идет вызов функции yiq() для преобразования цветов изображения в серые тона. В самом конце используется функция imagesetpixel() для рисования пикселя заданным цветом в точке с координатами xy на изображении image.

// Считываем оригинальное изображение по пикселям
for ($y=0;$y<$height;$y++){
  for ($x=0;$x<$width;$x++){
    $rgb = imagecolorat($source,$x,$y);
    $r = ($rgb >> 16) & 0xFF;
    $g = ($rgb >> 8) & 0xFF;
    $b = $rgb & 0xFF; 
    // Используем функцию yiq для изменения rgb-палитры
    // нашего цветного изображения, чтобы преобразовать его в серое
    $gs = yiq($r,$g,$b);
    imagesetpixel($bwimage,$x,$y,$palette[$gs]);
  }
} 
// Выводим в браузер преобразованное изображение
imagejpeg($bwimage);

И на последок  сжатие изображений

 

<?
function compress($path,$file)
{
$ext = strtolower(pathinfo($file, PATHINFO_EXTENSION));
//error_reporting(0);
ini_set('memory_limit', '512M');
if($ext=='jpg' || $ext=='jpeg'|| $ext=='png')
{
 $sfile=$path."s_".$file;
 $lfile=$path."l_".$file;
 $fullfile=$path.$file;
 if(!($im = imagecreatefromjpeg($fullfile)))
 $im = imagecreatefrompng($fullfile);
 if($im)
 {
 $iw = imagesx($im); $ih = imagesy($im);
 $k = 650 / $iw;
 if($k>1)$k=1;
 $sx = floor($iw * $k); $sy = floor($ih * $k);
 $im_m = imagecreatetruecolor($sx, $sy);
 imagealphablending( $im_m, false );
 imagesavealpha( $im_m, true );
 $transparent = imagecolorallocatealpha($im_m, 255, 255, 255,255);

 imagefilledrectangle($im_m, 0, 0, $sx, $sy, $transparent); 
 imagecopyresampled($im_m, $im, 0, 0, 0, 0, $sx, $sy, $iw, $ih);
 $r_l = imagejpeg($im_m,$lfile);

 $iw = imagesx($im); $ih = imagesy($im);
 $k = 100 / $iw;
 if($k>1)$k=1;
 $sx = floor($iw * $k); $sy = floor($ih * $k);
 $im_m = imagecreatetruecolor($sx, $sy);
 imagealphablending( $im_m, false );
 imagesavealpha( $im_m, true );
 $transparent = imagecolorallocatealpha($im_m, 255, 255, 255, 127);
 imagefilledrectangle($im_m, 0, 0, $sx, $sy, $transparent); 
 imagecopyresampled($im_m, $im, 0, 0, 0, 0, $sx, $sy, $iw, $ih);
 $r_s = imagejpeg($im_m,$sfile);
 }
else
 {
 copy($fullfile, $lfile);
 copy($fullfile, $sfile);
 }
}
error_reporting(1);
}
?>

ссылка для закачки проекта. http://ikurs.kz/alexey.zip

 

Раздел: PHP