568 lines
24 KiB
PHP
568 lines
24 KiB
PHP
|
|
<?php
|
|||
|
|
/**
|
|||
|
|
* Simpla CMS
|
|||
|
|
*
|
|||
|
|
* @copyright 2011 Denis Pikusov
|
|||
|
|
* @link http://simplacms.ru
|
|||
|
|
* @author Denis Pikusov
|
|||
|
|
*
|
|||
|
|
*/
|
|||
|
|
require_once ('Simpla.php');
|
|||
|
|
if(!class_exists('SimpleImage')) include $_SERVER['DOCUMENT_ROOT'].'/api/SimpleImage.php';
|
|||
|
|
|
|||
|
|
|
|||
|
|
class Image extends Simpla
|
|||
|
|
{
|
|||
|
|
private $allowed_extentions = array(
|
|||
|
|
'png',
|
|||
|
|
'gif',
|
|||
|
|
'jpg',
|
|||
|
|
'jpeg',
|
|||
|
|
'ico');
|
|||
|
|
public function __construct()
|
|||
|
|
{
|
|||
|
|
parent::__construct();
|
|||
|
|
}
|
|||
|
|
/**
|
|||
|
|
* Создание превью изображения
|
|||
|
|
* @param $filename файл с изображением (без пути к файлу)
|
|||
|
|
* @param max_w максимальная ширина
|
|||
|
|
* @param max_h максимальная высота
|
|||
|
|
* @return $string имя файла превью
|
|||
|
|
*/
|
|||
|
|
function resizepost($filename)
|
|||
|
|
{
|
|||
|
|
list($source_file, $width, $height, $set_watermark) = $this->get_resize_params($filename);
|
|||
|
|
// Если вайл удаленный (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);
|
|||
|
|
// Пути к папкам с картинками
|
|||
|
|
$originals_dir = $this->config->root_dir . $this->config->original_images_dir;
|
|||
|
|
$preview_dir = $this->config->root_dir . $this->config->post_images_dir;
|
|||
|
|
if (class_exists('Imagick') && $this->config->use_imagick)
|
|||
|
|
$this->image_constrain_imagick($originals_dir . $original_file, $preview_dir . $resized_file, $width, $height);
|
|||
|
|
else
|
|||
|
|
$this->image_constrain_gd($originals_dir . $original_file, $preview_dir . $resized_file, $width, $height);
|
|||
|
|
return $preview_dir . $resized_file;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
function resizepage($filename)
|
|||
|
|
{
|
|||
|
|
list($source_file, $width, $height, $set_watermark) = $this->get_resize_params($filename);
|
|||
|
|
// Если вайл удаленный (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);
|
|||
|
|
// Пути к папкам с картинками
|
|||
|
|
$originals_dir = $this->config->root_dir . $this->config->original_images_dir;
|
|||
|
|
$preview_dir = $this->config->root_dir . $this->config->page_images_dir;
|
|||
|
|
if (class_exists('Imagick') && $this->config->use_imagick)
|
|||
|
|
$this->image_constrain_imagick($originals_dir . $original_file, $preview_dir . $resized_file, $width, $height);
|
|||
|
|
else
|
|||
|
|
$this->image_constrain_gd($originals_dir . $original_file, $preview_dir . $resized_file, $width, $height);
|
|||
|
|
return $preview_dir . $resized_file;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
|
|||
|
|
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|||
|
|
function resizecat($filename)
|
|||
|
|
{
|
|||
|
|
|
|||
|
|
|
|||
|
|
//list($source_file, $width , $height, $set_watermark) = $this->get_resize_params($filename); //echo $source_file;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);
|
|||
|
|
*/
|
|||
|
|
$width = 252;
|
|||
|
|
$height = 252;
|
|||
|
|
$original_file = $filename;
|
|||
|
|
$resized_file = $this->add_resize_params($filename, $width, $height, $set_watermark);
|
|||
|
|
|
|||
|
|
// Пути к папкам с картинками
|
|||
|
|
$originals_dir = $this->config->root_dir . $this->config->categories_images_dir;
|
|||
|
|
$preview_dir = $this->config->root_dir . $this->config->categories_images_dir;
|
|||
|
|
|
|||
|
|
if (class_exists('Imagick') && $this->config->use_imagick)
|
|||
|
|
$this->image_constrain_imagick($originals_dir . $original_file, $preview_dir . $resized_file, $width, $height);
|
|||
|
|
else
|
|||
|
|
$this->image_constrain_gd($originals_dir . $original_file, $preview_dir . $resized_file, $width, $height);
|
|||
|
|
|
|||
|
|
|
|||
|
|
return $preview_dir . $resized_file;
|
|||
|
|
|
|||
|
|
//echo $preview_dir .'999'. $resized_file;
|
|||
|
|
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
|
|||
|
|
function resizeArticle($filename, $width, $height)
|
|||
|
|
{
|
|||
|
|
|
|||
|
|
|
|||
|
|
$original_file = $filename;
|
|||
|
|
$resized_file = $this->add_resize_params($filename, $width, $height, $set_watermark);
|
|||
|
|
|
|||
|
|
// Пути к папкам с картинками
|
|||
|
|
$originals_dir = $this->config->root_dir . 'files/article_photo/';
|
|||
|
|
$preview_dir = $this->config->root_dir . 'files/article_photo/';
|
|||
|
|
|
|||
|
|
if(is_file($preview_dir . $resized_file)) return '/files/article_photo/' . $resized_file;
|
|||
|
|
|
|||
|
|
$img = new SimpleImage($originals_dir . $filename);
|
|||
|
|
if($width == $height) $img->square_crop($width)->save($preview_dir . $resized_file);
|
|||
|
|
else $img->best_fit($width, $height)->save($preview_dir . $resized_file);
|
|||
|
|
|
|||
|
|
|
|||
|
|
return '/files/article_photo/' . $resized_file;
|
|||
|
|
|
|||
|
|
//echo $preview_dir .'999'. $resized_file;
|
|||
|
|
|
|||
|
|
}
|
|||
|
|
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|||
|
|
|
|||
|
|
|
|||
|
|
function resize($filename, $imgs_dir = '')
|
|||
|
|
{
|
|||
|
|
$imgs_dir = $imgs_dir ? $imgs_dir : $this->config->resized_images_dir;
|
|||
|
|
$orig_dir = $imgs_dir ? $imgs_dir : $this->config->original_images_dir;
|
|||
|
|
|
|||
|
|
list($source_file, $width, $height, $set_watermark) = $this->get_resize_params($filename);
|
|||
|
|
// Если вайл удаленный (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;
|
|||
|
|
} echo $original_file;
|
|||
|
|
$resized_file = $this->add_resize_params($original_file, $width, $height, $set_watermark);
|
|||
|
|
// Пути к папкам с картинками
|
|||
|
|
$originals_dir = $this->config->root_dir . $this->config->original_images_dir;
|
|||
|
|
$preview_dir = $this->config->root_dir . $this->config->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->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);
|
|||
|
|
//echo $preview_dir . '1'. $resized_file;
|
|||
|
|
return $preview_dir . $resized_file;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
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;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
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);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
public function download_image($filename)
|
|||
|
|
{
|
|||
|
|
// Заливаем только есть такой файл есть в базе
|
|||
|
|
$this->db->query('SELECT 1 FROM __images WHERE filename=? LIMIT 1', $filename);
|
|||
|
|
if (!$this->db->result())
|
|||
|
|
return false;
|
|||
|
|
// Имя оригинального файла
|
|||
|
|
$uploaded_file = array_shift(explode('?', pathinfo($filename, PATHINFO_BASENAME)));
|
|||
|
|
$uploaded_file = array_shift(explode('&', pathinfo($filename, PATHINFO_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;
|
|||
|
|
}
|
|||
|
|
$this->db->query('UPDATE __images SET filename=? WHERE filename=?', $new_name, $filename);
|
|||
|
|
// Перед долгим копированием займем это имя
|
|||
|
|
fclose(fopen($this->config->root_dir . $this->config->original_images_dir . $new_name, 'w'));
|
|||
|
|
copy($filename, $this->config->root_dir . $this->config->original_images_dir . $new_name);
|
|||
|
|
return $new_name;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
public function upload_image($filename, $name)
|
|||
|
|
{
|
|||
|
|
// Имя оригинального файла
|
|||
|
|
$uploaded_file = $new_name = pathinfo($name, PATHINFO_BASENAME);
|
|||
|
|
//$uploaded_file = $new_name = $this->rus_lat($new_name);
|
|||
|
|
$uploaded_file = $new_name = $this->translateStr($new_name);
|
|||
|
|
|
|||
|
|
|
|||
|
|
$base = pathinfo($uploaded_file, PATHINFO_FILENAME);
|
|||
|
|
$ext = pathinfo($uploaded_file, PATHINFO_EXTENSION);
|
|||
|
|
if (in_array(strtolower($ext), $this->allowed_extentions))
|
|||
|
|
{
|
|||
|
|
|
|||
|
|
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;
|
|||
|
|
}
|
|||
|
|
if (move_uploaded_file($filename, $this->config->root_dir . $this->config->original_images_dir . $new_name)){
|
|||
|
|
$img = new SimpleImage($this->config->root_dir . $this->config->original_images_dir . $new_name);
|
|||
|
|
$img->best_fit(1200, 1200)->save($this->config->root_dir . $this->config->original_images_dir . $new_name); //echo '---'.$this->config->root_dir . $this->config->original_images_dir . $new_name;
|
|||
|
|
return $new_name;
|
|||
|
|
}else{
|
|||
|
|
//die($filename . '='.$this->config->root_dir . $this->config->original_images_dir . $new_name);
|
|||
|
|
}
|
|||
|
|
}else{
|
|||
|
|
//die('bad image');
|
|||
|
|
}
|
|||
|
|
return false;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
|
|||
|
|
|
|||
|
|
|
|||
|
|
function rus_lat($name){
|
|||
|
|
$rus = array('','а','б','в','г','д','е','ё','Ё','ж','з','и','й','к',
|
|||
|
|
'л','м','н','о','п','р','с','т','у','ф','х','ц','ч','ш','щ','ъ','ы','ь','э','ю','я');
|
|||
|
|
$eng = array('','a','b','v','g','d','e','e','e','zh','z','i','j','k',
|
|||
|
|
'l','m','n','o','p','r','s','t','u','f','h','c','ch','sh','shch','','y','','e','yu','ya');
|
|||
|
|
$name = mb_strtolower($name,"UTF-8");
|
|||
|
|
$name = str_replace(array('"',"'"),'',$name);
|
|||
|
|
$name = str_replace(array(',',':',';','/','{','}','[',']'),'',$name);
|
|||
|
|
$name = str_replace(array(' '),'_',$name);
|
|||
|
|
$res = '';
|
|||
|
|
$arr = $this->str_split_unicode($name);
|
|||
|
|
foreach($arr as $key){
|
|||
|
|
if($key == '_'){
|
|||
|
|
$res .= '_';
|
|||
|
|
continue;
|
|||
|
|
}
|
|||
|
|
if (!preg_match("/[а-я]/i", $key)){
|
|||
|
|
$res .= $key;
|
|||
|
|
continue;
|
|||
|
|
}
|
|||
|
|
$k = array_search($key,$rus);
|
|||
|
|
if($k){
|
|||
|
|
$res .= $eng[$k];
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
return $res;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
function str_split_unicode($str, $l = 0) {
|
|||
|
|
if ($l > 0) {
|
|||
|
|
$ret = array();
|
|||
|
|
$len = mb_strlen($str, "UTF-8");
|
|||
|
|
for ($i = 0; $i < $len; $i += $l) {
|
|||
|
|
$ret[] = mb_substr($str, $i, $l, "UTF-8");
|
|||
|
|
}
|
|||
|
|
return $ret;
|
|||
|
|
}
|
|||
|
|
return preg_split("//u", $str, -1, PREG_SPLIT_NO_EMPTY);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* Создание превью средствами gd
|
|||
|
|
* @param $src_file исходный файл
|
|||
|
|
* @param $dst_file файл с результатом
|
|||
|
|
* @param max_w максимальная ширина
|
|||
|
|
* @param max_h максимальная высота
|
|||
|
|
* @return bool
|
|||
|
|
*/
|
|||
|
|
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($src_type == 'application/octet-stream') $src_type = 'image/jpeg';
|
|||
|
|
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);
|
|||
|
|
//imagecopymerge($dst_img, $overlay, $watermark_x, $watermark_y, 0, 0, $owidth, $oheight, $watermark_opacity*100);
|
|||
|
|
}
|
|||
|
|
// 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;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
/**
|
|||
|
|
* Создание превью средствами imagick
|
|||
|
|
* @param $src_file исходный файл
|
|||
|
|
* @param $dst_file файл с результатом
|
|||
|
|
* @param max_w максимальная ширина
|
|||
|
|
* @param max_h максимальная высота
|
|||
|
|
* @return bool
|
|||
|
|
*/
|
|||
|
|
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->setImageOpacity($watermark_opacity);
|
|||
|
|
//$overlay_compose = $overlay->getImageCompose();
|
|||
|
|
$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, $overlay_compose, $watermark_x, $watermark_y, imagick::COLOR_ALPHA);
|
|||
|
|
$frame->compositeImage($overlay, imagick::COMPOSITE_OVER, $watermark_x, $watermark_y, imagick::COLOR_ALPHA);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
// Убираем комменты и т.п. из картинки
|
|||
|
|
$thumb->stripImage();
|
|||
|
|
// $thumb->setImageCompressionQuality(100);
|
|||
|
|
// Записываем картинку
|
|||
|
|
if (!$thumb->writeImages($dst_file, true))
|
|||
|
|
return false;
|
|||
|
|
// Уборка
|
|||
|
|
$thumb->destroy();
|
|||
|
|
if (isset($overlay) && is_object($overlay))
|
|||
|
|
$overlay->destroy();
|
|||
|
|
return true;
|
|||
|
|
}
|
|||
|
|
/**
|
|||
|
|
* Вычисляет размеры изображения, до которых нужно его пропорционально уменьшить, чтобы вписать в квадрат $max_w x $max_h
|
|||
|
|
* @param src_w ширина исходного изображения
|
|||
|
|
* @param src_h высота исходного изображения
|
|||
|
|
* @param max_w максимальная ширина
|
|||
|
|
* @param max_h максимальная высота
|
|||
|
|
* @return array(w, h)
|
|||
|
|
*/
|
|||
|
|
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);
|
|||
|
|
}
|
|||
|
|
private function files_identical($fn1, $fn2)
|
|||
|
|
{
|
|||
|
|
$buffer_len = 1024;
|
|||
|
|
if (!$fp1 = fopen($fn1, 'rb'))
|
|||
|
|
return false;
|
|||
|
|
if (!$fp2 = fopen($fn2, 'rb'))
|
|||
|
|
{
|
|||
|
|
fclose($fp1);
|
|||
|
|
return false;
|
|||
|
|
}
|
|||
|
|
$same = true;
|
|||
|
|
while (!feof($fp1) and !feof($fp2))
|
|||
|
|
if (fread($fp1, $buffer_len) !== fread($fp2, $buffer_len))
|
|||
|
|
{
|
|||
|
|
$same = false;
|
|||
|
|
break;
|
|||
|
|
}
|
|||
|
|
if (feof($fp1) !== feof($fp2))
|
|||
|
|
$same = false;
|
|||
|
|
fclose($fp1);
|
|||
|
|
fclose($fp2);
|
|||
|
|
return $same;
|
|||
|
|
}
|
|||
|
|
}
|