Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > PHP: Графика > превью изображения


Автор: Anarki 5.12.2007, 16:28
Вообщем нужно уменьшить большую картинку - сделать тумбу(превью), но так:
Цитата

Тумбинашки дожны обрезаться - тоесть например в настройках стоит размер 100х100. Картинка для тумбы уменьшается до 100 по меньшей стороне - например 100х150, а на длинной стороне лишнее обрезается - получается 100х100.

Это можно как-то сделать через imagecopyresampled? Что-то не могу догнать.
Я сделал пропорциональное уменьшение с помощью imagecopyresampled, но заказчик видимо хочет чтобы тумбы оставались одного размера.

Автор: Anarki 5.12.2007, 19:29
Если кому интересно, я решил так. Напишу алгоритм.
1. получил пропорции тумбы
2. открыл исходное(большое) изображение
3. получил "обрезку" с пропорциями тумбы
4. ресайзнул эту обрезку

thWidth,thHeight - заданные размеры тумбы
width_orig,height_orig размеры оригинального изображения
Код

<?php
// обрезка под пропорции тумбы
$ratio_thumb = $thWidth/$thHeight; // пропорции тумбы
if ($width_orig/$height_orig > $ratio_thumb) {
    $width_orig = $height_orig * $ratio_thumb;
} else {
    $height_orig = $width_orig/$ratio_thumb;
}
$image = imagecreatefromjpeg($fname); // оригинальное изображение
$image_c = imagecreatetruecolor($width_orig,$height_orig); // обрезка
imagecopy($image_c,$image,0,0,0,0,$width_orig,$height_orig); // получам обрезку с пропорциями тумбы

$image_p = imagecreatetruecolor($thWidth, $thHeight); // тумба
imagecopyresampled($image_p, $image_c, 0, 0, 0, 0, $thWidth, $thHeight, $width_orig, $height_orig); // просто тупо ресайз без учета пропорций, потому что исходная обрезка уже с пропорциями тумбы

Но отрезает некоторые части очень зло, допустим если на широкой картинке автомобиль во всю длину, то отрезает его половину под квадратную тумбу

Автор: bars80080 6.12.2007, 15:04
чувак, превью - это не урезанный рисунок, а уменьшенный, если вначале 300*200, то превью соответственно 100*67
вот поиграйся:
Код

function img_resize($src, $dest, $width, $height, $rgb=0xFFFFFF, $proportion=false, $quality=100) {
    if(!file_exists($src)) return false;
    $size = getimagesize($src);
    if($size === false) return false;   
    if($proportion === true) {
        $h0 = $height;
        $height = ($width/$size[0])*$size[1];
        if($height > $h0) { $height = $h0; $width = ($height/$size[1])*$size[0]; }}
    if($width > $size[0]) $width = $size[0];
    if($height > $size[1]) $height = $size[1];
    $format = strtolower(substr($size['mime'], strpos($size['mime'], '/') + 1));
    $icfunc = 'imagecreatefrom'.$format;
    if(!function_exists($icfunc)) return false;
    $x_ratio = $width/$size[0];
    $y_ratio = $height/$size[1];
    $ratio = min($x_ratio, $y_ratio);
    $use_x_ratio = ($x_ratio == $ratio);
    if($use_x_ratio) { $new_width = $width; $new_left = 0; } 
    else { $new_width = floor($size[0] * $ratio); $new_left = floor(($width - $new_width) / 2); }
    if(!$use_x_ratio) { $new_height = $height; $new_top = 0; }
    else { $new_height = floor($size[1] * $ratio); $new_top = floor(($height - $new_height) / 2); }
    $isrc = $icfunc($src);
    $idest = imagecreatetruecolor($width, $height);
    if(is_array($dest)) { 
        $nd = explode('.', $src); 
        $ndc = count($nd); 
        $nd[$ndc - 2] .= $dest[0]; $dest = implode('.', $nd); }
    imagefill($idest, 0, 0, $rgb);
    imagecopyresampled($idest, $isrc, $new_left, $new_top, 0, 0, $new_width, $new_height, $size[0], $size[1]);
    imagejpeg($idest, $dest, $quality);
    imagedestroy($isrc);
    imagedestroy($idest);
    return $dest; }

