Оптимизация изображений: 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>

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

Готовый модуль OptiPic CDN – простое решение проблемы «Используйте современные форматы изображений» согласно рекомендациям Google Pagespeed Insights.

Он автоматически конвертирует изображения в современный формат Webp (для браузеров, которые поддерживают webp). А для браузеров, которые не поддерживают webp, OptiPic оптимизирует (сжимает) старые форматы png и jpeg. Дополнительными преимуществами OptiPic CDN является то, что он кэширует изображения в соответствии с требованиями Google, ускоряет их загрузку в браузере, а также защищает авторство картинок через мета-теги EXIF и IPTC.

Видео инструкция по установке и настройке модуля OptiPic CDN для Битрикс









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

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

  2. Доброго дня.
    Пытаюсь реализовать конвертацию, но ничего не выходит.
    Делаю все так же:
    1 Вынес функцию в отдельный файл
    2 В init.php прописал путь
    3 В result_modifier шаблона подключил класс через use, скопировал ваш код
    4 Для вывода так же использовал ваш код
    Но ничего не выходит, конвертация не выполняется. Права доступа подходят, все должно выполняться, но не работает ни в какую.

    1. Доброго дня, Артём! После Вашего комментария проверил работу функции на нескольких сайтах, всё ок 🙂 Не видя Вашего кода даже не знаю что подсказать. Напишите в личку, попробуем разобраться что не так. Ну и var_dump частенько спасает в таких случаях 🙂

  3. Здравствуйте. Функция отлично работает, кроме картинок в png с прозрачным фоном — фон становится черным. Это можно как-то вылечить?

    1. Здравствуйте, Роман! Чтобы конвертировать PNG в WebP с прозрачностью, нужно немного переписать функцию,
      заменить:

      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($file_type == 'image/png')
      {
      	$image = imagecreatefrompng($file);
      	imagealphablending ($image, true);
      	imagesavealpha($image, true);
      }
      elseif($file_type == 'image/jpeg')
      {
      	$image = imagecreatefromjpeg($file);
      }
      imagewebp($image, $save_to_path);
      imagedestroy($image);
      

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

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

*
*
*

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