КОД СКРИПТА 1.3b1 ▼
/*
* Mr.Miksar © 2009 - 02.2026
* img_resizer (ThumbCuter) version 1.3b1
* Функция подгонки и обрезки изображения под заданный размер для создания превью.
* Код написан как логический набросок без оптимизации длины кода. Но всё работает и так ;)
*
* @param string $src - Путь к исходному изображению.
* @param string $dest - Путь к сохраняемому превью. Значения: NULL или файл с полным путем для физического сохранения.
* Если указать NULL, то скрипт выдаст код изображения. Формат превью будет аналогичен исходному файлу.
* Можно получить превью с заданным форматом, если указать его для создаваемого файла.
* @param int $dw - Ширина превью (необязательно, если задана высота).
* @param int $dh - Высота превью (необязательно, если задана ширина).
* Если $dw и $dh равны нулю, то будет размер исходного изображения.
* @param int $quality - Качество превью (необязательная опция, по умолчанию 100): от 0 до 100.
* @param int $rgb - Цвет подложки (необязательно).
* @param int $rew - Перезаписывать превью (необязательно): true - да, false - нет.
* @return bool - true, если изображение сформировано, иначе false.
*/
function img_resizer($src, $dest = NULL, $dw = 0, $dh = 0, $quality = 100, $rgb = 0, $rew = true) {
global $ir_res; // что бы вывести полученный размер превью
$a = $b = 0;
//// проверка исходного изображения и получение его параметров
if (!file_exists($src) || !is_readable($src)) return false;
if (($size = getimagesize($src)) === false) return false;
$iw = $size[0]; // ширина исходника
$ih = $size[1]; // высота исходника
$im = strtolower($size['mime']); // формат исходника
//// Проверка поддерживаемого формата
$sup_im = ['image/jpeg', 'image/png','image/gif', 'image/bmp', 'image/webp'];
if (!in_array($im, $sup_im)) return false;
//// Может ли сервер создавать файлы с расширением исходного изображения
$s_ext = substr($im, strpos($im, '/') + 1);
if (!function_exists($icfunc = 'imagecreatefrom' . $s_ext)) return false;
//// Проверка заданных размеров для превью
if (!is_numeric($dw) || $dw < 0) $dw = 0;
if (!is_numeric($dh) || $dh < 0) $dh = 0;
//// Если заданные ширина и высота равны нулю, то размер превью равен размеру исходника
if ($dw == 0 && $dh == 0) {
$dw = $iw;
$dh = $ih;
}
//// Если заданные ширина или высота больше размера исходника, то приравниваем к размерам исходника
if ($iw <= $dw) $dw = $iw;
if ($ih <= $dh) $dh = $ih;
//// Проверка указанного качества для превью (0-100) // 02.2026
$quality = (is_numeric($quality) && $quality >= 0 && $quality <= 100) ? $quality : 100;
//// Параметры подложки
$rgb = (!empty($rgb) && is_int($rgb)) ? $rgb : 0xFFFFFF;
//// Удалим старую превью, если выбрана опция перезаписи и оно создано
if ($rew && !empty($dest)) {
if (file_exists($dest)) unlink($dest);
}
//// Коэффициенты отношения сторон исходника
$rsw = $iw / $ih; // прямой по ширине (ratio src width)
$rsh = $ih / $iw; // обратный по высоте (ratio src height)
$imin = ($iw > $ih) ? $ih : $iw; // находим минимальную сторону
$imax = ($iw > $ih) ? $iw : $ih; // находим максимальную сторону
//// получение относительного размера для не заданной стороны превью, относительно заданной по исходному изображению
if (empty($dw) && !empty($dh)) $dw = (int)round($dh * $rsw); // если не задана ширина результата
if (empty($dh) && !empty($dw)) $dh = (int)round($dw * $rsh); // если не задана высота результата
//// значения по умолчанию для функции imagecopyresampled
$dstx = 0; // координаты, куда будет скопирована область в результат
$dsty = 0;
$srcx = 0; // начальные координаты копируемой области на исходнике
$srcy = 0;
$dstw = $dw; // ширина и высота превью
$dsth = $dh;
$srcw = $iw; // ширина и высота копируемой области на исходнике
$srch = $ih;
//echo "<p>TEST: src: ".$iw."x".$ih." | dest: ".$dw."x".$dh." | imin: ".$imin." | </p>"; // тест входных данных
//// start function
$prev = false; // Переменная с результатом
$d_ext = !empty($dest) ? strtolower(pathinfo($dest, PATHINFO_EXTENSION)) : $s_ext; // Формат создаваемого превью
$isrc = $icfunc($src); // Создание исходного изображения
// Ширина превью больше/равна исходнику, высота превью меньше исходника
// вырезать середину из исходника высотой превью $dh
if ($iw <= $dw && $ih > $dh) {
$srcy = round((($srch - $dh) / 2), 0, PHP_ROUND_HALF_DOWN);
$srch = $dh;
// Ширина превью меньше исходника, высота превью больше/равна исходнику
// вырезать середину из исходника шириной превью $dw
} elseif ($iw > $dw && $ih <= $dh) {
$srcx = round((($srcw - $dw) / 2), 0, PHP_ROUND_HALF_DOWN);
$srcw = $dw;
// Ширина и высота превью меньше исходника
// уменьшить исходник по меньшему размеру стороны превью и вырезать середину из исходника высотой $dh и шириной $dw
} else {
// ходят, ходят ёжики в туман...
// исходное изображение вертикальное
if ($iw < $ih) {
// превью - горизонтальное или квадратное
if ($dw >= $dh) {
$rh = $dw * $rsh;
if ($dh <= $rh) {
$rh = $dh;
$rsrch = round(($srcw / $dw) * $dh);
} elseif ($dh > $rh && $dh <= $srch) {
$rsrch = round(($srcw / $dw) * $rh);
} elseif ($dh > $rh && $dh > $srch) {
$rh = $srch;
$rsrch = $srch;
}
$rsrch = ($rsrch <= $srch) ? $rsrch : $srch;
$a = round(($srch - $rsrch) / 2);
$srcy = $a;
$dsth = $rh;
$srch = $rsrch;
// превью - вертикальное
} elseif ($dw < $dh) {
$rw = $dh * $rsw;
if ($dw <= $rw) {
$rw = $dw;
$rsrcw = round(($srch / $dh) * $rw);
} elseif ($dw > $rw && $dw <= $srcw) {
$rw = $dw;
$rsrcw = $srcw;
$rsrch = round(($srcw / $dw) * $dh);
$rsrch = ($rsrch <= $srch) ? $rsrch : $srch;
$a = round(($srch - $rsrch) / 2);
$srcy = $a;
$srch = $rsrch;
} elseif ($dw > $rw && $dw > $srcw) {
$rw = $srcw;
$rsrcw = $srcw;
}
$rsrcw = ($rsrcw <= $srcw) ? $rsrcw : $srcw;
$b = round(($srcw - $rsrcw) / 2);
$srcx = $b;
$dstw = $rw;
$srcw = $rsrcw;
}
// исходное изображение горизонтальное/квадратное
} elseif ($iw >= $ih) {
// превью - горизонтальное
if ($dw > $dh) {
$rh = $dw * $rsh;
if ($dh <= $rh) {
$rh = $dh;
$rsrch = round(($srcw / $dw) * $rh);
} elseif ($dh > $rh && $dh <= $srch) {
$rh = $dh;
$rsrch = $srch;
$rsrcw = round(($srch / $dh) * $dw);
$rsrcw = ($rsrcw <= $srcw) ? $rsrcw : $srcw;
$b = round(($srcw - $rsrcw) / 2);
$srcx = $b;
$srcw = $rsrcw;
} elseif ($dh > $rh && $dh > $srch) {
$rh = $srch;
$rsrch = $srch;
}
$rsrch = ($rsrch <= $srch) ? $rsrch : $srch;
$a = round(($srch - $rsrch) / 2);
$dsth = $rh;
$srch = $rsrch;
$srcy = $a;
// превью - вертикальное или квадратное
} elseif ($dw <= $dh) {
$rw = $dh * $rsw;
if ($dw <= $rw) {
$rw = $dw;
$rsrcw = round(($srch / $dh) * $rw);
} elseif ($dw > $rw && $dw <= $srcw) {
$rsrcw = round(($srch/$dh)*$rw);
} elseif ($dw > $rw && $dw > $srcw) {
$rw = $srcw;
$rsrcw = $srcw;
}
$rsrcw = ($rsrcw <= $srcw) ? $rsrcw : $srcw;
$b = round(($srcw - $rsrcw) / 2);
$srcx = $b;
$dstw = $rw;
$srcw = $rsrcw;
}
}
// фух, вышли из тумана 8D
}
//// Создаем превью-изображение
$idest = imagecreatetruecolor($dstw, $dsth);
imagefill($idest, 0, 0, $rgb);
imagecopyresampled($idest, $isrc, $dstx, $dsty, $srcx, $srcy, $dstw, $dsth, $srcw, $srch);
$ir_res = array("dstx" => $dstx, "dsty" => $dsty, "srcx" => $srcx, "srcy" => $srcy, "dstw" => $dstw, "dsth" => $dsth, "srcw" => $srcw, "srch" => $srch, "mime" => "image/".$d_ext);
switch ($d_ext) {
case 'jpg':
case 'jpeg':
$prev = imagejpeg($idest, $dest, $quality);
break;
case 'png':
// для PNG quality 0-9
$prev = imagepng($idest, $dest, (int)($quality / 10));
break;
case 'bmp':
// для BMP true - сжимать, false - исходное качество
$cmpr = ($quality < 50) ? true : false;
$prev = imagebmp($idest, $dest, $cmpr);
break;
case 'webp':
$prev = imagewebp($idest, $dest, $quality);
break;
}
imagedestroy($isrc);
imagedestroy($idest);
return $prev;
}
Обновления
v.1.3.b1
- Код причёсан и оптимизирован, добавленны все необходимые проверки и комментарии. Упрощена логика обработки размеров без потери функционала. Добавлен глобальный массив $ir_res который даст значения аргументов функции imagecopyresampled(). Так можно сразу получить, например, итоговые размеры превью, что бы не получать их потом из getimagesize().
v.1.2.b8
- Внесено изменение, которое добавляет опцию вывода обработанной картинки в файл или в трансляцию кода. Переработан интерфейс для скрипта. Добавлена опция демонстрации работающего скрипта (под спойлером под демонстрацией работы скрипта). Можно ставить 0% качества превью - вот такой пиксель-арт ;-)
v.1.2.b7
- Добавлена проверка для входных параметров и в алгоритме рассчета. Можно не задавать одну из сторон превью, тогда она будет высчитана пропорционально заданной стороне относительно исходного изображения.
v.1.2.b6
- Исправлены найденные ошибки в v.1.2.b5
v.1.2.b5
- Исправлены найденные ошибки в v.1.2.b4
v.1.2.b4
- Переписана логика вырезания картинки. Переписан алгоритм рассчетов размера изображения на выходе.
v.1
- первая версия для тестирования вывода картинки нужного размера.
Исправленные ошибки (присылайте найденные вами ошибки на e-mail: mrmiksar@mail.ru)
v.1.2.b5
- 7.11.12 обнаружена ошибка при условии создания квадратного превью. Если ширина больше, а высота меньше заданного квадрата, то высоту растягивало по заданной высоте, а должно по наименьшей высоте исходного изображения.
Так, например, для изображения 1030х603 px надо было создать превью по условию 800х800 px. Тогда должно создаваться превью 800х603, а создавалось 800х800.
v.1.2.b4
- обнаружено неправильное масштабирование вертикальной картинки. При задании размера превью (89-99)х100 для картинки Вертикальная - дельфины получается превью размером 100х88. Ошибка идентична предыдущей.
v.1.2.b4
- обнаружено неправильное масштабирование горизонтальной картинки. При задании размера превью 100х(67-99) для картинки Горизонтальная - Клубника получается превью размером 100х66. При задании размера превью 100х(99-75) для картинки Горизонтальная - Шахматы получается превью размером 100х75.
Имеем масштабирование по ширине.
С одной стороны - не происходит обрезание в смаштабированной картинке (т.к. придется перемасштабировать по высоте и, соответственно, ширина увеличится и станет более заданныx 100px и потребуется обрезать края, что бы получить изображение заданной ширины) и в изображении присутствует максимум информации от исходника, с другой стороны - заданные размеры не выдерживаются...
v.1
- первая модификация обрезает изображения не по центру, а смещенно влево и вниз. Однако заданные пропорции выдерживаются.