Автор: Anarki 6.12.2007, 17:27
bars80080
Спасибо за функцию, но превью может быть и урезанным и уменьшенным впринципе,имхо.

Автор: bars80080 6.12.2007, 17:43
как знаешь, но если рисунок 200*600 или 100*1000 ?

Автор: Anarki 9.12.2007, 14:06
Обрезать по большей стороне.

Автор: Feldmarschall 13.12.2007, 11:44
Лично я бы не обрезал, а добивал бы. рамкой какой-нибудь.

Автор: armor85 8.1.2008, 14:03
bars80080
для тех кто в танке, подскажи $dest что такое и как его использовать?

Код

if (img_resize('/upload/'.$rsFile["SUBDIR"].'/'.$rsFile["FILE_NAME"], $imgPrew, 40, 40))
 $ppl = "yes";
else
 $ppl = "no";


Всегда возвращает no. Что не так делаю подскажите. Может с $imgPrew что делать надо?

Автор: Date 9.1.2008, 11:04
armor85, $dest - это путь куда будет сохранена уменьшеная/урезанная копия изображения.

Если я все правельно понял!!!! 

Код

$imgPrew="prw.jpg";
(img_resize('/upload/'.$rsFile["SUBDIR"].'/'.$rsFile["FILE_NAME"], $imgPrew, 40, 40));


так вроде должно работать....

Автор: bars80080 9.1.2008, 12:47
обижаете, всё работает,
ессно, это чьи-то наработки, я просто их подправляю, а комментария конечно нету

img_resize($src, $dest, $width, $height, $rgb=0xFFFFFF, $proportion=false, $quality=100)
путь к оригиналу, имя превьюшки (почему в массиве уже не помню, но наверняка это была гениальная идея), пределы ширины, высоты, вообще не касался, сохранять ли пропорции, качество

кстати, я её использую в сочетании с такой функцией:
Код

function upLoader($userfile, $uploaddir = 'upload', $save = 'image', $data = array(160, 120, true, 100), $copy = 'true') {
    global $mistake, $BASE_DIR;          
    $temp = $_FILES[$userfile]['tmp_name'];
    $name = $_FILES[$userfile]['name'];
    $size = $_FILES[$userfile]['size'];
    $type = $_FILES[$userfile]['type'];
    $error = $_FILES[$userfile]['error']; $b = false;
    
    if($error > 0) { 
        $mistake = 'Çàãðóçêà íå âûïîëíåíà: '.$name.' '; switch($error) {
            case 1: $mistake .= 'ðàçìåð ôàéëà áîëüøå upload_max_filesize'; break;
            case 2: $mistake .= 'ðàçìåð ôàéëà áîëüøå max_file_size'; break;
            case 3: $mistake .= 'çàãðóæåíà òîëüêî ÷àñòü ôàéëà'; break;
            case 4: $mistake .= 'ôàéë íå çàãðóæåí'; break; }
        return $b; }
    $upfile = $uploaddir.'/'.$name; @mkdir($uploaddir, 755);
    if(is_uploaded_file($temp)) {
        if(!move_uploaded_file($temp, $upfile)) {          
            $mistake = 'Íåâîçìîæíî ïåðåñëàòü ôàéë â êàòàëîã íàçíà÷åíèÿ'; return $b; }}
    else { $mistake = 'Âîçìîæíî àòàêà ÷åðåç çàãðóçêó ôàéëà. Ôàéë: '.$name; return $b; }
    $mistake = 'Ôàéë óñïåøíî çàãðóæåí '.$name; $res = strstr($upfile, '../');
    if($res) { $res1 = explode('../', $upfile); $upfile = $res1[1]; }
    $b = $upfile;
    if(strstr($b, $BASE_DIR)) {
        $a = strlen($BASE_DIR);
        $b = substr($upfile, $a); }
    if($save == 'image' and $copy == 'true') {
        $b = img_resize($b, array('_small'), $data[0], $data[1], '', $data[2], $data[3]); }
    if($save == 'php') {
        $fp = fopen($b, 'r');
        $file = fread($fp, 100000);
        fclose($fp);
        $file = str_replace('<?', '', $file); $file = str_replace('?'.'>', '', $file); 
        $fp = fopen($b, 'w');
        $res = fwrite($fp, $file);
        fclose($fp); }
    return $b;    
}

