Take the 2-minute tour ×
WordPress Development Stack Exchange is a question and answer site for WordPress developers and administrators. It's 100% free, no registration required.

I've this function, which I'm pretty sure a lot of you already know:

function catch_that_image() {
  global $post, $posts;
  $first_img = '';
  ob_start();
  ob_end_clean();
  $output = preg_match_all('/<img.+src=[\'"]([^\'"]+)[\'"].*>/i', $post->post_content, $matches);
  $first_img = $matches[1][0];

  return $first_img;
}

I would like to use the thumb, medium, etc sizes in the posts loop.

Do you guys have any idea how can I do this?

Cheers

share|improve this question
    
You want to replace the images in the post body with images of some specific size? Why do you have ob_start and ob_end_clean back to back with nothing in between? –  s_ha_dum Apr 29 '13 at 13:26
    
Hey, this was a copy paste from another website. You're right, the ob_start and ob_end_clean has nothing to do with it. I want to use the medium size of the post images in the loop. –  Telmo Gonçalves Apr 29 '13 at 13:30
    
But you are trying to replace images in the post body, correct? –  s_ha_dum Apr 29 '13 at 14:20
    
No, the idea is to grab the first image used in the post to use it when looping all the posts, but instead of getting the original image I would like to get the medium sized one. –  Telmo Gonçalves Apr 29 '13 at 14:23

3 Answers 3

up vote 3 down vote accepted

When the first image is a Wordpress image attachment.

in 3.6, there is an easier way.

function get_first_image_medium_size_url($post_id) {

 if(!$images = get_attached_images($post_id))
    return false;

 $first_image = current($images);

 if(!$src = wp_get_attachment_image_src($first_image->ID,'medium'))
    return false;

 $medium_url = current($src);

 return $medium_url;
}

get_attached_images is available in 3.6.

wp_get_attachment_image_src is available since 2.5.0 which will automatically get or scale the image attachment to specified size.

Since the 3.6 isn't released yet, you may want to create your own get_attached_images function

function my_get_attached_images( $post_id = 0 ) {
    $post = empty( $post_id ) ? get_post() : get_post( $post_id );
    if ( empty( $post ) )
        return;

    $args = array(
        'post_parent' => $post->ID,
        'post_type' => 'attachment',
        'post_mime_type' => 'image',
        'posts_per_page' => -1,
        'orderby' => 'menu_order',
        'order' => 'ASC',
    );


    $children = get_children( $args );

    return (array)$children;
}

What if the image isn't a Wordpress attachment type?

for example, you are linking to an flickr image.

Well, here is my version of catch_first_image

function get_first_image($content){
    if(!$content)
        return false;
    preg_match("@<img.+?src=[\"'](.+?)[\"'].+?>@",$content,$m);

    if($m[1])
        if(filter_var($m[1], FILTER_VALIDATE_URL))
            return $m[1];
    return false;
}

I think it is better than yours. Oftentimes, my heartbeat raises when I see the ob_* functions. hehe

How to resize the image?

I'd like to use Wordpress Photon to do this thing.

function photon_image_url($orgin_url){
        $orgin_url = str_replace(array('http://','https://'),'',$origin_url);
        return 'http://i0.wp.com/'.$origin_url.'?w=50%';
}

note: this function is just to give you a general idea of how to use photon.


Of course, you can use Photon for both scenarios. You know, it is kind of a CDN service.

share|improve this answer
    
This worked fine, thanks :) –  Telmo Gonçalves Apr 30 '13 at 15:48

You will need to grab the image, get its ID, and then use wp_get_attachment_image to pick the appropriately sized image.

function first_image_medium_wpse_97658($content) {
  global $wpdb;
  $pattern = '|<img.*?src="([^"]+)".*?/>|';
  preg_match($pattern,$content,$matches);
  if (!empty($matches[1])) {
    $path = pathinfo($matches[1]);
    if (!empty($path['filename'])) {
      $id = $wpdb->get_var($wpdb->prepare("SELECT ID FROM {$wpdb->posts} WHERE post_name = %s",$path['filename']));
      if (!empty($id)) {
        $content = wp_get_attachment_image($id,'medium'); 
      }
    }
  }
  return $content;
}
add_filter('the_content','first_image_medium_wpse_97658');

