Говорят, что создание сайта - очень длительный и трудоемкий процесс. Мы скажем - НЕТ! Ведь с новыми технологиями, такими как HTML5, CSS3, PHP и MySql можно быстро и легко научиться создавать сайты любой сложности.
Два сумасшедших веб-мастера покажут где что лежит и как этим пользоваться.
Авторизация
Новый
Забыл
Пожалуйста, заполните поля выше. Это нужно сделать обязательно, иначе ничего не получится.
PHP Статейки /

Изменение изображений с помощью PHP

  • Среда, 16 марта 2012, 21:47 |
  • Автор: fiamma |
  • Просмотров: 7387 |
  • Комментарии: 10 |
  • В закладки:
Здравствуйте, дорогие друзья. Сегодня я покажу как быстро и легко можно написать класс, с помощью которого можно изменять изображения. Данный класс пригодится практически в каждом проекте, который вы будете делать в будущем. Я постараюсь создать класс, который будет не только соответствовать всем требованиям, но и будет легко расширяемым.

Введение

Для начала мы должны сформулировать главные требования, предъявляемые к нашему классу:
1. Класс должен быть легок в использовании
2. Не зависеть от формата (то есть открывать, изменять и сохранять разные форматы изображений)
3. Необходимо реализовать "умный" алгоритм изменения изображений. (При котором искажения изображения будет минимальным.)

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

Шаг 1. Подготовка

Начнем с простого. Создаем в нашей рабочей папке два файла, один из которых называем index.php, а другой - resize-class.php.

Изменение изображений с помощью PHP


Шаг 2. Подготовка

Для того, чтобы увидеть как на практике мы будем изменять изображения давайте откроем файл index.php и добавим туда сл. строки кода.
Между строк: спонсором данного поста является техцентр "Van Auto", который находиться по адресу Москва, ул. Сосинская, д. 43, (м. Волгоградский проспект), там я и нашел лобовое стекло на audi 100, в тот момент когда мне это было нужно больше всего.
Как вы видите, данный код - простейшее использование нашего класса. Мы открываем исходное изображение, затем указываем необходимые параметры (ширину, высоту, тип выходного изображения). Затем сохраняем изображение в нужном нам формате с указанным качеством. Сохраняем данный код в index.php и закрываем файл.

// *** Подключение класса
include("resize-class.php");

// *** 1) Инициализация\загрузка изображения
$resizeObj = new resize('sample.jpg');

// *** 2) Изменение размера изображения (параметры: exact, portrait, landscape, auto, crop)
$resizeObj -> resizeImage(150, 100, 'crop');

// *** 3) Сохранение изображения
$resizeObj -> saveImage('sample-resized.gif', 100);


Шаг 3. Создаем основу для нашего класса

Суть Объектно-Ориентированного программирования (ООП) заключается в том, что один и тот же класс мы можем использовать несколько раз. В случае если необходимо дополнить класс новым функционалом, мы можем запросто его расширить, дописав необходимые строчки кода.

Давайте приступим к непосредственному созданию нашего класса. Откроем файл resize-class.php. Ниже показан пример основы для нашего класса, который мы назовем "resize". Обратите внимание на строку "// *** Class variables" где в дальнейшем будут располагаться переменные, необходимые нашему классу.

Метод _construct, называемый конструктором, это специальный метод класса который вызывается при создании объекта данного класса.
Class resize
{
    // *** Class variables

    public function __construct()
        {

    }
}


При описании данного метода очень важно не упустить двойное подчеркивание.

Шаг 4. Конструктор

Давайте немного изменим наш класс, добавив в него несколько переменных: $image, $width и $height. При открытии изображения мы автоматически задаем эти переменные.
Class resize
{
    // *** Переменные класса
    private $image;
    private $width;
    private $height;

    function __construct($fileName)
    {
        // *** Открываем файл
        $this->image = $this->openImage($fileName);

        // *** Устанавливаем исходные параметры: ширину и высоту.
        $this->width  = imagesx($this->image);
        $this->height = imagesy($this->image);
    }
}

Методы imagesx и imagesy будут использовать часть стандартной библиотеки в PHP - GD. Они возвращают ширину и высоту изображения.

Шаг 5. Открытие изображения

На предыдущем шаге мы вызывали метод openImage, а на этом шаге мы опишем этот метод. В зависимости от типа изображения скрипт должен определять какую функцию библиотеки GD вызвать. Это легко реализовать с помощью конструкции switch.

