From dadd00f6f5607c89620d995f2d72307763ff8c69 Mon Sep 17 00:00:00 2001 From: Pavel Belyaev Date: Sat, 29 May 2021 21:58:33 +0500 Subject: [PATCH] add LE_IMG class and documentation --- CLASSES/core/LE_IMG.md | 106 +++++++++++++++++ CLASSES/core/LE_IMG.php | 248 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 354 insertions(+) create mode 100644 CLASSES/core/LE_IMG.md create mode 100644 CLASSES/core/LE_IMG.php diff --git a/CLASSES/core/LE_IMG.md b/CLASSES/core/LE_IMG.md new file mode 100644 index 0000000..136e37e --- /dev/null +++ b/CLASSES/core/LE_IMG.md @@ -0,0 +1,106 @@ +# LE_IMG class by Pavel Belyaev + +Данный класс создан для простейших манипуляций с изображениями в формате jpeg, png и gif. + +Для работы данного класса требуется библиотека GD + +Класс делится на основные функции и вспомогательные, вспомогательные используются самим классом для работоспособности основных функций, но иногда может быть полезным использовать эти вспомогательные функции как самостоятельные для реализации специфичного функционала в вашем приложении... + +## Основные функции + +### Изменение размера изображения + +#### Пропорциональное + +Просто вписывает изображение в прямоугольник заданных размеров, если изображение меньше, то размер не меняется +``` +LE_IMG::resize($inp_path,$out_path,$max_width,$max_height); +``` +* `$inp_path` и `$out_path` - путь до исходной картинки и путь куда сохранять результат +* `$max_width` и `$max_height` - размер, в который нужно вписать изображение + +#### Пропорциональное с подрезкой +Данная функция красиво подрезает картинку, т.е. сперва вписывает в размер так, чтобы оно вылезало за пределы прямоугольника, но не было меньше, а дальше подрезает лишнее равномерно с каждой стороны. Если изображение после ресайза вписывается в заданную область, то ничего не вылезает и не подрезается. +``` +LE_IMG::resize_crop($inp_path,$out_path,$max_width,$max_height); +``` +### Простая подрезка картинки +Иногда нужно к примеру просто срезать произвольный участок с произвольной стороны картинки +``` +LE_IMG::crop($inp_path,$out_path,$left_crop,$top_crop,$right_crop,$bottom_crop); +``` + +### Наложение водяных знаков (watermark) + +#### Наложение на картинку текста по диагонали +```php +$conf = [ + 'text'=>'mytext', + 'font'=>'/path_to_font.ttf', + 'rgb'=>'78,78,78,40' //необязательный параметр +]; + +LE_IMG::watermark1($path_to_img,$conf); +``` + + + +#### Наложение прозрачного png на картинку +```php +LE_IMG::watermark2($path_to_img,$stamp_path,$skeep_err=1); +``` + + + + +___ + + +## Вспомогательные функции + +### Загрузка картинки +На вход передается путь до файла изображения +> Данная функция используется методами resize, resize_crop, crop, watermark1, watermark2 +```php +list($width,$height,$type,$img_resource) = LE_IMG::LOAD($path); +``` + +Возвращаeт `array` или `false` если файла нет или у файла неподдерживаемый тип +* `$type=1` - GIF +* `$type=2` - JPEG +* `$type=3` - PNG + +### Сохранение картинки +Сохраняет картинку после всех манипуляций с ресурсом LibGD +```php +LE_IMG::SAVE($img_resource,$type,$path); +``` + +### Вычисление новых размеров для ресайза + +#### Пропорциональное уменьшение +```php +list ($new_width,$new_height) = +LE_IMG::calc_prop($width,$height,$width_out,$height_out,$max=0); +``` + +calc_prop уменьшает ширину, если она больше нужной, и пропорционально высоту, далее тоже самое с высотой + +* `$width`, `$height` - текущие ширина и высота картинки в пикселях +* `$width_out`, `$height_out` - размеры, в которые нужно вписать картинку, обычно ограничивающие значения по ширине и высоте, если одно из значений превышает заданное, то второе пропорционально уменьшается +* `$max` - если передать этот параметр 1 или true, то поведение функции меняется, картинку меньше нужного размера тянет на нужные размеры, да, будет мыльно, но не всегда, при наложении прозрачной картинки на картинку немного большего размера ничего не поплывет... + +#### Уменьшение для подрезки +Иногда при уменьшении картинки она к примеру превращается в прямоугольник, тогда как нужно ее превратить в квадрат, т.е. уменьшить до такого прямоугольника, у которого одна из сторон будет побольше, а далее большую сторону подрезать +```php +list ($new_width,$new_height) = +LE_IMG::calc_prop2($width,$height,$width_out,$height_out); +``` + +## ToDo +* Реализовать crop для картинок отличных от квадратных (тест) +* Для resize_crop устранить раздутие картинки, если входное изображение меньше, делать уменьшенную версию... +* Добавить поддержку webp + + +## Changelog diff --git a/CLASSES/core/LE_IMG.php b/CLASSES/core/LE_IMG.php new file mode 100644 index 0000000..67254dd --- /dev/null +++ b/CLASSES/core/LE_IMG.php @@ -0,0 +1,248 @@ +0) && ($w<$w_out) && ($w=$w_out)) $h = Ceil($w*$r); + if (($h_out>0) && ($h<$h_out) && ($h=$h_out)) $w = Ceil($h*pow($r,-1)); + } + + //если ширина не вписалась, уменьшаем ширину, а высоту пропорционально + if (($w_out>0) && ($w>$w_out)) + { + $w=$w_out; + $h = Ceil($w*$r); + } + //если высота не вписалась, уменьшаем высоту, а ширину пропорционально + if (($h_out>0) && ($h>$h_out)) + { + $h=$h_out; + $w = Ceil($h*pow($r,-1)); + } + return [$w,$h]; //x,y + } + + public static function calc_prop2($w,$h,$w_out,$h_out) + { + $_w = $w/$w_out; + $_h = $h/$h_out; + $r = $h/$w; + + if($_w<$_h) + { + $w = $w_out; + $h = Ceil($w*$r); + } + else + { + $h=$h_out; + $w = Ceil($h*pow($r,-1)); + } + + return [$w,$h]; + + } + + + + //LE_IMG::resize ($in,$out,$mw=0,$mh=0); + public static function resize ($in,$out,$mw=0,$mh=0) + { + if (!file_exists($in)) return false; + $__load = LE_IMG::load($in); + if ($__load===false) return false; + list($w,$h,$t,$obj) = $__load; + $nw=$w; $nh=$h; + if (($mw>0) && ($w>$mw) && ($nw=$mw)) $nh = Ceil($nw*$h/$w); + if (($mh>0) && ($nh>$mh) && ($nh=$mh)) $nw = Ceil($nh*$w/$h); + $resource = imagecreatetruecolor ($nw,$nh); //создаем лист по новым размерам + imagealphablending($resource, false); + imagecopyresampled ($resource,$obj,0,0,0,0,$nw,$nh,$w,$h); + imageSaveAlpha($resource, true); + LE_IMG::save($resource,$t,$out); + return true; + } + + public static function resize_crop ($in,$out,$mw=0,$mh=0) + { + if (!file_exists($in)) return false; + $__load = LE_IMG::load($in); + if ($__load===false) return false; + + list($w,$h,$t,$obj) = $__load; + + list($nw,$nh) = LE_IMG::calc_prop2($w,$h,$mw,$mh); + + + //resize + $resource = imagecreatetruecolor ($nw,$nh); //создаем лист по новым размерам + imagealphablending($resource, false); + imagecopyresampled ($resource,$obj,0,0,0,0,$nw,$nh,$w,$h); + imageSaveAlpha($resource, true); + + //crop + $cr = array('width'=>$mw,'height'=>$mh); + $cr['x'] = Ceil(($nw-$mw)/2); + $cr['y'] = Ceil(($nh-$mh)/2); + $resource = imagecrop($resource,$cr); + + LE_IMG::save($resource,$t,$out); + return ; + } + + + //срезка кусочков изображения со всех сторон + public static function crop ($in,$out,$l=0,$t=0,$r=0,$b=0) + { + /*открытие*/ + list($w,$h,$t,$obj) = LE_IMG::load($in); + + /*новые размеры*/ + $n_w=$w-$l-$r; $n_h=$h-$t-$b; + + $res = imagecreatetruecolor($n_w,$n_h); + imagealphablending($res,false); + imagecopy ($res,$obj,0,0,$l,$t,$n_w,$n_h); + imageSaveAlpha($res, true); + + LE_IMG::save($res,$t,$out); + } + + public static function fix_color($w,$h,&$img) + { + //fix for png not truecolor + $uig = imagecreatetruecolor($w, $h); + imageSaveAlpha($uig, true); + //$transparent = imagecolortransparent ($img); + $transparent = imagecolorallocatealpha($uig,255,255,255,127); + imagefill($uig, 0, 0, $transparent); + imagecopy($uig, $img, 0, 0, 0, 0, $w, $h); + return $uig; + } + + + + public static function watermark1($url,$conf) + { + //return LE_IMG::demo_water($url,$conf); + if (!is_file($url)) exit('Нет файла для наложения watermark'); + $__load = LE_IMG::load($url); + if ($__load===false) return false; + + list($w,$h,$t,$src_img) = $__load; + + //fix for png not truecolor + if (imageistruecolor($src_img)===false) + { + $uig = LE_IMG::fix_color($w,$h,$src_img); + imagedestroy($src_img); + } + else + $uig = &$src_img; + + $txt_w = $w*0.9; $txt_h = $h*0.9; + if (!isset($conf['rgb'])) $conf['rgb'] = '78,78,78,40'; + $col = explode(',',$conf['rgb']); + $text = " ".$conf['text']." "; + $angle = -rad2deg(atan2((-$h),($w))); + + $color = imagecolorclosestalpha ($uig, $col[0], $col[1], $col[2], $col[3]); + $size = (($txt_w+$txt_h)/2)*2/mb_strlen(" ".$text." "); + + $fnt = $conf['font']; + $box = imagettfbbox ( $size, $angle, $fnt, $text); + $pad_left = ($txt_w/2 - abs($box[4] - $box[0])/2); + $pad_top = ($txt_h/2 + abs($box[5] - $box[1])/2); + + imagettftext($uig,$size ,$angle, $pad_left,$pad_top , $color, $fnt, $text); + + LE_IMG::save($uig,$t,$url); + return; + } + + public static function watermark2($url,$stamp_path,$skeep_err=1) + { + if (!is_file($url)) + { + if ($skeep_err) return false; + exit('Нет файла для наложения watermark'); + } + + $__load = LE_IMG::load($url); + if ($__load===false) return false; + + list($w,$h,$t,$src_img) = $__load; + + //fix for png not truecolor + if (imageistruecolor($src_img)===false) + { + $uig = LE_IMG::fix_color($w,$h,$src_img); + imagedestroy($src_img); + } + else + $uig = &$src_img; + + $_stamp = LE_IMG::load($stamp_path); + + if ($_stamp===false) return false; + + list($st_w,$st_h,$st_t,$stamp) = $_stamp; + + + list($_w,$_h) = LE_IMG::calc_prop($st_w,$st_h,$w,$h,1); + + $dst_x = $dst_y =0; + if ($_w<$w) $dst_x = ceil(($w-$_w)/2); + if ($_h<$h) $dst_y = ceil(($h-$_h)/2); + + imagecopyresampled ($uig,$stamp,$dst_x, $dst_y,0,0,$_w,$_h,$st_w,$st_h); + + LE_IMG::save($uig,$t,$url); + imagedestroy($stamp); + return; + } +} \ No newline at end of file