And another version using the classes set on the image by default. This one has no extra database query but would fail if those classes are not set.

function first_image_medium_wpse_97658_v2($content) {
  $pattern = '|<img.*?class="([^"]+)".*?/>|';
  preg_match($pattern,$content,$matches);
  if (!empty($matches[1])) {
    $classes = explode(' ',$matches[1]);
    $id = preg_grep('|^wp-image-.*|',$classes);
    if (!empty($id)) {
      $id = str_replace('wp-image-','',$id);
      if (!empty($id)) {
        $id = reset($id);
        $content = wp_get_attachment_image($id,'medium');  
      }
    }
  }
  return $content;
}
add_filter('the_content','first_image_medium_wpse_97658_v2');

The function can also be called directly, without being used as a filter callback.

echo first_image_medium_wpse_97658_v2($post->post_content);

To replace the excerpt with the first image from the content requires a minor change. The the_excerpt filter is passed content like the the_content filter but there is no guarantee that the _post_content_ images will be in there.

function first_image_medium_wpse_97658_v3($excerpt) {
  global $post;
  $content = $post->post_content;
  $pattern = '|<img.*?class="([^"]+)".*?/>|';
  preg_match($pattern,$content,$matches);
  if (!empty($matches[1])) {
    $classes = explode(' ',$matches[1]);
    $id = preg_grep('|^wp-image-.*|',$classes);
    if (!empty($id)) {
      $id = str_replace('wp-image-','',$id);
      if (!empty($id)) {
        $id = reset($id);
        $excerpt = wp_get_attachment_image($id,'medium');  
      }
    }
  }
  return $excerpt;
}
add_filter('the_excerpt','first_image_medium_wpse_97658_v3',100);

I also added a priority to the callback so that the filter runs late, hopefully after other filters so that the the_excerpt is completely replaced by the filter output.

share|improve this answer
    
Hey, thanks for your help. Pretty neat function. Although it's not working for me, I'm printing the_excerpt in my index.php file, in your function I've changed the_content with the_excerpt and I don't get any image. Any more ideas? Or am I doing something wrong? –  Telmo Gonçalves Apr 30 '13 at 13:15
    
Use the the_excerpt filter instead, or call the function directly where you need it-- first_image_medium_wpse_97658_v2('string with your image in it');. I'll edit the answer. –  s_ha_dum Apr 30 '13 at 13:32

Sometimes I used a similar approach to your, so here is a simple function to be copied/pasted in your functions.php

As you can see it sets image Width = 100px and Image Height = 80px, I know that this isn't the best solution as the image isn't cropped or resized and it can be also an 'heavy' image but If the only thing you are looking for is a fast function that catches your first image... here it is.

Get's First image Width = 100px Height = 80px

<?php
function getImage10080($num) {
global $more;
$more = 1;
$link = get_permalink();
$content = get_the_content();
$count = substr_count($content, '<img');
$start = 0;
for($i=1;$i<=$count;$i++) {
$imgBeg = strpos($content, '<img', $start);
$post = substr($content, $imgBeg);
$imgEnd = strpos($post, '>');
$postOutput = substr($post, 0, $imgEnd+1);
$postOutput = preg_replace('/width="([0-9]*)" height="([0-9]*)"/', '/width="100px" height="80px"/',$postOutput);
$image[$i] = $postOutput;
$start=$imgEnd+1;
}
if(stristr($image[$num],'<img')) { echo ''.$image[$num].""; }
$more = 0;
};
?>

After placing this code in your functions.php (without ) you'll only have to write this:

<?php getImage10080('1');?>

where you want your 'catched' image to be shown.

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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