Главная > PHP > Масштабирование изображений на PHP и GD

Масштабирование изображений на PHP и GD

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

Самая распространенная задача, при работе с изображениями — создание уменьшенной копии. Например для создания аватарок или превью фотографий и т.д. Напишем для этой задачи небольшой класс.

Сначала определим задачу: Во первых нам нужен класс, который будет работать с 3-мя популярными форматами изображений: jpeg, gif и png. Во вторых, при масштабировании должно сохраняться соотношение сторон.

  1. /**
  2.  * Класс масштабирования изображении
  3.  */
  4. class image{
  5.     private $file;              //Путь к файлу с исходным изображением
  6.     private $image;             //Исходное изображение
  7.     private $image_new=false;   //Изображение после масштабирования
  8.  
  9.     /**
  10.      * Загрузка файла для обработки
  11.      *
  12.      * @param string $file путь к файлу
  13.      */
  14.     public function __construct($file)
  15.     {
  16.         if(!file_exists($file)) return false;
  17.  
  18.         //Получаем информацию о файле
  19.         list($width, $height, $image_type) = getimagesize($file);
  20.  
  21.         //Создаем изображение из файла
  22.         switch ($image_type)
  23.         {
  24.             case 1: $this->image = imagecreatefromgif($file); break;
  25.             case 2: $this->image = imagecreatefromjpeg($file);  break;
  26.             case 3: $this->image = imagecreatefrompng($file); break;
  27.             default: return '';  break;
  28.         }
  29.         $this->file=$file;
  30.     }
  31.  
  32.     /**
  33.      * Масштабирует исходное изображение
  34.      *
  35.      * @param int $W Ширина
  36.      * @param int $H Высота
  37.      */
  38.     public function resize($W, $H)
  39.     {
  40.         $this->image_new=false;
  41.  
  42.         $X=ImageSX($this->image);
  43.         $Y=ImageSY($this->image);
  44.  
  45.  
  46.         $H_NEW=$Y;
  47.         $W_NEW=$X;
  48.  
  49.         if($X>$W){
  50.             $W_NEW=$W;
  51.             $H_NEW=$W*$Y/$X;
  52.         }
  53.  
  54.         if($H_NEW>$H){
  55.             $H_NEW=$H;
  56.             $W_NEW=$H*$X/$Y;
  57.         }
  58.  
  59.         $H=(int)$H_NEW;
  60.         $W=(int)$W_NEW;
  61.  
  62.  
  63.         $this->image_new=imagecreatetruecolor($W,$H);
  64.         imagecopyresampled($this->image_new,$this->image,0,0,0,0,$W,$H,$X,$Y);
  65.  
  66.     }
  67.  
  68.  
  69.     /**
  70.      * Сохранение файла
  71.      *
  72.      * @param string $file Путь к файлу (если не указан, записывает в исходный)
  73.      * @param int $qualiti Качество сжатие JPEG
  74.      */
  75.     public function save($file=false, $qualiti=90)
  76.     {
  77.         if(!$file || $file==$this->file) {
  78.             $file=$this->file;
  79.             if(!$this->image_new) return true;
  80.             else ImageJpeg($this->image_new, $file, $qualiti);
  81.         }else{
  82.             if(!$this->image_new) copy($this->file, $file);
  83.             else ImageJpeg($this->image_new, $file, $qualiti);
  84.         }
  85.     }
  86. }

И пример использования класса, создадим из файла myImage.jpeg две уменьшеные копии:

  1. $image = new image('upload/myImage.jpeg');
  2. $image->resize(20, 20);
  3. $image->save('upload/mySmallImage.jpeg');
  4. $image->resize(400, 300);
  5. $image->save('upload/myBigImage.jpeg');
