• Главная»
  • Уроки»
  • PHP»
  • Динамическое создание миниатюр изображений с помощью PHP

Динамическое создание миниатюр изображений с помощью PHP

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

 

Код

Мы будем использовать PHP для динамического создания миниатюр изображений. В скрипте будут обрабатываться изображения основных форматов: png, jpg, gif.

Укажем нужный размер миниатюры.

$nw = 150;    // Ширина миниатюр
$nh = 100;    // Высота миниатюр

Теперь укажем скрипту исходный файл и файл с результатом работы.

$source = "images/test/test.jpg";    	// Исходный файл 
$dest = "images/test/thumb/test.jpg";   // Файл с результатом работы

Следующая часть кода будет автоматически отделять расширение файла. Мы используем функцию PHP explode для разделения имени файла на части между точками, а затем используем функцию count для определения последней части исходной строки, которая является расширением файла.

$stype = explode(".", $source);
$stype = $stype[count($stype)-1];

Затем получаем размер оригинального изображения.

$size = getimagesize($source);
$w = $size[0];    // Ширина изображения 
$h = $size[1];    // Высота изображения

Затем используем нужную функцию PHP для работы с определенным форматом изображения:

switch($stype) {
    case 'gif':
    $simg = imagecreatefromgif($source);
    break;
    case 'jpg':
    $simg = imagecreatefromjpeg($source);
    break;
    case 'png':
    $simg = imagecreatefrompng($source);
    break;
}

И, наконец, создаем миниатюру и помещаем ее в указанную папку.

$dimg = imagecreatetruecolor($nw, $nh);
$wm = $w/$nw;
$hm = $h/$nh;
$h_height = $nh/2;
$w_height = $nw/2;
 
if($w > $h) {
    $adjusted_width = $w / $hm;
    $half_width = $adjusted_width / 2;
    $int_width = $half_width - $w_height;
    imagecopyresampled($dimg,$simg,-$int_width,0,0,0,$adjusted_width,$nh,$w,$h);
} elseif(($w < $h) || ($w == $h)) {     
		$adjusted_height = $h / $wm;
		$half_height = $adjusted_height / 2;
		$int_height = $half_height - $h_height;
		imagecopyresampled($dimg,$simg,0,-$int_height,0,0,$nw,$adjusted_height,$w,$h);
	 } else {     
		imagecopyresampled($dimg,$simg,0,0,0,0,$nw,$nh,$w,$h); 
	 }     
imagejpeg($dimg,$dest,100);

В результате выполнения скрипта мы получим готовую миниатюру в указанном файле.

 

Вариант скрипта

Представленный ниже скрипт находит все изображения в указанной папке и создает миниатюры для них, помещая в нужный каталог.

$thumb_directory =  "images/thumb";    	//Папка для миниатюр 
$orig_directory = "images/full";    	//Папка для полноразмерных изображений 
 
