Класс для работы с изображениями

Arlevnar

Новичок
Доброго времени суток Уважаемые Коллеги.
Хотел бы прконсультироваться с вами по вопросу функционала одного класса для работы с изображениями.
Я конечно прекрасно понимаю что готовых решений океан. Но всё же в голову пришла мысль создать собственный класс. Вопрос такой.
Есть класс (пока особо не богатый методами) который бы хотелось бы раширить но в голову помимо просто ресайза пока нечего не приходит. Подскажите пожалуйста что бы можно было бы пересмотреть в данном классе и какой бы функционал можно было бы добавить. Собственно говоря вот и сам код:
PHP:
class Image {
    
    public $filename;
    
    public $name;
    
    public $extension;
    
    public $mime;
    
    public $width;
    
    public $height;
    
    public $file_size;
    
    public $ratio;
    
    
    public function __construct($filename)
    {
        if (!self::is_image($filename)) {
            trigger_error('The file is not an image', E_USER_ERROR);
        }
        $this->filename = $filename;
        $this->init_settings();
    }
    
    public static function is_image($filename)
    {
        if (!file_exists($filename)) {
            trigger_error('File "'.$filename.'" not found');
        }
        return count(getimagesize($filename)) ? true : false;     
    }
    
    private function init_settings()
    {
        if (!$this->filename) return;
        $data = getimagesize($this->filename);
        $this->mime   = $data['mime'];
        $this->width  = $data[0];
        $this->height = $data[1];
        $this->file_size = filesize($this->filename);
        $this->extension = strtolower(array_pop(explode(".", basename($this->filename)))); 
        $this->name = preg_replace('/\.'.$this->extension.'$/','',basename($this->filename));
        $this->ratio = $data[0]/$data[1];
    }
    
    public function __set($name, $value)
    {
        trigger_error('The property can not be overridden', E_USER_ERROR);
    }
    
    public function resize_calculation($width, $height)
    {
        if (!isset($width) && !isset($height)) {
            trigger_error('Not indicated the size of the image', E_USER_ERROR);
        }
        elseif ($width && $height == null) {
            $height = $width / $this->ratio;
        }
        elseif ($width == null && $height) {
            $width = $height * $this->ratio; 
        }
        
        return array($width, $height);
    }
    
    public function resize($width, $height, $new_filename=null)
    {
        list($new_w, $new_h) = $this->resize_calculation($width, $height);
        $type = str_replace('image/', '', $this->mime);
        $dst_image = imagecreatetruecolor($new_w, $new_h);
        $src_image = call_user_func('imagecreatefrom'.$type , $this->filename);
        imagecopyresampled($dst_image, $src_image, 0, 0, 0, 0, $new_w, $new_h, $this->width, $this->height);
        if ($new_filename == true) {
            $new_filename = $this->name.'_'.$new_w.'_'.$new_h.'.'.$this->extension;
        }
        elseif($new_filename) {
            if (!is_dir(dirname($new_filename))) {
                trigger_error(dirname($new_filename).' directory not found');
            }
            else {
                $dir = realpath(dirname($new_filename));
                $new_filename = preg_replace('/\.[a-zA-Z]+$/', '', basename($new_filename)).'.'.$this->extension;
                $new_filename = $dir.DIRECTORY_SEPARATOR.$new_filename;
            }
        }
        else {
            header('Content-Type: '.$this->mime);
        }
        call_user_func('image'.$type, $dst_image, $new_filename);
        if (file_exists($new_filename)) {
            return realpath($new_filename);
        }
    }
}
 

rotoZOOM

ACM maniac
Это не класс работы с изображениями, это просто набор функций для работы с файлом, в котором содержится изображение.
Обрамление функций ключевым словом class было сделано, видимо, случайно.
Почитай основы ООП.
 

Arlevnar

Новичок
Это не класс работы с изображениями, это просто набор функций для работы с файлом, в котором содержится изображение.
Обрамление функций ключевым словом class было сделано, видимо, случайно.
Почитай основы ООП.
Обосновать желания нет? Почему не класс. И что нужно поменять в общих чертах что бы это был класс?
 

rotoZOOM

ACM maniac
В общих чертах:
- отвязаться от файла (убрать зависимость класса, от необходимости передавать имя файла);
- скрыть члены класса (засунуть под private переменные класса).
И ... скачать какой-нибудь PHP фреймворк (например kohana), посмотреть как там устроен класс работы с изображениями.
 

Arlevnar

Новичок
В общих чертах:
- отвязаться от файла (убрать зависимость класса, от необходимости передавать имя файла);
- скрыть члены класса (засунуть под private переменные класса).
И ... скачать какой-нибудь PHP фреймворк (например kohana), посмотреть как там устроен класс работы с изображениями.
1. Если я отвяжусь от файла то как я получу данные по изображению.
2. Члены нельзя переопределить (см. public function __set() {} ) тем самым можно получить доступ к тем же данным через свойства (краткость).
3. http://docs.kohanaphp.com/libraries/image - посмотрите сами
 

Здыхлик

