Загрузка и масштабирование изображений в php
04.07.2008 от
Андрей Зарубин
Наверное, многие разработчики web-приложений сталкивались с необходимостью написания скрипта, который бы загружал на сервер графические файлы (изображения). Реализовать это достаточно просто.
Самое сложное в подобных скриптах это предварительная обработка изображения. То есть, допустим, стоит задача организовать фотогалерею. При этом нужно, чтобы на главной странице выводились preview (иконки) каждой фотографии в пропорционально уменьшенном виде. Следовательно, исходное изображение (загружаемое на сервер)
скрипт должен обработать так, чтобы в результате получилась аккуратная уменьшенная копия.
Методов, по которым строятся иконки несколько.
Первый: иконка создается путем вырезания центральной части (с заранее заданными размерами) изображения. Например, если исходное изображение имеет линейные размеры 500×500 пикселей, мы можем вырезать центральную область (зачастую именно там основное смысловое содержание картинки) размером 100×100 пикселей. Но мне этот метод не очень нравится, потому что не всегда можно угадать и вырезать фрагмент, который будет плохо передавать содержание исходной картинки. К слову: подобный метод, по моим наблюдениям, применяется в сервисе знакомств mamba.ru ![]()
Второй: иконка создается путем пропорционального уменьшения линейных размеров изображения до (не более) нужных. Этот метод немного сложнее, ведь изображения могут быть разными (горизонтальными, вертикальными, квадратными), а уменьшать их нужно так, чтобы сохранить пропорции, иначе получится искаженная иконка. Пропорции высчитываются из исходных линейных размеров изображения, для этого нужно наибольший исходный размер (для горизонтальных изображений это ширина, а для вертикальных — высота) поделить на установленную нами максимальную ширину (высоту). Далее, чтобы получить линейные размеры уже преобразованного изображения, нужно наименьший исходный размер разделить на полученное соотношение. Округленный до целого результат и будет преобразованным первым линейным размером. А второй линейный размер (ширина или высота) будет равен ранее установленному нами максимальному значению.
Например, если изображение имеет линейные размеры 800×400 пикселей, а максимальная ширина (изображение горизонтальное) равна, допустим, 125 пикселей, то соотношение будет равно 800/125=6,4. Следовательно, ширина изображения на выходе будет 125 пикселей (изображение горизонтальное), а высота будет равна 400/6,4=62 пикселя. В итоге результирующее изображение будет иметь линейные размеры 125×62 пикселей. Если же исходное изображение было вертикальное и имело линейные размеры 400×800 пикселей, то его линейные размеры на выходе были бы 62×125 пикселей. Так можно передать всю картинку полностью, ничего не вырезая. Этот метод, например, применяется на picasa.google.com
Итак, вот что я написал на php (скрипт по загрузке и масштабированию изображений)
Примечание: всякие (безусловно необходимые) проверки на тип файла, размер и все остальное я умышленно опустил.
$q = 100; // Качество jpeg изображения
$file = $_FILES["yourfile"]["name"]; // Записываем содержимое массива
// $_FILES в $file
$src = imagecreatefromjpeg($_FILES["yourfile"]["tmp_name"]); // Создаем временный
// файл
$w_src = imagesx($src); // Определяем его линейный размер по горизонтали (ширина)
$h_src = imagesy($src); // Определяем его линейный размер по вертикали (высота)
$dir = "$DOCUMENT_ROOT/images/"; // Папка, куда будет записан
// уже преобразованный файл
$path = "$dir$file"; // Полный путь к файлу (включая и его имя)
if ($w_src != $w) // Проверяем не равна ли уже
//исходная ширина необходимой нам
{
if ($w_src > $h_src) // Если изображение горизонтальное
{
$ratio = $w_src/$w; // Считаем соотношение пропорций
$w_dest = $w; // Конечная ширина будет равна максимальной
$h_dest = round($h_src/$ratio); // Считаем конечную высоту
}
elseif ($h_src > $w_src) // Если изображение вертикальное
{
$ratio = $h_src/$w; // Считаем соотношение пропорций
$h_dest = $w; // Конечная высота будет равна максимальной
$w_dest = round($w_src/$ratio); // Считаем конечную ширину
}
else // Если изображение квадратное
{
$w_dest = $w; // Подставляем максимальные значения
$h_dest = $w;
}
$dest = imagecreatetruecolor($w_dest,$h_dest); // Создаем пустое изображение
imagecopyresampled($dest, $src, 0, 0, 0, 0, $w_dest, $h_dest, $w_src, $h_src);
// Преобразуем исходное изображение в конечное (с новыми размерами).
// Функция использует ресемплинг, поэтому изображение будет лучшего
// качества, чем если использовать вместо imagecopyresampled функцию
// imagecopyresized
}
else
{
$dest = imagecreatefromjpeg($_FILES["yourfile"]["tmp_name"]);
// Если исходная ширина равна нужной нам на выходе, то просто
// создаем временный файл без преобразований
}
if (!file_exists ("$path")) // Проверяем не существует ли уже файл
{
$res = imagejpeg($dest,"$path",$q); // Копируем файл в папку
if ($res) // Если скопировано успешно, выдаем сообщение об успехе
{
echo “Файл закачан!”;
}
else // Если не скопировано, то выдаем сообщение об ошибке
{
echo “Ошибка записи файла!”;
}
imagedestroy($dest); // Освобождаем память
imagedestroy($src);
}
Критику в студию ![]()
__
Хороший туроператор по Кипру — самое время отдохнуть
Рубрики: php |
azarubin.com
05.07.2008 в 12:59
Реально понимаю, что человек, практически не знакомый с компьютером может просто не разобраться в этих программах. Хорошо было бы опубликовать подробную статью, с пошаговым описанием. Я вот встречала нечто подобное у Небомжа, но вот хоть убейте меня, сейчас не могу вспомнить, где именно. Эх, жаль…
06.07.2008 в 18:06
Ну, кому надо, тот разберется
А кто не поймет пропустит… Вообще, подробных статей на эту тему довольно много.
07.07.2008 в 11:51
Статей много небывает))в каждой что нибудь да упустят))
07.07.2008 в 19:29
Друган дал ссылку, я обычно подобное не читаю, но не пожалел!
08.07.2008 в 15:57
Я бы покитиковал, еслм бы был стоящик кодером, а вообще - задача очень не простая, насколько я знаю.
09.07.2008 в 12:40
Клим, ссмотря с чем сравнивать. Если сделать очень клево - то непросто, если так себе - то просто.
10.07.2008 в 22:04
Ендрю - молодец, повернулся к читателю лицом. Когда по пиву епнем?
16.07.2008 в 10:04
а для чего такие сложности? зачем изобретать велосипед с квадратными колесами? Не проще сразу же уменьшить изображение не на число, а на процент?
17.07.2008 в 09:26
vit, разверните мысль
11.08.2008 в 07:56
Верноятно, vit o imagecopyresampled и imagecopyresized. Он просто не доразворачивал Вашу, Андрей, мысль дальше первых строк
01.09.2008 в 02:18
>всякие (безусловно необходимые) проверки на тип файла, размер и все остальное я умышленно опустил.
И очень зря. Об этом нужно писать подробнее, т.к. информации хватает.
СПАСИБО!
Сатья - для общего развития. И все же
01.09.2008 в 17:21
Статья-то, конечно, для общего развития, я и не настаиваю на чем-то большем…
07.10.2008 в 21:37
Мне кажется эту строку: “if ($w_src != $w) // Проверяем не равна ли уже исходная ширина необходимой нам”
Стоит заменить на такую: “if ($w_src != $w || $h_src != $w)”, потому что при Вашей проверке юзер может загрузить изображение с нужной шириной и неврот**овой высотой…
Всё таки хотелось бы увидеть проверки на тип файла, размер и все остальное… Если не сложно - напишите пожалуйста!
08.10.2008 в 11:31
>>Стоит заменить на такую: “if ($w_src != $w || $h_src != $w)”, потому что при Вашей проверке юзер может загрузить изображение с нужной шириной и неврот**овой высотой…
Это проверяется тоже, смотрите дальше. Про проверки могу написать в общем, но по это йтеме инфы предостаточно вроде.
08.10.2008 в 18:29
Дело в том, что, если это условие: “if ($w_src != $w)” не выполняется, то все операторы, входящие в { } не будут так же выполняться, а сразу будет осуществлён переход к else, поэтому всё же нужно на всякий пожарный добавить проверку по вертикали!
Или я всё таки что-то не понимаю…
26.02.2009 в 08:54
Спасибо! Пришел по поисковику и ваша статья очень помогла.
26.02.2009 в 12:02
TAHOMOTO, вообще-то чесно говоря данный метод не очень хорошо. Я сейчас применяю немного другой.
13.08.2009 в 11:28
Вот таких:
$path = “$dir$file”;
конструкций лучше избегать. Очень сильно влияют на производительность переменные оставленные в кавычках. А в данном случае ещё и наглядность страдает. Так:
$path = $dir.$file;
будет и быстрее и красивее
А за статью спасибо!