$dir_handle = @opendir($orig_directory); 	//Открываем папку с полноразмерными изображениями 
if ($dir_handle > 1){ 				//Проверяем, что папка открыта и в ней есть файлы
 
$allowed_types=array('jpg','jpeg','gif','png'); // Список обрабатываемых расширений
$file_parts=array();
$ext='';
$title='';
$i=0;
 
while ($file = @readdir($dir_handle))
{
    /* Пропускаем системные файлы: */
    if($file=='.' || $file == '..') continue;
 
    $file_parts = explode('.',$file);    	//Разделяем имя файла на части 
    $ext = strtolower(array_pop($file_parts));
 
    /* Используем имя файла (без расширения) как заголовок изображения: */
    $title = implode('.',$file_parts);
    $title = htmlspecialchars($title);
 
    /* Если расширение входит в список обрабатываемых: */
    if(in_array($ext,$allowed_types))
    {
 
        /* Если вы планируете хранить изображения в базе данных, вставьте код для запроса здесь */
 
        /* Далее следует код, который разбирался в уроке */
        /* Выводим каждое изображение: */
 
        $nw = 150;
        $nh = 100;
        $source = $orig_directory . $file;
        $stype = explode(".", $source);
        $stype = $stype[count($stype)-1];
        $dest = $thumb_directory . $file;
 
        $size = getimagesize($source);
        $w = $size[0];
        $h = $size[1];
 
        switch($stype) {
            case 'gif':
                $simg = imagecreatefromgif($source);
                break;
            case 'jpg':
                $simg = imagecreatefromjpeg($source);
                break;
            case 'png':
                $simg = imagecreatefrompng($source);
                break;
        }
 
        $dimg = imagecreatetruecolor($nw, $nh);
        $wm = $w/$nw;
        $hm = $h/$nh;
        $h_height = $nh/2;
        $w_height = $nw/2;
 
        if($w> $h) {
            $adjusted_width = $w / $hm;
            $half_width = $adjusted_width / 2;
            $int_width = $half_width - $w_height;
            imagecopyresampled($dimg,$simg,-$int_width,0,0,0,$adjusted_width,$nh,$w,$h);
        } elseif(($w <$h) || ($w == $h)) {
            $adjusted_height = $h / $wm;
            $half_height = $adjusted_height / 2;
            $int_height = $half_height - $h_height;
 
            imagecopyresampled($dimg,$simg,0,-$int_height,0,0,$nw,$adjusted_height,$w,$h);
        } else {
            imagecopyresampled($dimg,$simg,0,0,0,0,$nw,$nh,$w,$h);
        }
            imagejpeg($dimg,$dest,100);
        }
}
 
/* Закрываем папку */
@closedir($dir_handle);
 
}

 

Заключение

С помощью такого скрипта можно существенно изменить стиль работы с изображениями при создании проекта. Ну а для тех, кто считает, что создание велосипеда - дело неблагодарное, есть готовые решения для создания миниатюр: Timthumb и PHPthumb (Описание по ссылкам на английском языке. Если вы хотите, чтобы мы сделали урок по использованию данных скриптов - пишите в комментариях).

Данный урок подготовлен для вас командой сайта ruseller.com
Источник урока: www.onextrapixel.com/2011/02/25/creating-dynamic-image-thumbnails-using-php/
Перевел: Сергей Фастунов
Урок создан: 1 Марта 2011
Просмотров: 47349
Правила перепечатки


5 последних уроков рубрики "PHP"

  • Фильтрация данных с помощью zend-filter

    Когда речь идёт о безопасности веб-сайта, то фраза "фильтруйте всё, экранируйте всё" всегда будет актуальна. Сегодня поговорим о фильтрации данных.

  • Контекстное экранирование с помощью zend-escaper

    Обеспечение безопасности веб-сайта — это не только защита от SQL инъекций, но и протекция от межсайтового скриптинга (XSS), межсайтовой подделки запросов (CSRF) и от других видов атак. В частности, вам нужно очень осторожно подходить к формированию HTML, CSS и JavaScript кода.

  • Подключение Zend модулей к Expressive

    Expressive 2 поддерживает возможность подключения других ZF компонент по специальной схеме. Не всем нравится данное решение. В этой статье мы расскажем как улучшили процесс подключение нескольких модулей.

  • Совет: отправка информации в Google Analytics через API

    Предположим, что вам необходимо отправить какую-то информацию в Google Analytics из серверного скрипта. Как это сделать. Ответ в этой заметке.

  • Подборка PHP песочниц

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

