E
E
Evgeny Koryakin2021-07-20 08:07:24
PHP
Evgeny Koryakin, 2021-07-20 08:07:24

How to properly adapt this code to work with @2x?

Hello!
I have a module that automatically converts images to WebP

spoiler
<?php
function udisabled($imagepath)
{
  // Список запрещенных путей для преобразования
  $disabled_path = array(
    'dleimages', 'engine',
  );

  // Проверяем список запрещенных путей для преобразования
  foreach($disabled_path as $disabled)
  {
    if(strpos($imagepath, $disabled) !== FALSE) return false;
  }

  return true;
}

function uimages($html)
{
  global $config, $uconfig, $home_page;

  $htmlParser = new HtmlDocument();
  $page = $htmlParser->load($html);

  // Список форматов изображений разрешенных к преобразованию
  $allowed_extensions = array();

  if($uconfig['convert_png']) $allowed_extensions[] = 'png';

  if($uconfig['convert_jpg']) 
  {
    $allowed_extensions[] = 'jpg'; 
    $allowed_extensions[] = 'jpeg';
  }

  if($uconfig['convert_gif']) $allowed_extensions[] = 'gif';

  // Качество сжатия изображений
  $quality = intval($uconfig['image_quality']);

  if(empty($quality) OR $quality < 0)
  {
    $quality = 80;
  }

  foreach($page->find('[data-uwebp="true"] img') as $image)
  {
    // Проверяем какой стоит аттрибут src или data-src
    if(isset($image->src))
    {
      $imagepath = $image->src;
    } else if(isset($image->{'data-src'}))
    {
      $imagepath = $image->{'data-src'};
    }

    // Записываем в переменную путь к изображению, для использования в разметке
    $shema_image_path = $imagepath;

    // Проверяем список запрещенных путей для преобразования
    if(!udisabled($imagepath)) continue;

    // Проверяем, чтобы изображение находилось на сервере
    $addhome = false;

    if(strpos($imagepath, "http://") !== false OR strpos($imagepath, "https://") !== false)
    {
      if(strpos($imagepath, $home_page) === false) 
      {
        continue;
      } else {
        // Убираем URL сайта из пути изображения
        $imagepath = str_replace($home_page, "", $imagepath);
      }
    } else {
      $addhome = true;
    }

    // Информация об изображении
    $imageinfo = pathinfo($imagepath);

    // Путь изображения на сервере
    $image_on_server = ROOT_DIR . $imageinfo['dirname'] . '/' . $imageinfo['basename'];
    $image_webp_on_server = ROOT_DIR . $imageinfo['dirname'] . '/' . $imageinfo['filename'] . '.webp';
    $output_webp_image = str_replace(ROOT_DIR, "", $image_webp_on_server);

    // Проверяем наличие изображения на сервере, а также разрешен ли формат к преобразованию
    if(file_exists($image_on_server) === FALSE OR in_array($imageinfo['extension'], $allowed_extensions) === FALSE)
    {
      continue;
    }

    // Проверяем конвертировалось изображение ранее, если нет - конвертируем его
    if(!file_exists($image_webp_on_server))
    {
      // Если это GIF изображение и включен режим преобразования в анимированные WebP изображения
      if(mime_content_type($image_on_server) == "image/gif" AND $uconfig['convert_gif'] AND $uconfig['animate_webp'] AND is_animated_gif($image_on_server))
      {
        // Обязательно получаем размеры изображения для корректного преобразования в анимированный WebP
        $gif_size = getimagesize($image_on_server);
        
        try {
          $gifStream = new FileStream($image_on_server);

          $gifDecoder = new Decoder($gifStream);

          $gifRenderer = new Renderer($gifDecoder);

          $gifRenderer->start(function (FrameRenderedEvent $event) {
            $GLOBALS['frames'][] = getFrameData($event->decodedFrame->createGDImage(), $event->decodedFrame->getDuration() * 10);
          });

          $fileWEBP = "";
          $fileHeader = "";
          $fileContents = "";

          $fileContents .="VP8X";
          $headChunkSize = bytesToString(toUint32(10));

          $oVP8XflagsBin = "00010010 00000000 00000000 00000000";
          $oVP8Xflags = bytesToString(binaryToBytes($oVP8XflagsBin));

          $oCanvasSize = bytesToString(toUint24($gif_size[0] - 1)) . bytesToString(toUint24($gif_size[1] - 1));

          $fileContents .= $headChunkSize. $oVP8Xflags. $oCanvasSize;

          $fileContents .="ANIM";
          $animChunkSize = bytesToString(toUint32(6));

          $oLoopCount = str_repeat(chr(0), 2);

          $oBackGround = str_repeat(chr(0), 4);
          $fileContents .= $animChunkSize . $oBackGround . $oLoopCount;

          foreach ($GLOBALS['frames'] as $frame)
          {
            $fileContents .= "ANMF";
            $frameDataChunkSize = bytesToString(toUint32(strlen($frame['frameData']) + 16));

            $fOrigin = str_repeat(chr(0), 6);

            $fSize = $frame['width'] . $frame['height'];

            $fDuration = $frame['duration'];

            $fFlagsBin = "00000010";
            $fFlags = bytesToString(binaryToBytes($fFlagsBin));

            $fileContents .= $frameDataChunkSize . $fOrigin . $fSize . $fDuration . $fFlags . $frame['frameData'];
          }

          $fileSize = bytesToString(toUint32(strlen($fileContents) + 4));
          $fileHeader = "RIFF" . $fileSize . "WEBP";
          $fileWEBP = $fileHeader . $fileContents;

          if(!file_put_contents($image_webp_on_server, $fileWEBP))
          {
            continue;
          }

        } catch(RuntimeException $e) 
        {
          continue;
        }
      } else
      {
        \ImageConverter\convert($image_on_server, $image_webp_on_server, $quality);
      }
    }
    
     // Если в настройках CMS включена опция: 'Отложенная загрузка изображений'
    if($config['image_lazy']) 
    {
      $data_attr = 'data-srcset';
      
      $image->{'data-src'} = $image->src;
      $image->src = null;
      
    } else
    {
      $data_attr = 'srcset'; 
    }

    // Если включена разметка изображений schema.org
    if($uconfig['schema_org'])
    {
      $schema_org_html = "";

      // contentUrl или image – (URL) ссылка на изображение. Обязательное поле, если не заполнено thumbnail. Без заполнения одного из этих полей, данные не будут обработаны. Предпочтительно contentUrl, обязательно ссылка именно на файл изображения;
      //$image->attr['itemprop'] = "contentUrl";
      $schema_array['image'] = $shema_image_path;

      // Если нужно добавить главную страницу сайта к URL изображения
      if($addhome)
      {
        if($home_page[strlen($home_page) - 1] == "/")
        {
          $home_page = mb_substr($home_page, 0, -1);
        }

        $schema_array['image'] = $home_page . $imageinfo['dirname'] . '/' . $imageinfo['basename'];
      }

      // description – (Text) описание изображения;
      if(!empty($image->alt)) $schema_array['description'] = $image->alt;

      // Получаем размеры изображения
      if($imagesize = getimagesize($image_on_server))
      {
        list($width, $height, $type, $attr) = $imagesize;

        if($width > 0) $schema_array['width'] = $width . 'px';

        if($height > 0) $schema_array['height'] = $height . 'px';
      } 

      if(!empty($schema_array))
      {
        foreach($schema_array as $skey => $value)
        {
          $value = str_replace("&amp;amp;", "&amp;", htmlspecialchars(strip_tags(stripslashes($value)), ENT_QUOTES, $config['charset']));

          $schema_org_html .= '<meta itemprop="' . $skey . '" content="' . $value . '">';
        }
      }

      $webpTemplate = <<<HTML
<picture itemscope itemtype="http://schema.org/ImageObject">
<source type="image/webp" {$data_attr}="{$output_webp_image}">
{$image->outertext}
{$schema_org_html}
</picture>
HTML;
    } else {
      $webpTemplate = <<<HTML
<picture>
<source type="image/webp" {$data_attr}="{$output_webp_image}">
{$image->outertext}
</picture>      
HTML;
    }

    $image->outertext = $webpTemplate;
  }

  return $htmlParser->save();    
}
?>


In fact, this code converts the string into this code
<img srcset="image.png" src="image.png">

<picture itemscope="" itemtype="http://schema.org/ImageObject">
    <source type="image/webp" data-srcset="/image.webp" srcset="/image.webp">
    <img srcset="image.png" src="image.png">
    <meta itemprop="image" content="image.png">
    <meta itemprop="description" content="Title">
    <meta itemprop="width" content="128px">
    <meta itemprop="height" content="128px">
</picture>


But if there are two values ​​in srcset, like 2x, then it does not process it.
<img srcset="image.png, image-retina.png 2x" src="image.png">


How to make him eat and 2x?
<source type="image/webp" data-srcset="/image.webp" srcset="/image.webp, image-retina.webp 2x">

Answer the question

In order to leave comments, you need to log in

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question