Ресайз изображений на Bitrix D7
Недавно мне пришла задача по созданию своего хранилища изображений на сайте. Там должны храниться изображения после ресайза по заранее заданным модификаторам.
Очень не хотелось использовать старое ядро, и я начал искать решение на D7. В документации, разумеется, я ничего не нашел, статей тоже. Однако, посмотрев, как работает CFile под капотом обнаружил, что битрикс скрывает в себе большой кусок функционала, который может вам пригодиться. Вот об этом и расскажу :)
Когда CFile уже не подходит
Моей задачей было одновременно провести ресайз, создать хранилище для модифицированных изображений, а также создать инструменты для очистки, проверки целостности нового хранилища.
Главная проблема CFile в том, что все изображения после ресайза попадают в /upload и изменить это никак нельзя. Кроме того, в методе ResizeImageFile (а в конечном счете при ресайзе вызывается именно он) достаточно много лишних проверок и операций, которые не всегда к месту.
В целом - CFile недостаточно гибкий и маневренный т.к. написан под все возможные задачи одновременно. Поэтому стоит понимать как он устроен под капотом, чтобы в случае появления нестандартной задачи не искать костыли, как это делал я.
Готовим ресайз по-новому
Ресайзом занимается класс \Bitrix\Main\File\Image. Сразу посмотрим, как это выглядит в действии.
<?php
// Путь до исходного файла
$src = '/path/to/file';
// Создаем инстанс класса для работы с этим изображением
$srcImage = new \Bitrix\Main\File\Image($src);
// Собираем информацию о размерах и типе изображения
$srcInfo = $srcImage->getInfo();
// Информацию конвертируем в объект прямоугольника
$srcRectangle = $srcInfo->toRectangle();
// Задаем нужную ширину после ресайза
$needleWidth = 100;
// Задаем нужную высоту после ресайза
$needleHeight = 200;
// Создаем объект прямоугольника с нужными размерами
$needleRectangle = new \Bitrix\Main\File\Image\Rectangle(
$needleWidth,
$needleHeight
);
// Путь до файла после ресайза (куда положить и с каким названием)
$dst = '/path/to/resized/file';
// Копируем
copy($src, $dst);
// Инстанс класса для работы с изображением (кладем путь после ресайза)
$dstImage = new \Bitrix\Main\File\Image($dst);
// Загружаем данные файла для будущей конвертации
$dstImage->load();
// Проводим ресайз
$dstImage->resize($srcRectangle, $needleRectangle);
// Качество будущего файла
$quality = 95;
// Формат будущего файла
$format = \Bitrix\Main\File\Image::FORMAT_JPEG;
// Сохраняем файл
$dstImage->saveAs($dst, $quality, $format);Т.е. фактически вся суть сводится к тому, что мы создаем 2 объекта Rectangle - один с исходными размерами, другой с необходимыми нам размерами. А дальше сохраняем получившийся файл.
Выходные форматы файла поддерживаются следующие:
- JPEG -
\Bitrix\Main\File\Image::FORMAT_JPEG - WEBP -
\Bitrix\Main\File\Image::FORMAT_WEBP - BMP -
\Bitrix\Main\File\Image::FORMAT_BMP - GIF -
\Bitrix\Main\File\Image::FORMAT_GIF - PNG -
\Bitrix\Main\File\Image::FORMAT_PNG
Кроме того, функционал позволяет накладывать фильтры пост-обработки и водные знаки.
Пример фильтра пост-обработки
Попробуем создать самый простой фильтр.
// Добавить после $dstImage->load() $dstImage->filter(\Bitrix\Main\File\Image\Mask::createSharpen(10));
Да, этот тот самый фильтр sharpen, единственный на данный момент реализованный командой битрикса. Он добавляет резкости изображению. Соответственно 10 - это уровень резкости. Можно поиграться с этим параметром, но работает он так же, как и в CFile.
Но самое интересное в том, что оказывается из-коробки есть возможность создавать свои фильтры!
Делается это с помощью класса \Bitrix\Main\File\Image\Mask. Свой фильтр нужно добавить при создании инстанса класса. По умолчанию это выглядит так:
// Это маска по-умолчанию $mask = [[1, 1, 1], [1, 1, 1], [1, 1, 1]]; // Если закинем пустоту, создастся маска выше $filter = new \Bitrix\Main\File\Image\Mask($mask);
Заглянем внутрь этого класса. Выше мы использовали единственный созданный вендором фильтр с помощью метода createShapren. Вот этот метод изнутри:
$mask = null;
if ($precision > 0) {
$k = 1.0/((int)$precision);
$mask = [
[-$k, -$k, -$k],
[-$k, 1+8*$k, -$k],
[-$k, -$k, -$k],
];
}
return new static($mask);Думаю, теперь у вас сложилось примерное понимание, по какому принципу можно создавать свои фильтры.
Пример создания водного знака
С водным знаком ситуация примерно такая же, как и в старом ядре
// Добавить после $dstImage->load()
$watermarkParams = [
'name' => 'watermark',
'position' => 'bottomright',
'type' => 'image',
'size' => 'real',
'file' => $_SERVER['DOCUMENT_ROOT'] . '/upload/copy.png',
'fill' => 'exact'
];
$watermark = \Bitrix\Main\File\Image\Watermark::createFromArray(
$watermarkParams
);
$dstImage->drawWatermark($watermark);Параметры ничем не отличаются от параметров старого ядра, немного только меняется сам принцип установки.
Итого
Мы одновременно рассмотрели новый более гибкий способ ресайза изображений от битрикса, а также разобрались как работает изнутри ресайз от CFile под капотом.
Если тебе понравилась статья - обязательно оцени ее, буду признателен! Если есть вопросы - пиши под статьей или в ТГ.