Как обрезать и уменьшить изображение в 1С-Битрикс через CFile::ResizeImageGet

  • 2697
   
Разделы

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


По возможности указываю ссылки на источники.


Копируйте, комментируйте, переделывайте, пользуйтесь. Кому не жалко, оставляйте ссылку на источник.

Частный вебмастер по разработке сайтов на 1С Битрикс и WordPress

При работе с инфоблоками 1С-Битрикс часто требуется вывести не оригинальное изображение, а его уменьшенную копию: например, превью новости, карточки товара, элемента каталога или галереи.

Коротко: для уменьшения и обрезки изображений в 1С-Битрикс используется CFile::ResizeImageGet(). BX_RESIZE_IMAGE_EXACT обрезает изображение до точного размера, а BX_RESIZE_IMAGE_PROPORTIONAL уменьшает его с сохранением пропорций.

Простой пример CFile::ResizeImageGet

Допустим, в свойстве инфоблока ATT_IMG хранится изображение. В VALUE находится ID файла:

<?php
$imageId = $arResult['PROPERTIES']['ATT_IMG']['VALUE'];
?>

Получим из него превью размером 300×200:

<?php
$image = CFile::ResizeImageGet(
    $imageId,
    [
        'width'  => 300,
        'height' => 200,
    ],
    BX_RESIZE_IMAGE_EXACT,
    true
);
?>

После выполнения метода в переменной $image будет массив с данными готового изображения.

Array
(
    [src] => /upload/resize_cache/...
    [width] => 300
    [height] => 200
)

Путь к уменьшенной картинке находится в $image['src'], а фактические размеры — в $image['width'] и $image['height'].

Вывести изображение можно так:

<?php if ($image): ?>
    <img
        src="<?= $image['src'] ?>"
        width="<?= $image['width'] ?>"
        height="<?= $image['height'] ?>"
        alt="<?= htmlspecialcharsbx($arResult['NAME']) ?>"
        loading="lazy"
    >
<?php endif; ?>

Параметры CFile::ResizeImageGet

В наиболее распространённом варианте метод вызывается так:

<?php
CFile::ResizeImageGet(
    $fileId,
    $size,
    $resizeType,
    $getSize
);
?>

$fileId

ID исходного файла в Битриксе.

$imageId = $arResult['PROPERTIES']['ATT_IMG']['VALUE'];

$size

Размер изображения задаётся массивом:

[
    'width'  => 300,
    'height' => 200,
]

$resizeType

Определяет способ изменения размера изображения.

Режим Что делает
BX_RESIZE_IMAGE_EXACT Создаёт изображение точного размера и при необходимости обрезает лишние края
BX_RESIZE_IMAGE_PROPORTIONAL Уменьшает изображение с сохранением пропорций без обрезки
BX_RESIZE_IMAGE_PROPORTIONAL_ALT Альтернативный пропорциональный режим изменения размера

$getSize

Если четвёртым параметром передать true, в результате будут доступны фактические ширина и высота созданного изображения:

$image['width'];
$image['height'];

Обрезка изображения до точного размера

Если нужно получить изображение строго заданного размера, например 300×200, используется BX_RESIZE_IMAGE_EXACT.

<?php
$image = CFile::ResizeImageGet(
    $imageId,
    [
        'width'  => 300,
        'height' => 200,
    ],
    BX_RESIZE_IMAGE_EXACT,
    true
);
?>

Битрикс уменьшит изображение и при необходимости обрежет его края, чтобы итоговая картинка получилась точно 300×200.

Такой режим удобно использовать для:

  • превью статей и новостей;
  • карточек товаров;
  • элементов каталога;
  • фотографий сотрудников;
  • галерей с одинаковыми миниатюрами.
Совет: если все карточки на странице должны иметь одинаковую высоту, обычно лучше использовать BX_RESIZE_IMAGE_EXACT.

Уменьшение изображения без обрезки

Если изображение нужно показать полностью и обрезать его нельзя, используется BX_RESIZE_IMAGE_PROPORTIONAL.

<?php
$image = CFile::ResizeImageGet(
    $imageId,
    [
        'width'  => 600,
        'height' => 400,
    ],
    BX_RESIZE_IMAGE_PROPORTIONAL,
    true
);
?>

При таком режиме исходные пропорции сохраняются, а заданные width и height определяют максимальную область, в которую должно поместиться изображение.

Например, квадратное изображение 1200×1200 при ограничении 600×400 получится размером примерно 400×400.

BX_RESIZE_IMAGE_EXACT или BX_RESIZE_IMAGE_PROPORTIONAL

Задача Режим
Получить строго одинаковые превью BX_RESIZE_IMAGE_EXACT
Сохранить изображение целиком BX_RESIZE_IMAGE_PROPORTIONAL
Карточки товаров или новости BX_RESIZE_IMAGE_EXACT
Логотипы, схемы, документы BX_RESIZE_IMAGE_PROPORTIONAL

Полный пример для свойства инфоблока

Готовый пример для использования в шаблоне компонента:

<?php
$imageId = $arResult['PROPERTIES']['ATT_IMG']['VALUE'] ?? null;

$image = null;

if ($imageId) {
    $image = CFile::ResizeImageGet(
        $imageId,
        [
            'width'  => 600,
            'height' => 400,
        ],
        BX_RESIZE_IMAGE_EXACT,
        true
    );
}
?>

<?php if ($image): ?>
    <img
        src="<?= $image['src'] ?>"
        width="<?= $image['width'] ?>"
        height="<?= $image['height'] ?>"
        alt="<?= htmlspecialcharsbx($arResult['NAME']) ?>"
        loading="lazy"
    >
