Совсем недавно я столкнулся с задачей масштабированием изображений в php, создание маленьких превью для больших картинок. Соль задачи была в том, что масштабировать мне предстояло под определенное разрешение. Порыскав инете, не нашел ничего толкового, пришлось пораскинуть серым веществом, и вот что из этого вышло: у изображений в большинстве случаев либо горизонталь, либо вертикаль больше, поэтому просто сделать ресайз под заданные размеры не выйдет - уменьшенная картинка деформируется. Чтобы этого не произошло, перед масштабированием необходимо выполнить несколько операций, а именно: нужно вычислить так называемую "рамку", прямоугольник, по размеру которого будет обрезаться картинка. "Рамка" должна быть кратна заданным для масштабирования размерам, а значит размеры "рамки" надо вычислить. Потом, надо спозиционировать воображаемую "рамку" на изображении, чтобы обрезанная картинка содержала наиболее актуальную часть.
Итак, задача по пунктам:
1. вычислить размеры "рамки" так, чтобы они были кратными заданному разрешению.
2. спозиционировать "рамку", чтобы обрезаемая по рамке картинка содержала наиболее актуальную часть изображения, в нашем случае мы будем центрировать "рамку".
3. выполнить операции по масштабированию с заданными параметрами, сохранить изображение и очисить память.
1. вычислить размеры "рамки" так, чтобы они были кратными заданному разрешению.
2. спозиционировать "рамку", чтобы обрезаемая по рамке картинка содержала наиболее актуальную часть изображения, в нашем случае мы будем центрировать "рамку".
3. выполнить операции по масштабированию с заданными параметрами, сохранить изображение и очисить память.
Задача поставлена, теперь к делу.
Сразу скажу, в данной задаче мы делаем масштабирование jpeg изображения. Также для наших действий нам необходима библиотека GD. Чтобы проверить наличие библиотеки, воспользуйтесь функцией phpinfo();
Сразу скажу, в данной задаче мы делаем масштабирование jpeg изображения. Также для наших действий нам необходима библиотека GD. Чтобы проверить наличие библиотеки, воспользуйтесь функцией phpinfo();
Описание переменных на входе:
$filename - переменная, в которой содержится имя загруженного файла.
$thmb_w - заданная для масштабирования ширина превью.
$thmb_h - заданная для масштабирования высота превью.
$thmb_path – заданный путь для сохранения превью на сервере
Код по пунктам:
1. размеры рамки
//создание изображения
$img = imagecreatefromjpeg($filename);
//получение размеров изображения, загруженного на сервер
$imginfo = getimagesize($filename);
$src_w = $imginfo[0];
$src_h = $imginfo[1];
//создание чистого изображения с заданнми размерами
$pict = imagecreatetruecolor($thmb_w,$thmb_h) or die('cannot create image');
//вычисляем соотношение минимальной стороны и заданного нам размера превьюшки
$ratio = ( $src_w > $src_h )? ( $src_h / $thmb_h):( $src_w / $thmb_w);
//целевые длина и ширина "рамки", кратные заданным размерам превью
$dest_w = (int)($thmb_w * $ratio);
$dest_h = (int)($thmb_h * $ratio);
2. позиционирование "рамки"
//вычисление координат левого верхнего угла "рамки"
$point_x = (int)(($src_w - $dest_w) / 2);
$point_y = (int)(($src_h - $dest_h) / 2);
3. масштабирование с заданными параметрами
//создание изображения с заданными параметрами
imagecopyresampled($pict, $img, 0, 0, $point_x, $point_y, $thmb_w, $thmb_h, $dest_w, $dest_h);
//сохранение изображения
imagejpeg($pict,$thmb_path,100);
//очистка памяти, выделенной для создания изображения
imagedestroy($pict);
В сборе мое решение выглядит так:
//загрузка и сохранение файла с проверками
//--------------------------------
//создание изображения
$img = imagecreatefromjpeg($filename);
//получение размеров изображения, загруженного на сервер
$imginfo = getimagesize($filename);
$src_w = $imginfo[0];
$src_h = $imginfo[1];
//создание чистого изображения с заданнми размерами
$pict = imagecreatetruecolor($thmb_w,$thmb_h) or die('cannot create image');
//вычисляем соотношение минимальной стороны и заданного нам размера превьюшки
$ratio = ( $src_w > $src_h )? ( $src_h / $thmb_h):( $src_w / $thmb_w);
//целевые длина и ширина "рамки", кратные заданным размерам превью
$dest_w = (int)($thmb_w * $ratio);
$dest_h = (int)($thmb_h * $ratio);
//вычисление координат левого верхнего угла "рамки"
$point_x = (int)(($src_w - $dest_w) / 2);
$point_y = (int)(($src_h - $dest_h) / 2);
//создание изображения с заданными параметрами
imagecopyresampled($pict, $img, 0, 0, $point_x, $point_y, $thmb_w, $thmb_h, $dest_w, $dest_h);
//сохранение изображения
imagejpeg($pict,$thmb_path,100);
//очистка памяти, выделенной для создания изображения
imagedestroy($pict);
Конечно, слишком вытянутые изображения масштабируются плохо, потому что велика вероятность обрезать большую часть актуальной части, но таких изображений как правило очень мало в общей массе, и если они действительно имеют место, для них нужно делать отдельную центровку, например вытянутые по вертикали фотографии как правило актуальную часть содержат в верхней части.
Хочу сказать, что я намеренно почти не останавливался на проверках, ибо целью моей было именно подача механизма масштабирования. Код проверял на работоспособность. Но люди не идеальны, и если где то закралась ошибка - я буду рад конструктивной критике )
Хочу сказать, что я намеренно почти не останавливался на проверках, ибо целью моей было именно подача механизма масштабирования. Код проверял на работоспособность. Но люди не идеальны, и если где то закралась ошибка - я буду рад конструктивной критике )
Комментариев нет:
Отправить комментарий