Оптимизация изображений в Sngine: Как уменьшить вес фото в 15 раз без потери качества
1. Проблема: Качество убивают дважды
Если вы владелец сайта на движке Sngine, вы наверняка сталкивались с ситуацией, когда пользователи жалуются на «мыло» и пикселизацию на фотографиях. Особенно обидно, когда человек загружает шикарный снимок с камеры на 12–15 Мб, а система превращает его в нечто ужасное.
Почему так происходит?
По умолчанию Sngine работает по стандартному алгоритму:
-
Он не меняет физические размеры изображения (ширину и высоту).
-
Он сжимает качество (уровень JPEG).
Представьте: пользователь загружает фото 6000×4000 px (12 Мб). Система «ресайзит» его, оставляя те же 6000×4000 px, но просто «выкидывая» цветовую информацию. В итоге:
- Размер файла становится чуть меньше (но не критично).
- Картинка превращается в пиксельную «лестницу» на каждом углу.
- Страница грузится долго из-за огромного полотна.
Нам показалось это нелогичным. Зачем хранить изображение с бешеным разрешением, если оно всё равно отображается в ленте шириной 800px?
2. Решение: Атакуем разрешение, а не качество
Мы пошли другим путем. Вместо того чтобы убивать качество при огромном разрешении, мы уменьшаем само разрешение до разумных пределов, сохраняя при этом оригинальные пропорции и четкость.
Логика простая: Сделать максимальную сторону изображения не более 1000 пикселей.
Это магическое число, которое обеспечивает: * Идеальный вид на мобильных устройствах и десктопах. * Сохранение естественной резкости (без пикселизации). * Уменьшение веса в 10–15 раз.
Что мы сделали с кодом?
Мы модифицировали системный файл class-image.php. Теперь при загрузке картинка скейлится не «в ширину экрана», а ограничивается по высоте (или ширине) до 1000px.
Пример из жизни:
- Было: 6000×4000 px | 12 Мб * Стало: ~1500×1000 px (пропорционально) | 0.8 Мб
- Разница: вес меньше в 15 раз! Качество — как при просмотре на ретина-экране.
3. Инструкция по внедрению
Внимание! Перед редактированием файлов обязательно сделайте резервную копию сайта и базы данных.
- Откройте файл /includes/class-image.php
- Перепишите функцию public function save, заменив код тем, что указан ниже.
-
Проверьте, что есть закрывающие скобки
}- их должно быть в конце 4 штуки (в самом файле class-image.php, а не в нашем коде)!
/**
* save
*
* @param string $path
* @param string $quality (high|medium|low)
* @param int|null $maxSize Максимальное значение для ширины/высоты (по умолчанию 1000px)
* @return void
* @throws Exception
*/
public function save($path, $quality = 'medium', $maxSize = 1000)
{
// Подготовка директории
if (!file_exists(dirname($path))) {
mkdir(dirname($path), 0777, true);
}
// Настройки качества
switch ($quality) {
case 'high':
$quality = 100;
$compression = 1;
break;
case 'low':
$quality = 50;
$compression = 7;
break;
default:
$quality = 85;
$compression = 3;
break;
}
// Текущие размеры
$currentWidth = $this->getWidth();
$currentHeight = $this->getHeight();
$imgToSave = $this->_img;
// Проверяем, нужно ли масштабировать
if ($currentWidth > $maxSize || $currentHeight > $maxSize) {
// Вычисляем коэффициент масштабирования
$ratio = min($maxSize / $currentWidth, $maxSize / $currentHeight);
$newWidth = (int)($currentWidth * $ratio);
$newHeight = (int)($currentHeight * $ratio);
// Создаем новое изображение
$resizedImg = imagecreatetruecolor($newWidth, $newHeight);
// Сохраняем прозрачность для PNG
if ($this->_img_type == 'image/png') {
imagealphablending($resizedImg, false);
imagesavealpha($resizedImg, true);
}
// Масштабируем с ресамплингом
imagecopyresampled(
$resizedImg, $this->_img,
0, 0, 0, 0,
$newWidth, $newHeight,
$currentWidth, $currentHeight
);
$imgToSave = $resizedImg;
}
// Сохранение в зависимости от типа
try {
switch ($this->_img_type) {
case 'image/jpeg':
case 'image/jpg':
if (!imagejpeg($imgToSave, $path, $quality)) {
throw new Exception(__("Failed to save JPEG image"));
}
break;
case 'image/png':
imagealphablending($imgToSave, false);
imagesavealpha($imgToSave, true);
if (!imagepng($imgToSave, $path, $compression)) {
throw new Exception(__("Failed to save PNG image"));
}
break;
case 'image/gif':
if (!imagegif($imgToSave, $path)) {
throw new Exception(__("Failed to save GIF image"));
}
break;
case 'image/webp':
if (!imagewebp($imgToSave, $path, $quality)) {
throw new Exception(__("Failed to save WebP image"));
}
break;
default:
throw new Exception(__("Unsupported image type: {$this->_img_type}"));
}
} finally {
// Очищаем временное изображение если оно создавалось
if (isset($resizedImg) && $resizedImg !== $this->_img) {
imagedestroy($resizedImg);
}
}
}
4. Финальная настройка
- Прейдите в Админ-панель → Настройки → Загрузки и выберите Качество фотографии: Фотографии среднего качества со средним сжатием

- После всех манипуляций обязательно очистите кэш браузера и кэш Sngine (Админ-панель → Инструменты → Уборщик мусора → Удаление скомпилированных файлов шаблонов).
5. Результат: Почему это круто
- Экономия дискового пространства до 90%. Ваш хостинг скажет вам спасибо.
- Скорость загрузки страниц вырастает в разы (меньше мегабайт скачивается).
- Google PageSpeed будет любить ваш сайт за правильную работу с изображениями.
- Никакой пикселизации. Глаз видит четкую картинку, а не артефакты сжатия.
Единственное ограничение: если на вашем сайте пользователям нужно приближать (зумить) изображения до 100% масштаба, чтобы рассмотреть мелкие детали (например, вы продаете запчасти или арт), этот метод не подойдет. Но для 90% социальных сетей, блогов и досок объявлений — это идеал.
Сделал. Спасибо!