Оптимизация изображений: WebP для сайта на Битрикс

После очередной «просьбы» гугла в сервисе PageSpeed Insights использовать современные форматы изображений, я решил оптимизировать изображения на одном из сайтов на Битрикс, добавив вывод слайдов в формате WebP. Для решения данной задачи я выбрал вариант использования библиотеки GD, коим и хочу поделиться. Так как эта библиотека является расширением для PHP, необходимо было убедиться, подключена ли она. Создал в корне сайта простой файл php:

<pre>
<?php var_dump(gd_info()); ?>
</pre>

и получил массив с неутешительным ответом.

["WebP Support"]=>
  bool(false)

Сайт, о котором я веду речь, расположен на виртуальном хостинге, поэтому какие-либо действия с настройками сервера проводить нет возможности, только через тех. поддержку. Забегая вперед скажу, что мне очень повезло, так как после вопроса в саппорт хостинга Бегет, мне сказали, что есть возможность перенести данный аккаунт на сервер с подключенной библиотекой. Уточнили удобное время для переноса аккаунта и после окончания работ я увидел желанное true. На этом предысторию закончил, пишем функции и выводим изображения в формате WebP.

Для начала я написал функцию, местами подсмотрел :), для конвертирования изображений из png и jpg в webp. Где её размещать, дело лично разработчика, у меня в папку php_interface добавлена папка inc и в ней все мои функции, подключенные в init.php. На случай, если GD библиотека «слетит», сделал проверку. Функция очень проста, я в нее передаю два параметра, тип файла и путь:

$gd_info = gd_info();

if($gd_info['WebP Support'] === true):
function convertImageWebp($file_type, $read_from_path) {

	$save_to_path = $read_from_path . '.webp';
	$output = '';

	$file = $read_from_path;
	if($file_type == 'image/png')
	{
		$image = imagecreatefrompng($file);
	}
	elseif($file_type == 'image/jpeg')
	{
		$image = imagecreatefromjpeg($file);
	}
	ob_start();
	imagejpeg($image,NULL,100);
	$cont = ob_get_contents();
	ob_end_clean();
	imagedestroy($image);
	$content = imagecreatefromstring($cont);
	imagewebp($content,$save_to_path);
	imagedestroy($content);

	if(filesize ( $save_to_path ) > 0)
	{
		$output = str_replace($_SERVER["DOCUMENT_ROOT"], '', $save_to_path);
	}

	return $output;
}
endif;

Я использую так называемый «ресайз изображений на лету», поэтому дальнейшие манипуляции в файле result_modifier.php необходимого шаблона. На этом сайте изображения выводятся в теге picture с использованием медиа-запросов, поэтому режем на три размера, проверяем функцию, конвертируем. Пример взят из шаблона слайдера:

if($arResult['ITEMS'])
{
	foreach ($arResult['ITEMS'] as $cell => $arItem)
	{
		$file = CFile::ResizeImageGet($arItem["DETAIL_PICTURE"]["ID"], Array("width" =>1920 , "height" => 1080),BX_RESIZE_IMAGE_EXACT, true);
		$file_1920_780 = CFile::ResizeImageGet($arItem["DETAIL_PICTURE"]["ID"], Array("width" =>1920 , "height" => 780),BX_RESIZE_IMAGE_EXACT, true);
		$file_996_560 = CFile::ResizeImageGet($arItem["DETAIL_PICTURE"]["ID"], Array("width" =>996 , "height" => 560),BX_RESIZE_IMAGE_EXACT, true);
		$file_600_338 = CFile::ResizeImageGet($arItem["DETAIL_PICTURE"]["ID"], Array("width" =>600 , "height" => 338),BX_RESIZE_IMAGE_EXACT, true);

		$arResult['ITEMS'][$cell]['DETAIL_PICTURE']['WIDTH'] = $file['width'];
		$arResult['ITEMS'][$cell]['DETAIL_PICTURE']['HEIGHT'] = $file['height'];
		$arResult['ITEMS'][$cell]['DETAIL_PICTURE']['SRC'] = $file['src'];
		$arResult['ITEMS'][$cell]['DETAIL_PICTURE']['1920_780']['SRC'] = $file_1920_780['src'];
		$arResult['ITEMS'][$cell]['DETAIL_PICTURE']['996_560']['SRC'] = $file_996_560['src'];
		$arResult['ITEMS'][$cell]['DETAIL_PICTURE']['600_338']['SRC'] = $file_600_338['src'];

		if (function_exists('convertImageWebp'))
		{
			$file_type = $arItem['DETAIL_PICTURE']['CONTENT_TYPE'];
			$img_webp_1920_780 = convertImageWebp($file_type, $_SERVER["DOCUMENT_ROOT"] . $file_1920_780['src']);
			$img_webp_996_560 = convertImageWebp($file_type, $_SERVER["DOCUMENT_ROOT"] . $file_996_560['src']);
			$img_webp_600_338 = convertImageWebp($file_type, $_SERVER["DOCUMENT_ROOT"] . $file_600_338['src']);
			$arResult['ITEMS'][$cell]['DETAIL_PICTURE']['1920_780']['SRC_WEBP'] = $img_webp_1920_780;
			$arResult['ITEMS'][$cell]['DETAIL_PICTURE']['996_560']['SRC_WEBP'] = $img_webp_996_560;
			$arResult['ITEMS'][$cell]['DETAIL_PICTURE']['600_338']['SRC_WEBP'] = $img_webp_600_338;
		}
	}
	
}

Выводим:

<picture>
    <source srcset="<?=$arItem['DETAIL_PICTURE']['1920_780']['SRC_WEBP']?>" type="image/webp" media="(min-width: 996px)">
    <source srcset="<?=$arItem['DETAIL_PICTURE']['1920_780']["SRC"]?>" media="(min-width: 996px)">
    <source srcset="<?=$arItem['DETAIL_PICTURE']['996_560']['SRC_WEBP']?>" type="image/webp" media="(min-width: 600px)">
    <source srcset="<?=$arItem['DETAIL_PICTURE']['996_560']["SRC"]?>" media="(min-width: 600px)">
    <source srcset="<?=$arItem["DETAIL_PICTURE"]['600_338']["SRC_WEBP"]?>" type="image/webp">
    <img src="<?=$arItem["DETAIL_PICTURE"]['600_338']["SRC"]?>" alt="<?=$arItem["NAME"]?>" alt="<?=$arItem["NAME"]?>">
</picture>

 

Всего комментариев - 1.

  1. Не увидел кеширования, по идеи всякий раз при обращении будет обработка картинки, будет здорово, если будет добавленно кеширование и когда картинка обработается то сохранится путь к ней в кеше, и при следующем запросе не будет вновь задействована процессора мощь, а взято все из кеша.
    А так спасибо за решение, перешел к Вам из твитера прочитал статью.

Добавить комментарий для Андрей Отменить ответ

Ваш адрес email не будет опубликован. Обязательные поля помечены *

*
*
*

Нажимая кнопку «Отправить комментарий» я даю свое согласие на использование и обработку моих персональных данных в соответствии с ч. 1 ст. 9 ФЗ от 27.07.2006 г. № 152 «О персональных данных»