Kohaner
Команда форума
1. Имя уже передано в конструкторе. Зачем оно нужно в других методах?
2. Прячем в protected (зачем private-то?), доступ через setter/getter. Можно еще разбавить плюшками, например изменение ширины через width() можно сопроводить ресайзом (причем даже не сразу, а при рендеринге, т.е. отдельно помнить оригинальные размеры).
3. https://github.com/kohana/image
4.
PHP:
if (!isset($width) && !isset($height))
А как такое может случиться, если эти пареметры в resize_calculation() обязательны? Кстати, этот метод имеет смысл спрятать (protected).
5. Почему trigger_error(), а не исключения?
6. С какого перепугу resize() отдает изображение в браузер? Этим должен заниматься отдельный метод, например render(). Еще можно __toString() прикрутить в качестве алиаса.

Ну и т.д. Возможностей много. В Kohana, если посмотрите, базовый класс абстрактный, и к нему можно прикручивать свои драйвера (GD и т.д.).
 

Arlevnar

Новичок
1. Имя уже передано в конструкторе. Зачем оно нужно в других методах?
2. Прячем в protected (зачем private-то?), доступ через setter/getter. Можно еще разбавить плюшками, например изменение ширины через width() можно сопроводить ресайзом (причем даже не сразу, а при рендеринге, т.е. отдельно помнить оригинальные размеры).
3. https://github.com/kohana/image
4.
PHP:
if (!isset($width) && !isset($height))
А как такое может случиться, если эти пареметры в resize_calculation() обязательны? Кстати, этот метод имеет смысл спрятать (protected).
5. Почему trigger_error(), а не исключения?
6. С какого перепугу resize() отдает изображение в браузер? Этим должен заниматься отдельный метод, например render(). Еще можно __toString() прикрутить в качестве алиаса.

Ну и т.д. Возможностей много. В Kohana, если посмотрите, базовый класс абстрактный, и к нему можно прикручивать свои драйвера (GD и т.д.).
Спасибо толковый ответ сейчас покапаюсь.

1. На какой строчке?
2. А зачем свойтва через getter пропускать если по хорошему в свойствах хранятся только данные по оригиналу, защиту от измения я поставил в setter
3. Сейчас гляну.
4. В случае не указания параметров в методе стандарная ошибка PHP на мой взгляд не уместна.
- в протектед я её не спрятал с целью дать возможность получить пропорциональные размеры.
5. Trigger error это временно я так понимаю что нужно свой класс Exception создать для класса Image
6. Отличное замечание дело в том что это было сделано с целью проверки работоспособности. (Поменяем не проблема)

Не хочется подвязывать не к каким фремворкам честно говоря.

Единственный вопрос этот класс можно сделать финальным по логике. Или не желательно?
 

rotoZOOM

ACM maniac
1. Изображения могут существовать и без файлов. imagecreatetruecolor создает вполне себе изображение.
2. Члены класса объявляются, как public (публичные, открытые), после чего с помощью __set закрывается доступ на запись в них. Где логика?
3. Да, согласен, мой косяк, в кохане имадж класс требует файла, но все остальное там сделано вполне сносно.
 

Arlevnar

Новичок
1. Изображения могут существовать и без файлов. imagecreatetruecolor создает вполне себе изображение.
2. Члены класса объявляются, как public (публичные, открытые), после чего с помощью __set закрывается доступ на запись в них. Где логика?
3. Да, согласен, мой косяк, в кохане имадж класс требует файла, но все остальное там сделано вполне сносно.
1. Ну акцент идёт непосредственно на то что бы работать с файлом изображений хотя по логике надо продумать как быть если изображение выводится из базы. (Хотя может я вас и не доконца понял что вы имеете ввиду)
2. Это сделано для того чтобы получать значения но не переопределять их.
3. Ну так Kohan-у делал не один человек как я понимаю и не в целях домашнего эксперимента)
 

Здыхлик

Kohaner
Команда форума
1. На какой строчке?
2. А зачем свойтва через getter пропускать если по хорошему в свойствах хранятся только данные по оригиналу, защиту от измения я поставил в setter
3. Сейчас гляну.
4. В случае не указания параметров в методе стандарная ошибка PHP на мой взгляд не уместна.
- в протектед я её не спрятал с целью дать возможность получить пропорциональные размеры.
5. Trigger error это временно я так понимаю что нужно свой класс Exception создать для класса Image
6. Отличное замечание дело в том что это было сделано с целью проверки работоспособности. (Поменяем не проблема)

Не хочется подвязывать не к каким фремворкам честно говоря.

Единственный вопрос этот класс можно сделать финальным по логике. Или не желательно?
1. Метод is_image($filename). Правда, в голову стукнуло, что этот метод можно использовать без создания объекта Image...
2. Потому что изменять их иногда стоит. Да и зачем дергать медленный __get(), если можно напрямую обратиться к методу?
4. Я имел в виду, что Вы не сможете передать два NULL в метод.

Привязываться не надо, предложили просто посмотреть :) Насчет final - а смысл? Просто ради final?
 

rotoZOOM

ACM maniac
1. Да, все верно. Изображение можно просто создавать. Например, для генерации картинки для капчи. Для этого не нужен файл.
2. Для этого можно воспользоваться __get, либо отдельными getter функциями.
 

Arlevnar

Новичок
Ребят огромное вам человеческое спасибо. Я обязательно должен довести дело до конца состыкуемся надеюсь ещё ту на форуме) Отредактированнй код скину сюда. Просто идти надо.
 
Сверху