Search code examples
phpregeximageamp-html

How to get src of a image inside ampify_img function


I'm using ampify_img to convert regular images tags to amp image tags. So:

    <img src="dir/whatever/photo.jpg" alt="Whatever">

Is converted to:

    <amp-img src="dir/whatever/photo.jpg" layout="responsive" class="i-amphtml-element"></amp-img>

Problem is: To be a valid markup for amp width and height must be set in this converted tag. And I couldn't figure out how to extract src into the function that converts the images and write in the new tag. I know that I can get image sizes with PHP getimagesize() but can't figure out where this is. I'm not good at regular expressions which probably makes it harder to reach the goal.

Ampify default image function:

<?php
/**
 * Replace img tag with amp-img
 *
 * <amp-img src="[src]"
 *   width="[width]"
 *   height="[height]"
 *   layout="responsive"
 *   alt="[alt]">
 * </amp-img>
 *
 */
function ampify_img ($html) {
  preg_match_all("#<img(.*?)\\/?>#", $html, $matches);
  foreach ($matches[1] as $key => $m) {
    preg_match_all('/(alt|src|width|height)=("[^"]*")/i', $m, $matches2);
    $amp_tag = '<amp-img ';
    foreach ($matches2[1] as $key2 => $val) {
      $amp_tag .= $val .'='. $matches2[2][$key2] .' ';
    }
    $amp_tag .= 'layout="responsive"';
    $amp_tag .= '>';
    $amp_tag .= '</amp-img>';
    $html = str_replace($matches[0][$key], $amp_tag, $html);
  }
  return $html;
}

I tried to extract getimagesize() from $matches2[2][$key2] or $matches2[2] or $matches without success. I think it's more knowing where to extract the information to write to $amp_tag than anything else.

<?php
// comments where i tried to get info
function ampify_img ($html) {
  preg_match_all("#<img(.*?)\\/?>#", $html, $matches);
  foreach ($matches[1] as $key => $m) {
    preg_match_all('/(alt|src|width|height)=("[^"]*")/i', $m, $matches2);
    $amp_tag = '<amp-img ';
    foreach ($matches2[1] as $key2 => $val) {
      $amp_tag .= $val .'='. $matches2[2][$key2] .' '; // guess it can be here and possibly width and height can be writed here
    }
    $amp_tag .= 'layout="responsive"'; // certainly width and height can be writed here if we can get each image src at conversion and call PHP getimagesize
    $amp_tag .= '>';
    $amp_tag .= '</amp-img>';
    $html = str_replace($matches[0][$key], $amp_tag, $html);
  }
  return $html;
}

Solution

  • I found a solution that does not involve using the ampify_img function but only the amp itself, changing the layout. For those who once have the same difficulty, having to implement the amp converting their <img> tag images to <amp-img> tag on the fly, this is a solution, but the image layout is fixed, preserving the aspect ratio. .

    I also don't know what cpu and ram would consume to check each image size in long content and write in the tag. But I think it would be the ideal alternative, writing the specific widths and heights for each image, not assigning a fixed layout.

    Solution was very simple to implement:

    function img_to_amp ($html) {
      preg_match_all("#<img(.*?)\\/?>#", $html, $matches);
      foreach ($matches[1] as $key => $m) {
        preg_match_all('/(alt|src|width|height)=("[^"]*")/i', $m, $matches2);
        $amp_tag = '<div class="fixed-height-container"><amp-img ';
        foreach ($matches2[1] as $key2 => $val) {
          $amp_tag .= $val .'='. $matches2[2][$key2] .' ';
        }
        $amp_tag .= 'class="contain" layout="fill"';
        $amp_tag .= '>';
        $amp_tag .= '</amp-img></div>';
        $html = str_replace($matches[0][$key], $amp_tag, $html);
      }
      return $html;
    }
    

    only have to put: <div class="fixed-height-container"> before <amp-img

    and change: $amp_tag .= 'layout="responsive"'; to: $amp_tag .= 'class="contain" layout="fill"';

    and a closing </div> after last $amp_tag .= '</amp-img></div>';

    You can check amp tutorial where I find this solution at: amp.dev site

    This way you do not need to provide width and height patterns along image tag.


    Update: Author of ampify_img returned my e-mails so here is a better approach. PHP check for img src and getimagesize() from there. This way images become responsive.

    function img_to_amp ($html) {
        preg_match_all("#<img(.*?)\\/?>#", $html, $img_matches);
        foreach ($img_matches[1] as $key => $img_tag) {
          preg_match_all('/(alt|src|width|height)=["\'](.*?)["\']/i', $img_tag, $attribute_matches);
          $attributes = array_combine($attribute_matches[1], $attribute_matches[2]);
          if (!array_key_exists('width', $attributes) || !array_key_exists('height', $attributes)) {
            if (array_key_exists('src', $attributes)) {
              list($width, $height) = getimagesize($attributes['src']);
              $attributes['width'] = $width;
              $attributes['height'] = $height;
            }
          }
          $amp_tag = '<amp-img ';
          foreach ($attributes as $attribute => $val) {
            $amp_tag .= $attribute .'="'. $val .'" ';
          }
          $amp_tag .= 'layout="responsive"';
          $amp_tag .= '>';
          $amp_tag .= '</amp-img>';
          $html = str_replace($img_matches[0][$key], $amp_tag, $html);
        }
        return $html;
      }
    

    You can also check the code and contribute on https://gist.github.com/elalemanyo/034490164beb7b935559585ff1cc7d9f