private function openImage($file)
{
    // *** Определяем extension
    $extension = strtolower(strrchr($file, '.'));

    switch($extension)
    {
        case '.jpg':
        case '.jpeg':
        $img = @imagecreatefromjpeg($file);
            break;
        case '.gif':
            $img = @imagecreatefromgif($file);
            break;
        case '.png':
            $img = @imagecreatefrompng($file);
            break;
        default:
            $img = false;
            break;
    }
    return $img;
}  


Шаг 6. Как изменять изображения

Теперь самое интересное... В этом шаге я всего-лишь объясню то, что мы будем делать в дальнейшем - поэтому НИКАКИХ домашних заданий здесь не будет ;) В следующем шаге мы создадим public-метод который и будет изменять пропорции наших изображений. Нам необходимо сохранять передаваемую высоту и ширину (чтобы потом использовать). На этом моменте давайте остановимся и немного поразмышляем. Но если в нашем распоряжении десятки-сотни не похожих друг на друга изображений по размерам? Если мы хотим изменять размер всех и сразу? Задавая каждому из них строгий размер, мы будем очень сильно их искажать.

In real life существует несколько методом решения данной проблемы:
1. Сохранять пропорции наших изображений
2. Сохранять приближенный размер изображения, удаляя (обрезая) все лишнее

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

Шаг 7. Ресайз изображений. Сделаем это!

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

Мы так же сохраним результат работы функции imagecreatetruecolor в переменной класса. Поэтому добавляем в наш класс строку ‘private $imageResized;’.
Все изменения с изображениями производятся с помощью GD Library. Многие реализуемые нами методы используют функции данной библиотеки.
// *** Добавляем переменную
private $imageResized;

public function resizeImage($newWidth, $newHeight, $option="auto")
        {

            // *** Получаем оптимальную высоту и ширину - базируясь на $option
            $optionArray = $this->getDimensions($newWidth, $newHeight, strtolower($option));

            $optimalWidth  = $optionArray['optimalWidth'];
            $optimalHeight = $optionArray['optimalHeight'];

            // *** Resample - create image canvas of x, y size
            $this->imageResized = imagecreatetruecolor($optimalWidth, $optimalHeight);
            imagecopyresampled($this->imageResized, $this->image, 0, 0, 0, 0, $optimalWidth, $optimalHeight, $this->width, $this->height);

            // *** Если опция включена 'crop'
            if ($option == 'crop') {
                $this->crop($optimalWidth, $optimalHeight, $newWidth, $newHeight);
            }
        }


Шаг 8. "Работа над ошибками"

Пока вы читали предыдущие 7 шагов, я быстренько набросал method-роутер для нашего класса. Вот он:
private function getDimensions($newWidth, $newHeight, $option)
        {

           switch ($option)
            {
                case 'exact':
                    $optimalWidth = $newWidth;
                    $optimalHeight= $newHeight;
                    break;
                case 'portrait':
                    $optimalWidth = $this->getSizeByFixedHeight($newHeight);
                    $optimalHeight= $newHeight;
                    break;
                case 'landscape':
                    $optimalWidth = $newWidth;
                    $optimalHeight= $this->getSizeByFixedWidth($newWidth);
                    break;
                case 'auto':
                    $optionArray = $this->getSizeByAuto($newWidth, $newHeight);
                    $optimalWidth = $optionArray['optimalWidth'];
                    $optimalHeight = $optionArray['optimalHeight'];
                    break;
                case 'crop':
                    $optionArray = $this->getOptimalCrop($newWidth, $newHeight);
                    $optimalWidth = $optionArray['optimalWidth'];
                    $optimalHeight = $optionArray['optimalHeight'];
                    break;
            }
            return array('optimalWidth' => $optimalWidth, 'optimalHeight' => $optimalHeight);
        }