или авторизуйтесь, чтобы добавлять комментарии, оценивать уроки и сохранять их в личном кабинете
  • 1 Марта 2011 13:27
    Mahay
    А можно демо выложить, посмотреть как это все выглядит!
    • 15 Февраля 2014 23:21
      anon__plus
      __ljbivbbbbhbhbbbhb___
  • 1 Марта 2011 13:46
    Mustec
    Вот на словах не передать, всю ночь мучился, просто ужасно мучился, и тут блин вот тебе. Как всегда. Спасибо за статейку
  • 1 Марта 2011 14:18
    zxspectr
    Спасибо! Полезная статья. Ещё бы сделали статью, как при загрузке flv файла вытянуть из него кадр и сохранить в JPEG
    • 1 Марта 2011 14:46
      RealVect0r
      Да, это было бы круто
  • 1 Марта 2011 14:52
    Mustec
    Ещё было бы круто посмотреть как сделать так, чтобы файлы загружались поочередно. Дело в том что если таким образом загружать 50 фотографий сервер отвалится. Каким нибудь образом чтобы поочередно каждый файл обрабатывался, а не все сразу. Ни кто не знает как?
    • 1 Марта 2011 19:14
      eko24ive
      Сделай очередь.
      • 1 Марта 2011 21:41
        Fizik
        foreach тебе в помощь....
        • 2 Марта 2011 22:49
          eko24ive
          Вот и я об этом.
          • 3 Марта 2011 16:13
            Mustec
            Спасибо
        • 16 Мая 2016 23:23
          alexandrknyazev13071
          НЕ подскажите, куда здесь вставлять цикл foreach? Вроде и так есть while
  • 1 Марта 2011 19:40
    MopuC
    К комментаторам выше: У вас это трудности вызывает? Вы вбейте в гугл.
  • 6 Марта 2011 13:30
    gogita1970
    как сделать так, што фон изображений был не черным а тот который мы укажем?
  • 6 Марта 2011 19:56
    Good
    Не плохо было бы еще добавить настройки ширины и высоты для full size изображений, а также указать качество изображений (0...100), также можно было бы добавить чек для добавления резкости изображения, но желательно чтобы чек стоял для каждой фотки ,т.е. требуется пред загрузчик. А с таким набором можно уже делать качественные галереи =)
  • 22 Апреля 2011 23:55
    mask
    А как же asido?
  • 25 Июня 2011 19:54
    mayor
    ПОМОГИТЕ!!! Как на выходе сделать чтобы большая картинка была с одним именем, а миниатюра с другим. Напимер img.jpg и img_mini.jpg (mini_img.jpg)??? Никак не могу разобраться где это подсунуть... Прошу, ответьте! Очень надо.
  • 4 Октября 2011 10:51
    SashaKKKKK
    Эх... И где вы раньше были с этим уроком все пальцы преломал пока написал подобное.... Терь от вас точно не буду отлучатся. Спасибо за уррок. Вопрос не по теме но может есть скрипт для автоматического изменения имени на пхп, Пример Александр сменить на Александра Иван сменить на Ивана. И тп.... Вы не представляете насколько буду благодарен вам. Можете в лычку кинуть ссыль может кто де видел такую штуку.
  • 2 Января 2012 02:57
    TavRoX
    почему то все миниатюрки черные я переделал код только одним убрал все что идет для проверки формата фотки количества фоток в папке и т.д. я даю скрипту сразу нужную фотку при заливке
    • 10 Мая 2012 17:36
      Diamond_cat
      Если у вас вся картинка получается черной, то скорей всего вы не правильно указали путь откуда берется картинка, и скрипт создает просто черную пустую подложку. А вот если у вас получается черный бекфон вместо прозрачности в png и gif то это косяк автора. Автор забыл или намеренно не поставил функции сохраняющие прозрачность при перерисовке изображения
      $dimg = imagecreatetruecolor($nw, $nh);	imageAlphaBlending($dimg, false); //режим смешивания отключить	imageSaveAlpha($dimg, true); //сохранить информацию о прозрачности
      $wm = $w/$nw;
      $hm = $h/$nh;
      Всего две строки и прозрачность будет сохраняться
  • 29 Августа 2012 12:34
    fsv123
    Не знаю что уже делать, почему на локальном работает а на удаленном хостинге не пашет. В чём может быть проблема?
  • 6 Октября 2012 04:08
    Drugan007
    Dmin добрый вечер! Я новечек в сайтостроении, этот скрипт самый понятный из того что я нашол. Только у меня возникла проблема , как его применять и куда вставлять????? Помогите разобраться!
  • 9 Февраля 2013 14:26
    nekal_san
    Спасибо! Достаточно просто описано. Теперь создаю сразу оригинал и миниатюру при апплоаде файла на сервер. Очень удобно. Еще раз спасибо.
  • 2 Марта 2013 18:41
    show_crazy
    Вертикальную обрезает - супер, а горизонтальную - оставляет по бокам вертикальные черные полосы. В чем ошибка?
  • 30 Марта 2013 22:37
    broker2717
    Спасибо за код, все отлично работает. Я только начинаю знакомство с PHP, а Вы бы не могли написать хотя бы пример кода который нужно написать вот сюда: "Если вы планируете хранить изображения в базе данных, вставьте код для запроса здесь" чтобы занести имена миниатюр в базу, и чтобы они совпадали при выводе на страницу (фото галерею) с оригиналом. Ну т.е. у меня есть на сайте фото галерея рабочая, при нажатии на миниатюру открывается оригинал, дак мне надо чтобы все так и работало а имена файлов естественно брались из базы.
  • 5 Апреля 2013 15:51
    show_crazy
    Вертикальную обрезает - супер, а горизонтальную - оставляет по бокам вертикальные черные полосы. В чем ошибка? Помогите с решением данной проблемы
  • 11 Июля 2013 10:14
    Invest
    А можно демо выложить?? ochen polezna menya,
  • 11 Сентября 2013 10:47
    colors
    Двойка автору по безопасности - определять формат файла по расширению это ужасно. Так можно загрузить на сервер все что угодно. Определяйте тип по содержимому и присваивайте нужное расширение сами. Хотя и картинка, отдающая реальный тип картинки - тоже может содержать вирус, но это уже другой вопрос..
    • 27 Марта 2016 21:31
      Хакер_Ботаник
      Ну думаю что тут безопасность рассматривается. Ну залили вы на сайт файл с PHP кодом имеющий расширение jpg а толку? Если на сервере не разрешено исполнять код в jpg формата, то чего бояться? А на тех серверах где это разрешено (к примеру для генерации каких либо графиков через php на лету) то там следят за этим надлежащим образом. В любом случае, ток делать нельзя!
  • 16 Мая 2016 23:24
    alexandrknyazev13071
    Не подскажите, что сделать чтобы код не сильно нагружал сервер ( при попытке загрузить 100 изображений выдал ошибку)
  • 7 Октября 2016 15:55
    zingerx1
    лучше так:
    $dimg = imagecreatetruecolor($nw, $nh);
    if (($w/$h) >= ($nw/$nh)) {	$ns = $h/$nh;
    }
    else {	$ns = $w/$nw;
    }
    $dst_w = $w/$ns;
    $dst_h = $h/$ns;
    $dst_x = ($nw - $dst_w)/2;
    $dst_y = ($nh - $dst_h)/2;
    imagecopyresampled($dimg, $simg, $dst_x, $dst_y, 0, 0, $dst_w, $dst_h, $w, $h);
    imagejpeg($dimg,$dest,100);
    
  • 7 Октября 2016 15:56
    zingerx1
    чем так:
    $dimg = imagecreatetruecolor($nw, $nh);
    $wm = $w/$nw;
    $hm = $h/$nh;
    $h_height = $nh/2;
    $w_height = $nw/2;
    if($w > $h) { $adjusted_width = $w / $hm; $half_width = $adjusted_width / 2; $int_width = $half_width - $w_height; imagecopyresampled($dimg,$simg,-$int_width,0,0,0,$adjusted_width,$nh,$w,$h);
    } elseif(($w < $h) || ($w == $h)) {	$adjusted_height = $h / $wm;	$half_height = $adjusted_height / 2;	$int_height = $half_height - $h_height;	imagecopyresampled($dimg,$simg,0,-$int_height,0,0,$nw,$adjusted_height,$w,$h);	&nbsp;} else {	imagecopyresampled($dimg,$simg,0,0,0,0,$nw,$nh,$w,$h); }
    imagejpeg($dimg,$dest,100);
    
    к тому же, исправлена ваша ошибка когда относительная ширина миниатюры больше чем относительная ширина исходного изображения например 800:400 -> 200:50 в Вашем коде на выходе получается изображение с черными полосками по бокам
^ Наверх ^