<?php endif; ?>

Проверка $imageId нужна, чтобы не вызывать CFile::ResizeImageGet(), если свойство изображения не заполнено.

Как уменьшить изображения из множественного свойства

Если свойство ATT_IMG множественное, в VALUE будет находиться массив ID файлов.

Например, создадим для каждого изображения превью размером 300×200:

<?php
$images = $arResult['PROPERTIES']['ATT_IMG']['VALUE'] ?? [];

foreach ($images as $imageId) {

    $image = CFile::ResizeImageGet(
        $imageId,
        [
            'width'  => 300,
            'height' => 200,
        ],
        BX_RESIZE_IMAGE_EXACT,
        true
    );

    if (!$image) {
        continue;
    }
    ?>

    <div class="gallery__item">
        <img
            src="<?= $image['src'] ?>"
            width="<?= $image['width'] ?>"
            height="<?= $image['height'] ?>"
            alt="<?= htmlspecialcharsbx($arResult['NAME']) ?>"
            loading="lazy"
        >
    </div>

    <?php
}
?>

Теперь все превью будут иметь одинаковый размер независимо от размеров и пропорций оригинальных фотографий.

Превью с открытием оригинала через Fancybox

Для галереи удобно выводить маленькое превью, а при клике открывать оригинальную фотографию.

Путь к оригинальному файлу можно получить через CFile::GetPath().

<?php
$images = $arResult['PROPERTIES']['ATT_IMG']['VALUE'] ?? [];

foreach ($images as $imageId) {

    $preview = CFile::ResizeImageGet(
        $imageId,
        [
            'width'  => 300,
            'height' => 200,
        ],
        BX_RESIZE_IMAGE_EXACT,
        true
    );

    $original = CFile::GetPath($imageId);

    if (!$preview || !$original) {
        continue;
    }
    ?>

    <a
        href="<?= $original ?>"
        data-fancybox="gallery"
    >
        <img
            src="<?= $preview['src'] ?>"
            width="<?= $preview['width'] ?>"
            height="<?= $preview['height'] ?>"
            alt="<?= htmlspecialcharsbx($arResult['NAME']) ?>"
            loading="lazy"
        >
    </a>

    <?php
}
?>

В результате на странице загружаются небольшие превью, а оригинальный файл открывается только после нажатия.

Обработка изображений в result_modifier.php

Если в шаблоне становится много логики, обработку изображений лучше перенести в result_modifier.php.

Например, заранее подготовим массив галереи:

<?php
$arResult['GALLERY'] = [];
$images = $arResult['PROPERTIES']['ATT_IMG']['VALUE'] ?? [];
foreach ($images as $imageId) {
    $preview = CFile::ResizeImageGet(
        $imageId,
        [
            'width'  => 300,
            'height' => 200,
        ],
        BX_RESIZE_IMAGE_EXACT,
        true
    );

    if (!$preview) {
        continue;
    }

    $arResult['GALLERY'][] = [
        'ORIGINAL' => CFile::GetPath($imageId),
        'PREVIEW'  => $preview['src'],
        'WIDTH'    => $preview['width'],
        'HEIGHT'   => $preview['height'],
    ];
}

После этого в template.php останется только вывод HTML:

<?php foreach ($arResult['GALLERY'] as $image): ?>

    <a
        href="<?= $image['ORIGINAL'] ?>"
        data-fancybox="gallery"
    >
        <img
            src="<?= $image['PREVIEW'] ?>"
            width="<?= $image['WIDTH'] ?>"
            height="<?= $image['HEIGHT'] ?>"
            alt="<?= htmlspecialcharsbx($arResult['NAME']) ?>"
            loading="lazy"
        >
    </a>

<?php endforeach; ?>
Совет: если подготовка данных занимает несколько десятков строк, лучше выполнять её в result_modifier.php, а template.php оставить только для вывода.

Где хранятся уменьшенные изображения

Созданные через CFile::ResizeImageGet() изображения Битрикс сохраняет в каталоге /upload/resize_cache/.

При следующем запросе изображения с такими же параметрами используется уже созданная копия.

Поэтому самостоятельно создавать отдельные каталоги для превью в большинстве случаев не требуется.

Важно: не удаляйте содержимое /upload/resize_cache/ без необходимости. После очистки Битрикс будет создавать нужные превью заново.

Короткий рабочий пример

Если нужно просто получить превью размером 300×200 с обрезкой лишней части изображения:

<?php
$image = CFile::ResizeImageGet(
    $imageId,
    [
        'width'  => 300,
        'height' => 200,
    ],
    BX_RESIZE_IMAGE_EXACT,
    true
);
?>

Путь к готовой картинке:

$image['src'];

Фактические размеры:

$image['width'];
$image['height'];

Путь к оригинальному файлу:

CFile::GetPath($imageId);

Итог

Для уменьшения и обрезки изображений в 1С-Битрикс в большинстве случаев достаточно стандартного метода CFile::ResizeImageGet().

  • BX_RESIZE_IMAGE_EXACT — когда нужен точный размер с обрезкой.
  • BX_RESIZE_IMAGE_PROPORTIONAL — когда изображение нужно уменьшить целиком без обрезки.
  • CFile::GetPath() — когда требуется получить путь к оригинальному файлу.

Для небольших шаблонов обработку можно выполнять непосредственно в template.php. Если логики становится много, удобнее заранее подготовить данные в result_modifier.php.

Комментарии

CAPTCHA
Комментарий отправлены на валидацию!