Изменение размера изображения

Проблема большой фотогалереи возникла на корпоративном портале от 1С-Битрикс. За более чем год использования ограничения на максимальный размер файла размер папки /upload/ содержащей все загруженные файлы стал более 20 GB.

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

Скрипт делает следующее:
1) Рекурсивно обходит все файлы в директории из которой запущен;
2) Если файл имеет расширение gif, png или jpeg, размер более 500 Kb, высоту более 850px и ширину более 640 px сжимает его пропорционально до этих параметров.

Требования:

1) На сервере должна быть установлена библиотека gd для php.
2) Если файлов много, сжатие займет значительное время, поэтому придется запускать из консоли, следовательно потребуется ssh.
3) У скрипта должно быть право на изменение изображений.

Скрипт с комментариями приведен ниже:

[sourcecode lang="php"]
#!/usr/local/bin/php
$max_size)&&($size[0]<$width)&&($size[1]>height)){
 $resized_files++;
 // Вычилсить горизонтальное соотношение
 $gor = $width  / $size[0];
 // Вертикальное соотношение
 $ver = $height / $size[1];  

 // Если не задана высота, вычислить изходя из ширины, пропорционально
 if ($height == 0) {
 $ver = $gor;
 $height  = $ver * $size[1];
 }
 // Так же если не задана ширина
 elseif ($width == 0) {
 $gor = $ver;
 $width   = $gor * $size[0];
 }

 // Формируем размер изображения
 $ratio   = min($gor, $ver);
 // Нужно ли пропорциональное преобразование
 if ($gor == $ratio)
 $use_gor = true;
 else
 $use_gor = false;

 $new_width   = $use_gor  ? $width  : floor($size[0] * $ratio);
 $new_height  = !$use_gor ? $height : floor($size[1] * $ratio);
 $new_left    = $use_gor  ? 0 : floor(($width - $new_width)   / 2);
 $new_top     = !$use_gor ? 0 : floor(($height - $new_height) / 2);

 $picsrc  = $picfunc($src);
 // Создание изображения в памяти
 $picout = imagecreatetruecolor($width, $height);

 // Заполнение цветом
 imagefill($picout, 0, 0, $color);
 // Нанесение старого на новое
 imagecopyresampled($picout, $picsrc, $new_left, $new_top, 0, 0, $new_width, $new_height, $size[0], $size[1]);

 // Создание файла изображения
 imagejpeg($picout, $out, $quality);

 // Очистка памяти
 imagedestroy($picsrc);
 imagedestroy($picout);

 return true;
 } else {
 return false;
 }
 } else {
 return false;
 }
}

function scan_dir($dirname)
 {
 // Объявляем переменные замены глобальными
 global $count_files;
 global $result_width, $result_height, $max_size, $resized_files;
 // Открываем текущую директорию
 $dir = opendir($dirname);
 // Читаем в цикле директорию
 while (($file = readdir($dir)) !== false)
 {
 // Если файл обрабатываем его содержимое
 if($file != '.' && $file != '..')
 {
 // Если имеем дело с файлом - производим в нём замену
 if(is_file($dirname.'/'.$file))
 {
 $str = $_SERVER['DOCUMENT_ROOT'].$_SERVER["REQUEST_URI"].$dirname."/".$file;
 $str = str_replace("//", "/", $str);
 $str = str_replace("./", "", $str);
 $str = str_replace("//", "/", $str);
 echo("Try to resize file # ".$count_files." \n ");
 img_resize($str, $str, $result_width, $result_height);
 // echo($_SERVER["DOCUMENT_ROOT"].$_SERVER["REQUEST_URI"].$dirname."");
 $count_files++;
 }
 // Если перед нами директория, вызываем рекурсивно
 // функцию scan_dir
 if(is_dir($dirname."/".$file))
 {
 scan_dir($dirname."/".$file);
 }
 }
 }
 // Закрываем директорию
 closedir($dir);
 } 

$time1 = time();
$dirname = "./"; // Текущая директория
 scan_dir($dirname);  // Вызов рекурсивной функции
 echo "All files: $count_files \n ";
 echo "Resized files: $resized_files \n ";
$time2 = time();
 echo("Total time:".($time2-$time1)." sec \n");


?>
[/sourcecode]

Результат работы оказался таким: скрипт работал чуть более 4х часов, изменил чуть более
20 000 изображений. Размер папки /upload/ стал 5 Gb, т.е. уменьшился в 4 раза!

Скачать скрипт можно здесь.