2

Using the WordPress the_content tag, I am running a custom function to search for all images that do not have a width and height attribute set and insert the proper dimensions. Below is the function:

add_filter( 'the_content', 'add_img_dimensions' );

function add_img_dimensions( $image_no_dimensions ) { // Insert width & height to images missing dimensions
    if ( preg_match_all( '/<img [^>]+width=[^>]+height=>/i', $image_no_dimensions, $result ) ) {
        // Do nothing...
    }
    else {
        preg_match_all( '/(alt|title|src)=("[^"]*")/i', $image_no_dimensions, $img );
        list( $width, $height, $type, $attr ) = getimagesize( str_replace( "\"", "" , ( $img[2][0] ) ) );
        $imgname = str_replace( "\"", "" , ( $img[2][0] ) );
    }

    return sprintf( '<img src="%s" width="%dpx" height="%dpx" />', str_replace("\"", "" , ( $img[2][0] ) ), $width, $height );
}

For example, if there is an image on one of my pages that looks like the following:

<img src="https://link.to/sum/img.jpg" alt="Image Title" />

It will then insert the width and height of the actual image:

<img width="150" height="50" src="https://link.to/sum/img.jpg" alt="Image Title" />

The function works as expected. However, all of the page's content is replace with the first image that it finds that don't have dimensions set.

How can I return all of the content but only change the images that don't have a dimension?

Before and after enter image description here

3

Tested and confirmed that this works:

add_filter( 'the_content', 'add_image_dimensions' );

function add_image_dimensions( $content ) {

    preg_match_all( '/<img[^>]+>/i', $content, $images);

    if (count($images) < 1)
        return $content;

    foreach ($images[0] as $image) {
        preg_match_all( '/(alt|title|src|width|class|id|height)=("[^"]*")/i', $image, $img );

        if ( !in_array( 'src', $img[1] ) )
            continue;

        if ( !in_array( 'width', $img[1] ) || !in_array( 'height', $img[1] ) ) {
            $src = $img[2][ array_search('src', $img[1]) ];
            $alt = in_array( 'alt', $img[1] ) ? ' alt=' . $img[2][ array_search('alt', $img[1]) ] : '';
            $title = in_array( 'title', $img[1] ) ? ' title=' . $img[2][ array_search('title', $img[1]) ] : '';
            $class = in_array( 'class', $img[1] ) ? ' class=' . $img[2][ array_search('class', $img[1]) ] : '';
            $id = in_array( 'id', $img[1] ) ? ' id=' . $img[2][ array_search('id', $img[1]) ] : '';
            list( $width, $height, $type, $attr ) = getimagesize( str_replace( "\"", "" , $src ) );

            $image_tag = sprintf( '<img src=%s%s%s%s%s width="%d" height="%d" />', $src, $alt, $title, $class, $id, $width, $height );
            $content = str_replace($image, $image_tag, $content);
        }
    }

    return $content;
}
  • It works, excellent! However, I notice the class is stripped form my sample images. Is there a way to retain all of the tags besides the class? If you could show me where to do that, I can try it myself. – Ethan Jinks O'Sullivan Aug 20 '16 at 18:22
  • 1
    Updated the code so it will add class and id attributes. – Nate Allen Aug 20 '16 at 18:31
  • Great, thank you. I see where you add the extra tags for the image. One more question: I notice that my sample items have title="" and id="" set like that because they were not originally included in the image. Is there a way to only display the tags that have information in it? In this instance, it won't show the title and id since nothing was originally set. – Ethan Jinks O'Sullivan Aug 20 '16 at 18:35
  • 1
    Updated the code again. Let me know what you think. – Nate Allen Aug 20 '16 at 18:59
0

You always need to return the full content when using the_content filter. But the code you have will not quite handle multiple images anyway... something like this might do it better, by extracting all the image tags first then looping to maybe add the width/height to each and replacing the original tag:

add_filter( 'the_content', 'add_img_dimensions' );

function add_img_dimensions( $content ) { 

    preg_match_all( '/<img[^>]+>/i', $content, $images);
    if (count($images) < 1) {return $content;}

    foreach ($images as $image) {
        preg_match_all( '/(alt|title|src|width|height)=("[^"]*")/i', $image[0], $img );
        // Insert width & height to image if no width specified
        if (!isset($img[3])) {
            $imgalt = str_replace( "\"", "" , ( $img[0][0] ) );                                 
            $imgtitle = str_replace( "\"", "" , ( $img[1][0] ) );
            $imgname = str_replace( "\"", "" , ( $img[2][0] ) );                
            list( $width, $height, $type, $attr ) = getimagesize( $imgname );
            $newimagetag = sprintf( '<img src="%s" alt="%s" title="%s" width="%dpx" height="%dpx" />', $imgname, $imgalt, $imgtitle, $width, $height );
            $content = str_replace($image, $newimagetag, $content);
        }
    }

    return $content;
}

Note: Untested I'm not sure I have the index references just right... also you will lose any inline styles or other attributes (eg. border) this way so further would need to be done to preserve those.

  • Thanks for looking into this question. I tried out the code and I get an error preg_match_all() expects parameter 2 to be string, array given which is referring to line 9 of your code. From doing some research, it looks like there is an issue with it being an array. I've seen a suggestion to use preg_grep. Also another error: getimagesize(): Filename cannot be empty. May you help go through your code so I can understand it? – Ethan Jinks O'Sullivan Aug 19 '16 at 12:01
  • hmmm yeah like I said some indexes may be off, I have edited and changed $image to $image[0] on that line see if that fixes it... $image is basically the full HTML tag match there eg. <img src="http://someurl.com"> ... you can always print_r($image); on the line before if that doesn't work it should help debug the index. – majick Aug 19 '16 at 13:47
  • Thanks for the update. Looks like that fixed it, but another issue shows up: Undefined offset: 3 for line 11 and str_replace() expects at least 3 parameters, 2 given for line 17. If it helps, I've set up the following sample content to test out your function: GitHub Gist – Ethan Jinks O'Sullivan Aug 19 '16 at 14:27
  • yeah whoops the third parameter should be $content and changed the check on the image array... let me know if that fixes it and if not I'll check out the gist. – majick Aug 20 '16 at 1:46
  • Progress! Thanks for the update. However, it looks like all of the image are not replaced with just one – Ethan Jinks O'Sullivan Aug 20 '16 at 1:54

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.