ещё тот полуфабрикат, руки никак не доходят

Автор: MoLeX 9.1.2008, 14:39
особенно радует комментарий в коде, фсе четко и понятно  smile 
Цитата(bars80080 @  9.1.2008,  12:47 Найти цитируемый пост)
Çàãðóçêà íå âûïîëíåíà:


Автор: bars80080 9.1.2008, 14:59

 ! 
SamDark
Не ругаемся!

я спрашивал, и никто мне ответил

у меня в редакторе кодировка 1251, а здесь в textarea насколько понимаю koi8-r,
при копировании получается тоже самое

как избежать проблемы?

Автор: MoLeX 10.1.2008, 09:08
bars80080 до НГ я использовал Notepad 2++ (Кодировка -> Выбираем кодировку)
ща использую phpDesigner 2008 и там тоже самое есть (File -> Encoding -> Выбираем кодировку).

не ругайся)))


Автор: bars80080 10.1.2008, 11:50
<вырезано: нецензурная лексика>

 ! 
PARROT
Уважаемый bars80080, если у Вас есть конкретные предложения, по поводу улучшения функциональности форума, то для этого существует специальный раздел "Обсуждение форума". Модераторы РНР раздела этим не занимаются.

по поводу вставки кода6
меня мой редактор smart web builder очень даже устраивает, подсветка синтаксиса у него на 20 языков и при этом постоянно предлагает мне забытые ключевые слова, кодировку он тоже менять умеет
в нём я пишу в cp1251, что меня устраивает, ибо не слышал аргументов против
а вот при копировании такая ботва, впрочем, открыв файлик в блокноте, я обнаружил, что он нормально корветнул в нужную кодировку, так что вот
Код

function upLoader($userfile, $uploaddir = 'upload', $save = 'image', $data = array(160, 120, true, 100), $copy = 'true') {
    global $mistake, $BASE_DIR;          
    $temp = $_FILES[$userfile]['tmp_name'];
    $name = $_FILES[$userfile]['name'];
    $size = $_FILES[$userfile]['size'];
    $type = $_FILES[$userfile]['type'];
    $error = $_FILES[$userfile]['error']; $b = false;
    
    if($error > 0) { 
        $mistake = 'Загрузка не выполнена: '.$name.' '; switch($error) {
            case 1: $mistake .= 'размер файла больше upload_max_filesize'; break;
            case 2: $mistake .= 'размер файла больше max_file_size'; break;
            case 3: $mistake .= 'загружена только часть файла'; break;
            case 4: $mistake .= 'файл не загружен'; break; }
        return $b; }
    $upfile = $uploaddir.'/'.$name; @mkdir($uploaddir, 755);
    if(is_uploaded_file($temp)) {
        if(!move_uploaded_file($temp, $upfile)) {          
            $mistake = 'Невозможно переслать файл в каталог назначения'; return $b; }}
    else { $mistake = 'Возможно атака через загрузку файла. Файл: '.$name; return $b; }
    $mistake = 'Файл успешно загружен '.$name; $res = strstr($upfile, '../');
    if($res) { $res1 = explode('../', $upfile); $upfile = $res1[1]; }
    $b = $upfile;
    if(strstr($b, $BASE_DIR)) {
        $a = strlen($BASE_DIR);
        $b = substr($upfile, $a); }
    if($save == 'image' and $copy == 'true') {
        $b = img_resize($b, array('_small'), $data[0], $data[1], '', $data[2], $data[3]); }
    if($save == 'php') {
        $fp = fopen($b, 'r');
        $file = fread($fp, 100000);
        fclose($fp);
        $file = str_replace('<?', '', $file); $file = str_replace('?'.'>', '', $file); 
        $fp = fopen($b, 'w');
        $res = fwrite($fp, $file);
        fclose($fp); }
    return $b; }