Шаг 9. Оптимальные изменения
Мы уже обсудили что делаю эти 4 метода (те, что описаны выше). Теперь мы может математически высчитать "оптимальные изменения".
private function getSizeByFixedHeight($newHeight)
        {
            $ratio = $this->width / $this->height;
            $newWidth = $newHeight * $ratio;
            return $newWidth;
        }

        private function getSizeByFixedWidth($newWidth)
        {
            $ratio = $this->height / $this->width;
            $newHeight = $newWidth * $ratio;
            return $newHeight;
        }

        private function getSizeByAuto($newWidth, $newHeight)
        {
            if ($this->height < $this->width)
            // *** Изображения изменяется по ширине (landscape)
            {
                $optimalWidth = $newWidth;
                $optimalHeight= $this->getSizeByFixedWidth($newWidth);
            }
            elseif ($this->height > $this->width)
            // *** Изображение изменяется по высоте (portrait)
            {
                $optimalWidth = $this->getSizeByFixedHeight($newHeight);
                $optimalHeight= $newHeight;
            }
            else
            // *** Изображение изменяется в соответствии с указанными значениями
            {
                if ($newHeight < $newWidth) {
                    $optimalWidth = $newWidth;
                    $optimalHeight= $this->getSizeByFixedWidth($newWidth);
                } else if ($newHeight > $newWidth) {
                    $optimalWidth = $this->getSizeByFixedHeight($newHeight);
                    $optimalHeight= $newHeight;
                } else {
                    // *** Sqaure being resized to a square
                    $optimalWidth = $newWidth;
                    $optimalHeight= $newHeight;
                }
            }

            return array('optimalWidth' => $optimalWidth, 'optimalHeight' => $optimalHeight);
        }

        private function getOptimalCrop($newWidth, $newHeight)
        {

            $heightRatio = $this->height / $newHeight;
            $widthRatio  = $this->width /  $newWidth;

            if ($heightRatio < $widthRatio) {
                $optimalRatio = $heightRatio;
            } else {
                $optimalRatio = $widthRatio;
            }

            $optimalHeight = $this->height / $optimalRatio;
            $optimalWidth  = $this->width  / $optimalRatio;

            return array('optimalWidth' => $optimalWidth, 'optimalHeight' => $optimalHeight);
        }


Шаг 10. CROP

Если вам необходимо обрезать изображение, то придется дописать еще один маленький метод.
private function crop($optimalWidth, $optimalHeight, $newWidth, $newHeight)
        {
            // *** Поиск центра изображения - используется для резайза
            $cropStartX = ( $optimalWidth / 2) - ( $newWidth /2 );
            $cropStartY = ( $optimalHeight/ 2) - ( $newHeight/2 );

            $crop = $this->imageResized;
            //imagedestroy($this->imageResized);

            // *** Вырезаем указанный кусочек изображения
            $this->imageResized = imagecreatetruecolor($newWidth , $newHeight);
            imagecopyresampled($this->imageResized, $crop , 0, 0, $cropStartX, $cropStartY, $newWidth, $newHeight , $newWidth, $newHeight);
        }


Шаг 11. Сохранение изображений.

Ну вот в принципе и все. Осталось только сохранить наше изображения. Для этого добавляем еще один метод:
public function saveImage($savePath, $imageQuality="100")
        {
            // *** Get extension
            $extension = strrchr($savePath, '.');
            $extension = strtolower($extension);

            switch($extension)
            {
                case '.jpg':
                case '.jpeg':
                    if (imagetypes() & IMG_JPG) {
                        imagejpeg($this->imageResized, $savePath, $imageQuality);
                    }
                    break;

                case '.gif':
                    if (imagetypes() & IMG_GIF) {
                        imagegif($this->imageResized, $savePath);
                    }
                    break;

                case '.png':
                    // *** Приводим качество из диапазона 0-100 к 0-9
                    $scaleQuality = round(($imageQuality/100) * 9);

                    // *** Инвертируем качество (0 - наилучшее)
                    $invertScaleQuality = 9 - $scaleQuality;

                    if (imagetypes() & IMG_PNG) {
                        imagepng($this->imageResized, $savePath, $invertScaleQuality);
                    }
                    break;

                // ... etc

                default:
                    // *** Не указано - не сохраняем
                    break;
            }

            imagedestroy($this->imageResized);
        }


Исходник кода можно скачать здесь: resize-example.zip [120.96 Kb] (cкачиваний: 514)

Вы всегда можете почитать статью QR-коды с помощью PHP
Оригинал статьи на английском находится здесь.

Для объединения компьютеров Вашего офиса в локальную сеть возьмите сервер для аренды с супербыстрой доставкой - ее осуществление начнется уже через 5 минут после поступления оплаты!
  • Пишет: Jhony (Гости) |
  • Сообщений: 0 |
  • 20 сентября, 16:09
  • #1
Hahaahha. I'm not too bright today. Great post!
супер!!!!! супер!!! Супер скрипть !!!!

супер!!!! супер!!!! Супер скрипть!!!!
Добавить комментарий