Categories: PHP Tags: ,
Комментарии (11) Уведомления (0) Написать комментарий Уведомление
  1. VK
    15 Июнь 2009 в 17:41 | #1
    Ответить | Цитата

    А почему сохраняем то только в jpg? По идее надо если исходная картинка gif, то сохранять в gif, если png — соответственно png. А тут получается независимо от исходной картинки на выходе имеем jpg.
    И еще интересная отдельная тема — сохранение альфа-канала (прозрачности/полупрозрачности в png), а то я сталкивался — если просто
    imagecreatefrompng
    imagecreatetruecolor
    imagecopyresampled
    imagepng
    то прозрачный фон превращается в непрозрачный

  2. Roman
    15 Июнь 2009 в 18:23 | #2
    Ответить | Цитата

    @VK
    JPG на выходе — это дело вкуса. По мне, лучше и иметь на сервере все изображения в одном формате, это упрощает их массовую обработку (если потребуется).
    А вот насчет альфа-канала в PNG — тема действительно интересная, спасибо Вам за нее. На досуге попробую найти решение.

  3. punkWJ
    9 Июль 2009 в 09:47 | #3
    Ответить | Цитата

    А решение есть и очень простое, один из цветов делаем прозрачным:

    Создание нового цвета и занесение его в палитру рисунка.
    $white = imagecolorallocate($im, 255, 255, 255);
    //$im — идентификатор изображения, заданный функцией imageCreate()

    Определение цвета прозрачности.

    imageColorTransparent($im, 255, 255, 255)

    осталось вывести изображение…
    Вот и всё!!!

    з.ы.: если где то ошибся, прошу поправить)))

  4. Денис
    12 Ноябрь 2009 в 19:15 | #4
    Ответить | Цитата

    Спасибо огромное автору статьи — с первого раза все заработало, аж не ожидал, обычно приходится любой код, добытый таким образом править и править :)

    А вот, как я дополнил страницу загрузки изображения (форму не буду публиковать — все легко) которым пользуюсь я (если интересно):

    resize(400, 400);
    $image->save($uploadfile);
    /*вызываем успешно размещенную картинку, чтобы показать результат обработки */
    echo «Картинка успешно сжата. Вот она, собсно:»;
    // [-] МАСШТАБИРОВАНИЕ ЗАГРУЖЕННОГО ИЗОБРАЖЕНИЯ
    ?>

    Резюмирую: конкретно данный скрипт позволяет загрузить максимально дозволенного настройками PHP на сервере размера оригинал картинки в папку img, выставить на нее права доступа 777, затем масштабирует картинку до размера одной из сторон не более 400 пикселей и перезаписывает исходный файл в директории img. И еще — запрещает загрузку файлов с кодом PHP (некая пассивная безопасность).

    Если кому оказалось полезным — мне очень приятно. В случае чего, мастера, кидайте ботинки, люблю конструктивную критику — я ведь не волшебник, а только учусь :)

  5. Денис
    12 Ноябрь 2009 в 19:17 | #5
    Ответить | Цитата

    Ну вот, сидел, набирал, а код-то и не вставился полностью… Ну, если кому интересно, пишите сюда, поделюсь…

  6. Roman
    12 Ноябрь 2009 в 20:00 | #6
    Ответить | Цитата

    @Денис
    Рад, что моя статья пригодилась.
    А чтобы вставить код в текст комментария, нужно заменить знаки

  7. Денис
    13 Ноябрь 2009 в 15:58 | #7
    Ответить | Цитата

    Упс, спасибо за напоминание :)Итак, публикуюсь, и помоги мне великий WordPress на этот раз:

    <?php
    $subname = «Префикс к имени файла»;
    // ТУТ ВСТАВЛЯЕМ КЛАСС, ПРЕДЛОЖЕННЫЙ АВТОРОМ
    // ДАЛЕЕ ОСТАЛЬНОЙ КОД
    /* тут запрещаем к загрузке файлы, содержащие php */
    $blacklist = array(«.php», «.phtml», «.php3″, «.php4″);
    foreach ($blacklist as $item)
    {
    if(preg_match(«/$item\$/i», $_FILES['userfile']['name']))
    {
    echo «Файлы, содержащие php-код запрещены к загрузке\n»;
    exit;
    }
    }
    /* укажем полный путь к директории загрузки (на примере Мастерхоста) :)Причем права на директорию нужно выставить 775 */
    $uploaddir = ‘/home/uXXXXX/домен.ru/www/img/’;
    /* извлекаем расширение файла */
    $file_ext = strrchr(basename($_FILES['userfile']['name']), ‘.’);
    /* собственно сам процесс загрузки через временную директорию домена */
    $uploadfile = $uploaddir . $subname . $file_ext;
    if (move_uploaded_file($_FILES['userfile']['tmp_name'], $uploadfile))
    {
    chmod($uploadfile,0777); /* выставляем права на картинку (можно и свои) */
    echo «Изображение успешно загружено.\n»;
    // [+] МАСШТАБИРОВАНИЕ ЗАГРУЖЕННОГО ИЗОБРАЖЕНИЯ (побитый мной скрипт автора)
    $image = new image($uploadfile);
    $image->resize(400, 400);
    $image->save($uploadfile);
    /*вызываем успешно размещенную картинку, чтобы показать результат обработки */
    echo «Картинка успешно сжата. Вот она, собсно:<br><br><img src=\»img/» . $subname . $file_ext . «\»>»;
    // [-] МАСШТАБИРОВАНИЕ ЗАГРУЖЕННОГО ИЗОБРАЖЕНИЯ
    ?>

  8. Денис
    13 Ноябрь 2009 в 16:00 | #8
    Ответить | Цитата

    Блин, Роман, прошу прощения, но предыдущий пост удаляй, что-то я невнимателен:

    $subname = «Префикс к имени файла»;
    // ТУТ ВСТАВЛЯЕМ КЛАСС, ПРЕДЛОЖЕННЫЙ АВТОРОМ
    // ДАЛЕЕ ОСТАЛЬНОЙ КОД
    /* тут запрещаем к загрузке файлы, содержащие php */
    $blacklist = array(«.php», «.phtml», «.php3″, «.php4″);
    foreach ($blacklist as $item)
    {
    if(preg_match(«/$item\$/i», $_FILES['userfile']['name']))
    {
    echo «Файлы, содержащие php-код запрещены к загрузке\n»;
    exit;
    }
    }
    /* укажем полный путь к директории загрузки (на примере Мастерхоста) :)Причем права на директорию нужно выставить 775 */
    $uploaddir = ‘/home/uXXXXX/домен.ru/www/img/’;
    /* извлекаем расширение файла */
    $file_ext = strrchr(basename($_FILES['userfile']['name']), ‘.’);
    /* собственно сам процесс загрузки через временную директорию домена */
    $uploadfile = $uploaddir . $subname . $file_ext;
    if (move_uploaded_file($_FILES['userfile']['tmp_name'], $uploadfile))
    {
    chmod($uploadfile,0777); /* выставляем права на картинку (можно и свои) */
    echo «Изображение успешно загружено.\n»;
    // [+] МАСШТАБИРОВАНИЕ ЗАГРУЖЕННОГО ИЗОБРАЖЕНИЯ (побитый мной скрипт автора)
    $image = new image($uploadfile);
    $image->resize(400, 400);
    $image->save($uploadfile);
    /*вызываем успешно размещенную картинку, чтобы показать результат обработки */
    echo «Картинка успешно сжата. Вот она, собсно:

    »;
    // [-] МАСШТАБИРОВАНИЕ ЗАГРУЖЕННОГО ИЗОБРАЖЕНИЯ
    ?>

  9. Stronzo
    22 Ноябрь 2009 в 07:04 | #9
    Ответить | Цитата

    Вечер добрый. У меня есть вопрос по поводу контекстной рекламы у Вас на сайте. Вам не доводилось сталкиваться со случаями блокирования аккаунта администрацией гугла за как бы «накрутку»? Как защитить себя в этом случае?

  10. 27 Ноябрь 2009 в 16:29 | #10
    Ответить | Цитата

    @Stronzo
    К счастью, с такой проблемой не сталкивался.

  11. Resizer
    30 Апрель 2012 в 01:34 | #11
    Ответить | Цитата

    Есть хороший небольшой скрипт в тему — http://www.image-resizer.ru
    Уменьшает по ширине и высоте, обрезает лишнее с краёв, приводит к одному размеру, кеширует… Рекомендую!

  1. Пока что нет уведомлений.