но это лишние движения...

Автор: Noviy 25.5.2009, 08:37
Цитата(bars80080 @ 6.12.2007,  15:04)
чувак, превью - это не урезанный рисунок, а уменьшенный, если вначале 300*200, то превью соответственно 100*67
вот поиграйся:
Код

function img_resize($src, $dest, $width, $height, $rgb=0xFFFFFF, $proportion=false, $quality=100) {
    if(!file_exists($src)) return false;
    $size = getimagesize($src);
    if($size === false) return false;   
    if($proportion === true) {
        $h0 = $height;
        $height = ($width/$size[0])*$size[1];
        if($height > $h0) { $height = $h0; $width = ($height/$size[1])*$size[0]; }}
    if($width > $size[0]) $width = $size[0];
    if($height > $size[1]) $height = $size[1];
    $format = strtolower(substr($size['mime'], strpos($size['mime'], '/') + 1));
    $icfunc = 'imagecreatefrom'.$format;
    if(!function_exists($icfunc)) return false;
    $x_ratio = $width/$size[0];
    $y_ratio = $height/$size[1];
    $ratio = min($x_ratio, $y_ratio);
    $use_x_ratio = ($x_ratio == $ratio);
    if($use_x_ratio) { $new_width = $width; $new_left = 0; } 
    else { $new_width = floor($size[0] * $ratio); $new_left = floor(($width - $new_width) / 2); }
    if(!$use_x_ratio) { $new_height = $height; $new_top = 0; }
    else { $new_height = floor($size[1] * $ratio); $new_top = floor(($height - $new_height) / 2); }
    $isrc = $icfunc($src);
    $idest = imagecreatetruecolor($width, $height);
    if(is_array($dest)) { 
        $nd = explode('.', $src); 
        $ndc = count($nd); 
        $nd[$ndc - 2] .= $dest[0]; $dest = implode('.', $nd); }
    imagefill($idest, 0, 0, $rgb);
    imagecopyresampled($idest, $isrc, $new_left, $new_top, 0, 0, $new_width, $new_height, $size[0], $size[1]);
    imagejpeg($idest, $dest, $quality);
    imagedestroy($isrc);
    imagedestroy($idest);
    return $dest; }

Очень хорошая функция, но возникла проблема. Не обрезает белые поля, которые остаются после уменьшения картинки по оси Y. Использую её в cakephp 1.2
Код

if(isset($this->data['Admin']['photo'])){
    $this->img_resize("img/$fname", "img/$fname", 300, 400, $rgb=0xFFFFFF, $proportion=false, $quality=100);
}

Ужимал картинку 800x600.
В результате получаем: ( firebug видно поля ) 

Автор: bars80080 25.5.2009, 09:38
по факту оказалось, что закомментированный кусок был вставлен преднамерено для создания полей, когда картинка не вмещается полностью. в данном варианте функция работает как надо

Код

