Класс Image.php
Класс Image
Класс предназначен для работы с изображения сайта (товары, категории и т.д)
Функция resize()
public function resize($filename,$original_images_dir = null, $resized_images_dir = null) { list($source_file, $width , $height, $set_watermark) = $this->get_resize_params($filename); $size = $width.'x'.$height; $image_sizes = array(); if ($this->settings->image_sizes) { $image_sizes = explode('|', $this->settings->image_sizes); } if (!in_array($size, $image_sizes)){ header("http/1.0 404 not found"); exit(); } // Если вайл удаленный (http://), зальем его себе if(substr($source_file, 0, 7) == 'http://') { // Имя оригинального файла if(!$original_file = $this->download_image($source_file)) { return false; } $resized_file = $this->add_resize_params($original_file, $width, $height, $set_watermark); } else { $original_file = $source_file; } $resized_file = $this->add_resize_params($original_file, $width, $height, $set_watermark); // Пути к папкам с картинками if ($original_images_dir && !$resized_images_dir) { $resized_images_dir = $original_images_dir; } else { if (!$original_images_dir) { $original_images_dir = $this->config->original_images_dir; } if (!$resized_images_dir) { $resized_images_dir = $this->config->resized_images_dir; } } $originals_dir = $this->config->root_dir.$original_images_dir; $preview_dir = $this->config->root_dir.$resized_images_dir; $watermark_offet_x = $this->settings->watermark_offset_x; $watermark_offet_y = $this->settings->watermark_offset_y; $sharpen = min(100, $this->settings->images_sharpen)/100; $watermark_transparency = 1-min(100, $this->settings->watermark_transparency)/100; if($set_watermark && is_file($this->config->root_dir.$this->config->watermark_file)) { $watermark = $this->config->root_dir.$this->config->watermark_file; } else { $watermark = null; } if(class_exists('Imagick') && $this->config->use_imagick) { $this->image_constrain_imagick($originals_dir.$original_file, $preview_dir.$resized_file, $width, $height, $watermark, $watermark_offet_x, $watermark_offet_y, $watermark_transparency, $sharpen); } else { $this->image_constrain_gd($originals_dir.$original_file, $preview_dir.$resized_file, $width, $height, $watermark, $watermark_offet_x, $watermark_offet_y, $watermark_transparency); } return $preview_dir.$resized_file; }
Функция ресайза изображения (его нарезки до нужных размеров) Важно! Функция не делает кроп изображения, она его пропорционально уменьшает
Функция принимает три аргумента ($filename,$original_images_dir, $resized_images_dir)
Параметры которые содержит функция:
- $filename - имя изображения
- $original_images_dir - название директории с оригинальными фото
- $resized_images_dir - название директории с уменьшенными изображениями
Функция возвращает полный путь к наресайзеному изображению
Функция add_resize_params()
/*Добавление параметров ресайза для изображения*/ public function add_resize_params($filename, $width=0, $height=0, $set_watermark=false) { if('.' != ($dirname = pathinfo($filename, PATHINFO_DIRNAME))) { $file = $dirname.'/'.pathinfo($filename, PATHINFO_FILENAME); } else { $file = pathinfo($filename, PATHINFO_FILENAME); } $ext = pathinfo($filename, PATHINFO_EXTENSION); if($width>0 || $height>0) { $resized_filename = $file.'.'.($width>0?$width:'').'x'.($height>0?$height:'').($set_watermark?'w':'').'.'.$ext; } else { $resized_filename = $file.'.'.($set_watermark?'w.':'').$ext; } return $resized_filename; }
Функция добавление пераметров ресайза к изображению
Функция принимает 4 аргумента $filename, $width, $height, $set_watermark
Параметры которые содержит функция:
- $filename - имя изображения
- $width - ширина изображения в пикселях
- $height - высота изображения в пикселях
- $set_watermark - установка водяного знака (true/false)
Функция возвращает имя файла с установленными параметрами
Функция get_resize_params()
/*Выборка параметров изображения для ресайза*/ public function get_resize_params($filename) { // Определаяем параметры ресайза if(!preg_match('/(.+)\.([0-9]*)x([0-9]*)(w)?\.([^\.]+)$/', $filename, $matches)) { return false; } $file = $matches[1]; // имя запрашиваемого файла $width = $matches[2]; // ширина будущего изображения $height = $matches[3]; // высота будущего изображения $set_watermark = $matches[4] == 'w'; // ставить ли водяной знак $ext = $matches[5]; // расширение файла return array($file.'.'.$ext, $width, $height, $set_watermark); }
Функция для получения параметров ресайза из названия изображения
Функция принимает аргумент $filename
Параметры которые содержит функция:
- $filename - название файла изображения
Функция возвращает массив с параметрами ресайза
Функция download_image()
/*Загрузка изображения*/ public function download_image($filename) { // Заливаем только есть такой файл есть в базе $this->db->query('SELECT 1 FROM __images WHERE filename=? LIMIT 1', $filename); if(!$this->db->result()) { return false; } // Имя оригинального файла $basename = preg_replace('~(.+)\.([0-9]*)x([0-9]*)(w)?\.([^\.\?]+)(\?.*)?$~', '${1}.${5}', $filename); $basename = explode('&', pathinfo($basename, PATHINFO_BASENAME)); $uploaded_file = array_shift($basename); $base = urldecode(pathinfo($uploaded_file, PATHINFO_FILENAME)); $ext = pathinfo($uploaded_file, PATHINFO_EXTENSION); // Если такой файл существует, нужно придумать другое название $new_name = urldecode($uploaded_file); while(file_exists($this->config->root_dir.$this->config->original_images_dir.$new_name)) { $new_base = pathinfo($new_name, PATHINFO_FILENAME); if(preg_match('/_([0-9]+)$/', $new_base, $parts)) { $new_name = $base.'_'.($parts[1]+1).'.'.$ext; } else { $new_name = $base.'_1.'.$ext; } } // Перед долгим копированием займем это имя fclose(fopen($this->config->root_dir.$this->config->original_images_dir.$new_name, 'w')); if (copy($filename, $this->config->root_dir.$this->config->original_images_dir.$new_name)) { $this->db->query('UPDATE __images SET filename=? WHERE filename=?', $new_name, $filename); return $new_name; } else { @unlink($this->config->root_dir.$this->config->original_images_dir.$new_name); return false; } }
Функция загрузки изображения с удаленного ресурса
Функция принимает аргумент $filename
Параметры которые содержит функция:
- $filename - название файла изображения
Функция возвращает имя загруженного файла в случае успеха
Функция upload_image()
/*Загрузка изображения*/ public function upload_image($filename, $name, $original_dir = null) { // Имя оригинального файла $name = preg_replace('~(.+)\.([0-9]*)x([0-9]*)(w)?\.([^\.\?]+)$~', '${1}.${5}', $name); $name = $this->correct_filename($name); $uploaded_file = $new_name = pathinfo($name, PATHINFO_BASENAME); $base = pathinfo($uploaded_file, PATHINFO_FILENAME); $ext = pathinfo($uploaded_file, PATHINFO_EXTENSION); if (!$original_dir) { $original_dir = $this->config->original_images_dir; } if(in_array(strtolower($ext), $this->allowed_extentions)) { while(file_exists($this->config->root_dir.$original_dir.$new_name)) { $new_base = pathinfo($new_name, PATHINFO_FILENAME); if(preg_match('/_([0-9]+)$/', $new_base, $parts)) { $new_name = $base.'_'.($parts[1]+1).'.'.$ext; } else { $new_name = $base.'_1.'.$ext; } } if(move_uploaded_file($filename, $this->config->root_dir.$original_dir.$new_name)) { return $new_name; } } return false; }
Функция загрузки изображения на сервер
Функция принимает 3 аргумента ($filename, $name, $original_dir)
Параметры которые содержит функция:
- $filename - путь к изображению на сервере (временная папка)
- $name - имя файла изображения
- $original_dir - директория назначения (папка в которую будет помещен новый файл)
Функция возвращает имя загруженного файла в случае успеха
Функция image_constrain_gd()
private function image_constrain_gd($src_file, $dst_file, $max_w, $max_h, $watermark=null, $watermark_offet_x=0, $watermark_offet_y=0, $watermark_opacity=1) { $quality = 100; // Параметры исходного изображения @list($src_w, $src_h, $src_type) = array_values(getimagesize($src_file)); $src_type = image_type_to_mime_type($src_type); if(empty($src_w) || empty($src_h) || empty($src_type)) { return false; } // Нужно ли обрезать? if (!$watermark && ($src_w <= $max_w) && ($src_h <= $max_h)) { // Нет - просто скопируем файл if (!copy($src_file, $dst_file)) { return false; } return true; } // Размеры превью при пропорциональном уменьшении @list($dst_w, $dst_h) = $this->calc_contrain_size($src_w, $src_h, $max_w, $max_h); // Читаем изображение switch ($src_type) { case 'image/jpeg': $src_img = imageCreateFromJpeg($src_file); break; case 'image/gif': $src_img = imageCreateFromGif($src_file); break; case 'image/png': $src_img = imageCreateFromPng($src_file); imagealphablending($src_img, true); break; default: return false; } if(empty($src_img)) { return false; } $src_colors = imagecolorstotal($src_img); // create destination image (indexed, if possible) if ($src_colors > 0 && $src_colors <= 256) { $dst_img = imagecreate($dst_w, $dst_h); } else { $dst_img = imagecreatetruecolor($dst_w, $dst_h); } if (empty($dst_img)) { return false; } $transparent_index = imagecolortransparent($src_img); if ($transparent_index >= 0 && $transparent_index <= 128) { $t_c = imagecolorsforindex($src_img, $transparent_index); $transparent_index = imagecolorallocate($dst_img, $t_c['red'], $t_c['green'], $t_c['blue']); if ($transparent_index === false) { return false; } if (!imagefill($dst_img, 0, 0, $transparent_index)) { return false; } imagecolortransparent($dst_img, $transparent_index); } // or preserve alpha transparency for png elseif ($src_type === 'image/png') { if (!imagealphablending($dst_img, false)) { return false; } $transparency = imagecolorallocatealpha($dst_img, 0, 0, 0, 127); if (false === $transparency) { return false; } if (!imagefill($dst_img, 0, 0, $transparency)) { return false; } if (!imagesavealpha($dst_img, true)) { return false; } } // resample the image with new sizes if (!imagecopyresampled($dst_img, $src_img, 0, 0, 0, 0, $dst_w, $dst_h, $src_w, $src_h)) { return false; } // Watermark if(!empty($watermark) && is_readable($watermark)) { $overlay = imagecreatefrompng($watermark); // Get the size of overlay $owidth = imagesx($overlay); $oheight = imagesy($overlay); $watermark_x = min(($dst_w-$owidth)*$watermark_offet_x/100, $dst_w); $watermark_y = min(($dst_h-$oheight)*$watermark_offet_y/100, $dst_h); imagecopy($dst_img, $overlay, $watermark_x, $watermark_y, 0, 0, $owidth, $oheight); } // recalculate quality value for png image if ('image/png' === $src_type) { $quality = round(($quality / 100) * 10); if ($quality < 1) { $quality = 1; } elseif ($quality > 10) { $quality = 10; } $quality = 10 - $quality; } // Сохраняем изображение switch ($src_type) { case 'image/jpeg': return imageJpeg($dst_img, $dst_file, $quality); case 'image/gif': return imageGif($dst_img, $dst_file, $quality); case 'image/png': imagesavealpha($dst_img, true); return imagePng($dst_img, $dst_file, $quality); default: return false; } }
Функция построения конечного изображения с использованием библиотеки GD
Функция принимает такие аргументы ($src_file, $dst_file, $max_w, $max_h, $watermark, $watermark_offet_x, $watermark_offet_y)
Параметры которые содержит функция:
- $src_file - исходный файл
- $dst_file - файл с результатом
- $max_w - максимальная ширина
- $max_h - максимальная высота
- $watermark - водяной знак
- $watermark_offet_x - сдвиг знака по оси х
- $watermark_offet_у - сдвиг знака по оси у
Функция возвращает построенный файл
Функция image_constrain_imagick()
private function image_constrain_imagick($src_file, $dst_file, $max_w, $max_h, $watermark=null, $watermark_offet_x=0, $watermark_offet_y=0, $watermark_opacity=1, $sharpen=0.2) { $thumb = new Imagick(); // Читаем изображение if(!$thumb->readImage($src_file)) { return false; } // Размеры исходного изображения $src_w = $thumb->getImageWidth(); $src_h = $thumb->getImageHeight(); // Нужно ли обрезать? if (!$watermark && ($src_w <= $max_w) && ($src_h <= $max_h)) { // Нет - просто скопируем файл if (!copy($src_file, $dst_file)) { return false; } return true; } // Размеры превью при пропорциональном уменьшении list($dst_w, $dst_h) = $this->calc_contrain_size($src_w, $src_h, $max_w, $max_h); // Уменьшаем $thumb->thumbnailImage($dst_w, $dst_h); // Устанавливаем водяной знак if($watermark && is_readable($watermark)) { $overlay = new Imagick($watermark); $overlay->evaluateImage(Imagick::EVALUATE_MULTIPLY, $watermark_opacity, Imagick::CHANNEL_ALPHA); // Get the size of overlay $owidth = $overlay->getImageWidth(); $oheight = $overlay->getImageHeight(); $watermark_x = min(($dst_w-$owidth)*$watermark_offet_x/100, $dst_w); $watermark_y = min(($dst_h-$oheight)*$watermark_offet_y/100, $dst_h); } // Анимированные gif требуют прохода по фреймам foreach($thumb as $frame) { // Уменьшаем $frame->thumbnailImage($dst_w, $dst_h); /* Set the virtual canvas to correct size */ $frame->setImagePage($dst_w, $dst_h, 0, 0); // Наводим резкость if($sharpen > 0) { $thumb->adaptiveSharpenImage($sharpen, $sharpen); } if(isset($overlay) && is_object($overlay)) { $frame->compositeImage($overlay, imagick::COMPOSITE_OVER, $watermark_x, $watermark_y, imagick::COLOR_ALPHA); } } // Убираем комменты и т.п. из картинки $thumb->stripImage(); $thumb->setImageCompressionQuality($this->settings->image_quality ? $this->settings->image_quality : 80 ); $thumb->setImageCompression($this->settings->image_quality ? $this->settings->image_quality : 80); // Записываем картинку if(!$thumb->writeImages($dst_file, true)) { return false; } // Уборка $thumb->destroy(); if(isset($overlay) && is_object($overlay)) { $overlay->destroy(); } return true; }
Функция построения конечного изображения с использованием библиотеки Imagick
Функция принимает такие аргументы ($src_file, $dst_file, $max_w, $max_h, $watermark, $watermark_offet_x, $watermark_offet_y, $watermark_opacity, $sharpen)
Параметры которые содержит функция:
- $src_file - исходный файл
- $dst_file - файл с результатом
- $max_w - максимальная ширина
- $max_h - максимальная высота
- $watermark - водяной знак
- $watermark_offet_x - сдвиг знака по оси х
- $watermark_offet_у - сдвиг знака по оси у
- $watermark_opacity - прозрачность водяного знака
- $sharpen - резкость изображения
Функция возвращает построенный файл
Функция calc_contrain_size()
public function calc_contrain_size($src_w, $src_h, $max_w = 0, $max_h = 0) { if($src_w == 0 || $src_h == 0) { return false; } $dst_w = $src_w; $dst_h = $src_h; if($src_w > $max_w && $max_w>0) { $dst_h = $src_h * ($max_w/$src_w); $dst_w = $max_w; } if($dst_h > $max_h && $max_h>0) { $dst_w = $dst_w * ($max_h/$dst_h); $dst_h = $max_h; } return array($dst_w, $dst_h); }
Функция вычисления размера изображения, до которых нужно его пропорционально уменьшить, чтобы вписать в квадрат $max_w x $max_h
Функция принимает аргументы($src_w, $src_h, $max_w = 0, $max_h = 0)
Параметры которые содержит функция:
- $src_w - языка, который необходимо выбрать
- $src_h - языка, который необходимо выбрать
- $max_w - языка, который необходимо выбрать
- $max_h - языка, который необходимо выбрать
Функция возвращает вычисленную ширину и высоту
Функция delete_image()
public function delete_image($id, $field = null, $table = null, $original_dir = null, $resized_dir = null, $lang_id = 0, $lang_field = '') { if (!$field || !$table || !$original_dir) { return false; } if (!$lang_id) { $query = $this->db->placehold("SELECT $field FROM __$table WHERE id=?", $id); $this->db->query($query); $filename = $this->db->result($field); if (!empty($filename)) { $query = $this->db->placehold("UPDATE __$table SET $field='' WHERE id=?", $id); $this->db->query($query); $query = $this->db->placehold("SELECT count(*) as count FROM __$table WHERE $field=? LIMIT 1", $filename); $this->db->query($query); $count = $this->db->result('count'); if($count == 0) { $file = pathinfo($filename, PATHINFO_FILENAME); $ext = pathinfo($filename, PATHINFO_EXTENSION); // Удалить все ресайзы if (!empty($resized_dir)) { $rezised_images = glob($this->config->root_dir.$resized_dir.$file.".*x*.".$ext); if(is_array($rezised_images)) { foreach ($rezised_images as $f) { @unlink($f); } } } @unlink($this->config->root_dir.$original_dir.$filename); } } } else { $query = $this->db->placehold("SELECT $field FROM __lang_$table WHERE $lang_field=? and lang_id=?", $id, $lang_id); $this->db->query($query); $filename = $this->db->result($field); if (!empty($filename)) { $query = $this->db->placehold("UPDATE __lang_$table SET $field='' WHERE $lang_field=? and lang_id=?", $id, $lang_id); $this->db->query($query); $query = $this->db->placehold("SELECT count(*) as count FROM __lang_$table WHERE $field=? LIMIT 1", $filename); $this->db->query($query); $count = $this->db->result('count'); if($count == 0) { $file = pathinfo($filename, PATHINFO_FILENAME); $ext = pathinfo($filename, PATHINFO_EXTENSION); // Удалить все ресайзы if (!empty($resized_dir)) { $rezised_images = glob($this->config->root_dir.$resized_dir.$file.".*x*.".$ext); if(is_array($rezised_images)) { foreach ($rezised_images as $f) { @unlink($f); } } } @unlink($this->config->root_dir.$original_dir.$filename); } } } }
Функция удаляет изображение и все его ресайзы (физически и из БД)
Функция принимает аргументы($id, $field = null, $table = null, $original_dir = null, $resized_dir = null, $lang_id = 0, $lang_field = '')
Параметры которые содержит функция:
- $id - $id удаляемой сущности
- $field - поле в таблице БД
- $table - таблица в БД
- $original_dir - директория с оригинальным файлом
- $resized_dir - директория с ресайзами изображений
- $lang_id - мультиязычная таблица
- $lang_field - мультиязычные поля