Ширина превью:
Высота превью:
Выбрать файл:
Выбрать качество превью:
ИСХОДНОЕ ИЗОБРАЖЕНИЕ
300px X 500px; q:original
РЕЗУЛЬТАТ ОБРАБОТКИ
300px X 500px; q:100%

КОД СКРИПТА 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($imstrpos($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 == && $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 >= && $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($destPATHINFO_EXTENSION)) : $s_ext// Формат создаваемого превью
    
$isrc    $icfunc($src); // Создание исходного изображения

    // Ширина превью больше/равна исходнику, высота превью меньше исходника
    // вырезать середину из исходника высотой превью $dh
    
if ($iw <= $dw && $ih $dh) {
        
$srcy round((($srch $dh) / 2), 0PHP_ROUND_HALF_DOWN);
        
$srch $dh;

    
// Ширина превью меньше исходника, высота превью больше/равна исходнику
    // вырезать середину из исходника шириной превью $dw
    
} elseif ($iw $dw && $ih <= $dh) {
        
$srcx round((($srcw $dw) / 2), 0PHP_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($idest00$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
- первая модификация обрезает изображения не по центру, а смещенно влево и вниз. Однако заданные пропорции выдерживаются.
Author: Mr.Miksar © 2009 - 2026