function img_resize($src, $dest, $width, $height, $rgb=0xFFFFFF, $proportion=false, $quality=100) {
    if(!file_exists($src)) return false;
    $size = getimagesize($src);
    if($size === false) return false;   
    if($proportion === true) {
        $h0 = $height;
        $height = ($width/$size[0])*$size[1];
        if($height > $h0) { $height = $h0; $width = ($height/$size[1])*$size[0]; }}
    if($width > $size[0]) $width = $size[0];
    if($height > $size[1]) $height = $size[1];
    $format = strtolower(substr($size['mime'], strpos($size['mime'], '/') + 1));
    $icfunc = 'imagecreatefrom'.$format;
    if(!function_exists($icfunc)) return false;
    /*$x_ratio = $width/$size[0];var_dump($x_ratio);
    $y_ratio = $height/$size[1];var_dump($y_ratio);
    $ratio = min($x_ratio, $y_ratio);
    $use_x_ratio = ($x_ratio == $ratio);
    if($use_x_ratio) { $new_width = $width; $new_left = 0; } 
    else { $new_width = floor($size[0] * $ratio); $new_left = floor(($width - $new_width) / 2); }
    if(!$use_x_ratio) { $new_height = $height; $new_top = 0; }
    else { $new_height = floor($size[1] * $ratio); $new_top = floor(($height - $new_height) / 2); }*/
    $isrc = $icfunc($src);
    $idest = imagecreatetruecolor($width, $height);
    if(is_array($dest)) { 
        $nd = explode('.', $src); 
        $ndc = count($nd); 
        $nd[$ndc - 2] .= $dest[0]; $dest = implode('.', $nd); }
    imagefill($idest, 0, 0, $rgb);
    imagecopyresampled($idest, $isrc, 0, 0, 0, 0, $width, $height, $size[0], $size[1]);
    imagejpeg($idest, $dest, $quality);
    imagedestroy($isrc);
    imagedestroy($idest);
    return $dest; }
  

img_resize("img/$fname", "img/$fname", 300, 400, $rgb=0xFFFFFF, $proportion = false, $quality=100);


Добавлено через 54 секунды
но и прошлый вариант имеет право на существование

Автор: bars80080 25.5.2009, 09:58
я б даже сказал, лучше адаптировать функцию под обе ситуации:

Код
function img_resize($src, $dest, $width, $height, $rgb=0xFFFFFF, $proportion = false, $fields = false, $quality=100) {
    if(!file_exists($src)) return false;
    $size = getimagesize($src);
    if($size === false) return false;   
    if($proportion === true) {
        $h0 = $height;
        $height = ($width/$size[0])*$size[1];
        if($height > $h0) { $height = $h0; $width = ($height/$size[1])*$size[0]; }}
    if($width > $size[0]) $width = $size[0];
    if($height > $size[1]) $height = $size[1];
    $format = strtolower(substr($size['mime'], strpos($size['mime'], '/') + 1));
    $icfunc = 'imagecreatefrom'.$format;
    if(!function_exists($icfunc)) return false;
    if($fields) {
        $x_ratio = $width/$size[0];
        $y_ratio = $height/$size[1];
        $ratio = min($x_ratio, $y_ratio);
        $use_x_ratio = ($x_ratio == $ratio);
        if($use_x_ratio) { $new_width = $width; $new_left = 0; } 
        else { $new_width = floor($size[0] * $ratio); $new_left = floor(($width - $new_width) / 2); }
        if(!$use_x_ratio) { $new_height = $height; $new_top = 0; }
        else { $new_height = floor($size[1] * $ratio); $new_top = floor(($height - $new_height) / 2); }
    } else {
        $new_left = 0; $new_top = 0; $new_width = $width; $new_height = $height;
    }
    $isrc = $icfunc($src);
    $idest = imagecreatetruecolor($width, $height);
    if(is_array($dest)) { 
        $nd = explode('.', $src); 
        $ndc = count($nd); 
        $nd[$ndc - 2] .= $dest[0]; $dest = implode('.', $nd); }
    imagefill($idest, 0, 0, $rgb);
    imagecopyresampled($idest, $isrc, $new_left, $new_top, 0, 0, $new_width, $new_height, $size[0], $size[1]);
    imagejpeg($idest, $dest, $quality);
    imagedestroy($isrc);
    imagedestroy($idest);
    return $dest; }

Автор: Noviy 25.5.2009, 13:36
Благодарю. Кстати, можно создать тему с полезными функциями, и разместить её там smile

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)