WordPress.org

Make WordPress Core

Opened 3 years ago

Last modified 6 weeks ago

#15311 new enhancement

dynamic image resize (on the fly) using already available functions

Reported by: vteixeira Owned by:
Milestone: Future Release Priority: normal
Severity: normal Version: 3.1
Component: Media Keywords: dev-feedback has-patch
Focuses: Cc:

Description

The lack of a dynamic resize function in WordPress forces theme developers to register lots of image sizes for their themes to use.

One of the problems with this approach is that the server becomes full of image files that will be never used.

Another problem is that when someone changes their theme the image sizes simply doesn't match, forcing people to use a plugin to regenerate all image files, and once again lots of those files will never be used.

So theme developers right now are using some sort of image resizing script like timthumb that works outside of wp. I think it has many drawbacks comparing to a native implementation.

So I made a function that uses WordPress native image handling capabilities to resize and save those resized images for future use.

I use this for attached images as well as standalone files such as custom fields and other images.

What I want here is just to share my solution, and maybe we can someday put something like this into core (actually something better then this):

/*
 * Resize images dynamically using wp built in functions
 * Victor Teixeira
 *
 * php 5.2+
 *
 * Exemple use:
 * 
 * <?php 
 * $thumb = get_post_thumbnail_id(); 
 * $image = vt_resize( $thumb,'' , 140, 110, true );
 * ?>
 * <img src="<?php echo $image[url]; ?>" width="<?php echo $image[width]; ?>" height="<?php echo $image[height]; ?>" />
 *
 * @param int $attach_id
 * @param string $img_url
 * @param int $width
 * @param int $height
 * @param bool $crop
 * @return array
 */
function vt_resize( $attach_id = null, $img_url = null, $width, $height, $crop = false ) {

	// this is an attachment, so we have the ID
	if ( $attach_id ) {
	
		$image_src = wp_get_attachment_image_src( $attach_id, 'full' );
		$file_path = get_attached_file( $attach_id );
	
	// this is not an attachment, let's use the image url
	} else if ( $img_url ) {
		
		$file_path = parse_url( $img_url );
		$file_path = ltrim( $file_path['path'], '/' );
		//$file_path = rtrim( ABSPATH, '/' ).$file_path['path'];
		
		$orig_size = getimagesize( $file_path );
		
		$image_src[0] = $img_url;
		$image_src[1] = $orig_size[0];
		$image_src[2] = $orig_size[1];
	}
	
	$file_info = pathinfo( $file_path );
	$extension = '.'. $file_info['extension'];

	// the image path without the extension
	$no_ext_path = $file_info['dirname'].'/'.$file_info['filename'];

	$cropped_img_path = $no_ext_path.'-'.$width.'x'.$height.$extension;

	// checking if the file size is larger than the target size
	// if it is smaller or the same size, stop right here and return
	if ( $image_src[1] > $width || $image_src[2] > $height ) {

		// the file is larger, check if the resized version already exists (for crop = true but will also work for crop = false if the sizes match)
		if ( file_exists( $cropped_img_path ) ) {

			$cropped_img_url = str_replace( basename( $image_src[0] ), basename( $cropped_img_path ), $image_src[0] );
			
			$vt_image = array (
				'url' => $cropped_img_url,
				'width' => $width,
				'height' => $height
			);
			
			return $vt_image;
		}

		// crop = false
		if ( $crop == false ) {
		
			// calculate the size proportionaly
			$proportional_size = wp_constrain_dimensions( $image_src[1], $image_src[2], $width, $height );
			$resized_img_path = $no_ext_path.'-'.$proportional_size[0].'x'.$proportional_size[1].$extension;			

			// checking if the file already exists
			if ( file_exists( $resized_img_path ) ) {
			
				$resized_img_url = str_replace( basename( $image_src[0] ), basename( $resized_img_path ), $image_src[0] );

				$vt_image = array (
					'url' => $resized_img_url,
					'width' => $new_img_size[0],
					'height' => $new_img_size[1]
				);
				
				return $vt_image;
			}
		}

		// no cached files - let's finally resize it
		$new_img_path = image_resize( $file_path, $width, $height, $crop );
		$new_img_size = getimagesize( $new_img_path );
		$new_img = str_replace( basename( $image_src[0] ), basename( $new_img_path ), $image_src[0] );

		// resized output
		$vt_image = array (
			'url' => $new_img,
			'width' => $new_img_size[0],
			'height' => $new_img_size[1]
		);
		
		return $vt_image;
	}

	// default output - without resizing
	$vt_image = array (
		'url' => $image_src[0],
		'width' => $image_src[1],
		'height' => $image_src[2]
	);
	
	return $vt_image;
}

Attachments (3)

vt_resize.txt (3.5 KB) - added by daltonrooney 23 months ago.
Small update to predict final image size before naming it.
vt_resize.2.txt (3.9 KB) - added by foxinni 21 months ago.
Resize script to support MultiSite
15311.diff (14.8 KB) - added by prettyboymp 19 months ago.
Patch piggy backs off of 22100.2.diff in ticket @22100

Download all attachments as: .zip

Change History (95)

comment:1 filosofo3 years ago

For reference, here's a plugin I wrote to do something similar.

comment:2 vteixeira3 years ago

Hi Filosofo, I didn't know your plugin.

This function started as a less than 10 lines script, but soon I realized that I needed more checks before resizing the image.
And then I added the ability to resize any image even if it was not an attachment - this is really important because of the way we are using custom post types today with all those custom fields and metaboxes.
And I also wanted it to be available for plugins that uploads images to their own folders (and tables) as well.

What I keep asking myself is why we still don't have this in core.
All the functionality is already built in, it just needs to be made available as a simple function or a class.

The fact is every framework or cms out there have a dynamic resize function, we need this for wp.

The add_image_size() function really doesn't scales.

I'm convinced that the functions.php file (as I'm doing right now) is not the best place for this.

Maybe you or other dev could refactor this for a core function. It really needs some more testing as I don't know if it works without problems on a subfolder install.

comment:3 Utkarsh3 years ago

  • Cc admin@… added

comment:4 vteixeira3 years ago

  • Cc victorhteixeira@… added

comment:5 anointed3 years ago

  • Cc anointed added

fantastic script, using it already.. saved my bacon lol..

suggestion:
ability to control the 'quality' of the resized image itself for further optimization.

comment:6 vteixeira3 years ago

Quality control added!

@anointed: glad you liked it. It saves me everyday.

/*
 * Resize images dynamically using wp built in functions
 * Victor Teixeira
 *
 * php 5.2+
 *
 * Exemple use:
 * 
 * <?php 
 * $thumb = get_post_thumbnail_id(); 
 * $image = vt_resize( $thumb,'' , 140, 110, true, 70 );
 * ?>
 * <img src="<?php echo $image[url]; ?>" width="<?php echo $image[width]; ?>" height="<?php echo $image[height]; ?>" />
 *
 * @param int $attach_id
 * @param string $img_url
 * @param int $width
 * @param int $height
 * @param bool $crop
 * @param int $jpeg_quality
 * @return array
 */
function vt_resize( $attach_id = null, $img_url = null, $width, $height, $crop = false, $jpeg_quality = 90 ) {

	// this is an attachment, so we have the ID
	if ( $attach_id ) {
	
		$image_src = wp_get_attachment_image_src( $attach_id, 'full' );
		$file_path = get_attached_file( $attach_id );
	
	// this is not an attachment, let's use the image url
	} else if ( $img_url ) {
		
		$file_path = parse_url( $img_url );
		$file_path = ltrim( $file_path['path'], '/' );
		//$file_path = rtrim( ABSPATH, '/' ).$file_path['path'];
		
		$orig_size = getimagesize( $file_path );
		
		$image_src[0] = $img_url;
		$image_src[1] = $orig_size[0];
		$image_src[2] = $orig_size[1];
	}
	
	$file_info = pathinfo( $file_path );
	$extension = '.'. $file_info['extension'];

	// the image path without the extension
	$no_ext_path = $file_info['dirname'].'/'.$file_info['filename'];

	$cropped_img_path = $no_ext_path.'-'.$width.'x'.$height.$extension;

	// checking if the file size is larger than the target size
	// if it is smaller or the same size, stop right here and return
	if ( $image_src[1] > $width || $image_src[2] > $height ) {

		// the file is larger, check if the resized version already exists (for crop = true but will also work for crop = false if the sizes match)
		if ( file_exists( $cropped_img_path ) ) {

			$cropped_img_url = str_replace( basename( $image_src[0] ), basename( $cropped_img_path ), $image_src[0] );
			
			$vt_image = array (
				'url' => $cropped_img_url,
				'width' => $width,
				'height' => $height
			);
			
			return $vt_image;
		}

		// crop = false
		if ( $crop == false ) {
		
			// calculate the size proportionaly
			$proportional_size = wp_constrain_dimensions( $image_src[1], $image_src[2], $width, $height );
			$resized_img_path = $no_ext_path.'-'.$proportional_size[0].'x'.$proportional_size[1].$extension;			

			// checking if the file already exists
			if ( file_exists( $resized_img_path ) ) {
			
				$resized_img_url = str_replace( basename( $image_src[0] ), basename( $resized_img_path ), $image_src[0] );

				$vt_image = array (
					'url' => $resized_img_url,
					'width' => $new_img_size[0],
					'height' => $new_img_size[1]
				);
				
				return $vt_image;
			}
		}

		// no cached files - let's finally resize it
		$new_img_path = image_resize( $file_path, $width, $height, $crop, $jpeg_quality );
		$new_img_size = getimagesize( $new_img_path );
		$new_img = str_replace( basename( $image_src[0] ), basename( $new_img_path ), $image_src[0] );

		// resized output
		$vt_image = array (
			'url' => $new_img,
			'width' => $new_img_size[0],
			'height' => $new_img_size[1]
		);
		
		return $vt_image;
	}

	// default output - without resizing
	$vt_image = array (
		'url' => $image_src[0],
		'width' => $image_src[1],
		'height' => $image_src[2]
	);
	
	return $vt_image;
}

comment:7 anointed3 years ago

finally... goodbye timthumb, was a nice ride, but luvin this so much better. Time to redo entire theme image replacement.

tested out quality control, works great!

comment:8 anointed3 years ago

something you might check into:

I've noticed that many .jpg images that I am uploading are for some reason all sizing to approx 300x wide even though I have it set in my theme to be 800x550. There seems to be nothing in common between those that resize properly and those that don't.

If need be, I can post a zip file of images that all seem to resize wrong if it helps.

comment:9 vteixeira3 years ago

I just found a little bug, but that had nothing to do with the image resizing. Actually the resizing is performed by the WordPress native function resize_image().

Anyway, check this one:

/*
 * Resize images dynamically using wp built in functions
 * Victor Teixeira
 *
 * php 5.2+
 *
 * Exemple use:
 * 
 * <?php 
 * $thumb = get_post_thumbnail_id(); 
 * $image = vt_resize( $thumb,'' , 140, 110, true, 70 );
 * ?>
 * <img src="<?php echo $image[url]; ?>" width="<?php echo $image[width]; ?>" height="<?php echo $image[height]; ?>" />
 *
 * @param int $attach_id
 * @param string $img_url
 * @param int $width
 * @param int $height
 * @param bool $crop
 * @param int $jpeg_quality
 * @return array
 */
function vt_resize( $attach_id = null, $img_url = null, $width, $height, $crop = false, $jpeg_quality = 90 ) {

	// this is an attachment, so we have the ID
	if ( $attach_id ) {
	
		$image_src = wp_get_attachment_image_src( $attach_id, 'full' );
		$file_path = get_attached_file( $attach_id );
	
	// this is not an attachment, let's use the image url
	} else if ( $img_url ) {
		
		$file_path = parse_url( $img_url );
		$file_path = ltrim( $file_path['path'], '/' );
		//$file_path = rtrim( ABSPATH, '/' ).$file_path['path'];
		
		$orig_size = getimagesize( $file_path );
		
		$image_src[0] = $img_url;
		$image_src[1] = $orig_size[0];
		$image_src[2] = $orig_size[1];
	}
	
	$file_info = pathinfo( $file_path );
	$extension = '.'. $file_info['extension'];

	// the image path without the extension
	$no_ext_path = $file_info['dirname'].'/'.$file_info['filename'];

	$cropped_img_path = $no_ext_path.'-'.$width.'x'.$height.$extension;

	// checking if the file size is larger than the target size
	// if it is smaller or the same size, stop right here and return
	if ( $image_src[1] > $width || $image_src[2] > $height ) {

		// the file is larger, check if the resized version already exists (for crop = true but will also work for crop = false if the sizes match)
		if ( file_exists( $cropped_img_path ) ) {

			$cropped_img_url = str_replace( basename( $image_src[0] ), basename( $cropped_img_path ), $image_src[0] );
			
			$vt_image = array (
				'url' => $cropped_img_url,
				'width' => $width,
				'height' => $height
			);
			
			return $vt_image;
		}

		// crop = false
		if ( $crop == false ) {
		
			// calculate the size proportionaly
			$proportional_size = wp_constrain_dimensions( $image_src[1], $image_src[2], $width, $height );
			$resized_img_path = $no_ext_path.'-'.$proportional_size[0].'x'.$proportional_size[1].$extension;			

			// checking if the file already exists
			if ( file_exists( $resized_img_path ) ) {
			
				$resized_img_url = str_replace( basename( $image_src[0] ), basename( $resized_img_path ), $image_src[0] );

				$vt_image = array (
					'url' => $resized_img_url,
					'width' => $proportional_size[0],
					'height' => $proportional_size[1]
				);
				
				return $vt_image;
			}
		}

		// no cached files - let's finally resize it
		$new_img_path = image_resize( $file_path, $width, $height, $crop, $jpeg_quality );
		$new_img_size = getimagesize( $new_img_path );
		$new_img = str_replace( basename( $image_src[0] ), basename( $new_img_path ), $image_src[0] );

		// resized output
		$vt_image = array (
			'url' => $new_img,
			'width' => $new_img_size[0],
			'height' => $new_img_size[1]
		);
		
		return $vt_image;
	}

	// default output - without resizing
	$vt_image = array (
		'url' => $image_src[0],
		'width' => $image_src[1],
		'height' => $image_src[2]
	);
	
	return $vt_image;
}

comment:10 vteixeira3 years ago

Just to clarify, the native function is image_resize().

comment:11 vteixeira3 years ago

  • Keywords dev-feedback added

comment:12 iandstewart3 years ago

  • Cc ian@… added

comment:13 vteixeira3 years ago

I have a new version that should work without problems for a subfolder install (the previous version doesn't work with subfolder installs if I pass the image url instead of the ID).

Also I removed the possibility to define the image quality because when I pass this variable WordPress renames the images differently, adding the image quality on the file name instead of the sizes. This caused many problems with the if statements to check if the image exists. So I decided to remove it.

/*
 * Resize images dynamically using wp built in functions
 * Victor Teixeira
 *
 * php 5.2+
 *
 * Exemplo de uso:
 * 
 * <?php 
 * $thumb = get_post_thumbnail_id(); 
 * $image = vt_resize( $thumb, '', 140, 110, true );
 * ?>
 * <img src="<?php echo $image[url]; ?>" width="<?php echo $image[width]; ?>" height="<?php echo $image[height]; ?>" />
 *
 * @param int $attach_id
 * @param string $img_url
 * @param int $width
 * @param int $height
 * @param bool $crop
 * @return array
 */
function vt_resize( $attach_id = null, $img_url = null, $width, $height, $crop = false ) {

	// this is an attachment, so we have the ID
	if ( $attach_id ) {
	
		$image_src = wp_get_attachment_image_src( $attach_id, 'full' );
		$file_path = get_attached_file( $attach_id );
	
	// this is not an attachment, let's use the image url
	} else if ( $img_url ) {
		
		$file_path = parse_url( $img_url );
		$file_path = $_SERVER['DOCUMENT_ROOT'] . $file_path['path'];
		
		//$file_path = ltrim( $file_path['path'], '/' );
		//$file_path = rtrim( ABSPATH, '/' ).$file_path['path'];
		
		$orig_size = getimagesize( $file_path );
		
		$image_src[0] = $img_url;
		$image_src[1] = $orig_size[0];
		$image_src[2] = $orig_size[1];
	}
	
	$file_info = pathinfo( $file_path );
	$extension = '.'. $file_info['extension'];

	// the image path without the extension
	$no_ext_path = $file_info['dirname'].'/'.$file_info['filename'];

	$cropped_img_path = $no_ext_path.'-'.$width.'x'.$height.$extension;

	// checking if the file size is larger than the target size
	// if it is smaller or the same size, stop right here and return
	if ( $image_src[1] > $width || $image_src[2] > $height ) {

		// the file is larger, check if the resized version already exists (for $crop = true but will also work for $crop = false if the sizes match)
		if ( file_exists( $cropped_img_path ) ) {

			$cropped_img_url = str_replace( basename( $image_src[0] ), basename( $cropped_img_path ), $image_src[0] );
			
			$vt_image = array (
				'url' => $cropped_img_url,
				'width' => $width,
				'height' => $height
			);
			
			return $vt_image;
		}

		// $crop = false
		if ( $crop == false ) {
		
			// calculate the size proportionaly
			$proportional_size = wp_constrain_dimensions( $image_src[1], $image_src[2], $width, $height );
			$resized_img_path = $no_ext_path.'-'.$proportional_size[0].'x'.$proportional_size[1].$extension;			

			// checking if the file already exists
			if ( file_exists( $resized_img_path ) ) {
			
				$resized_img_url = str_replace( basename( $image_src[0] ), basename( $resized_img_path ), $image_src[0] );

				$vt_image = array (
					'url' => $resized_img_url,
					'width' => $proportional_size[0],
					'height' => $proportional_size[1]
				);
				
				return $vt_image;
			}
		}

		// no cache files - let's finally resize it
		$new_img_path = image_resize( $file_path, $width, $height, $crop );
		$new_img_size = getimagesize( $new_img_path );
		$new_img = str_replace( basename( $image_src[0] ), basename( $new_img_path ), $image_src[0] );

		// resized output
		$vt_image = array (
			'url' => $new_img,
			'width' => $new_img_size[0],
			'height' => $new_img_size[1]
		);
		
		return $vt_image;
	}

	// default output - without resizing
	$vt_image = array (
		'url' => $image_src[0],
		'width' => $image_src[1],
		'height' => $image_src[2]
	);
	
	return $vt_image;
}

comment:14 westi3 years ago

Please attach patches rather than embedding code fragments in comments - https://core.trac.wordpress.org/#HowtoSubmitPatches

comment:15 vteixeira3 years ago

Sorry for that. I was not suposed to embed code in the comment area.

The problem is that I'm not sure it should be a patch right now. I just want to get some feedback from the devs (that's why I added dev-feedback).
And then I made some changes to the code...

comment:16 follow-up: Viper007Bond3 years ago

I'm pretty sure there's already a ticket for this. Mark Jaquith has been wanting this for quite some time.

comment:17 in reply to: ↑ 16 ; follow-up: nacin3 years ago

Replying to Viper007Bond:

I'm pretty sure there's already a ticket for this. Mark Jaquith has been wanting this for quite some time.

Indeed, I had the same thought a few days ago. Couldn't locate one through even looking for tickets by Mark.

comment:18 filosofo3 years ago

I think you're thinking of this ticket and comment.

Really, if you like this idea I think you should take a look at my plugin's implementation, linked to above. It uses the WP API, and I've deployed it on a number of live sites.

comment:19 in reply to: ↑ 17 Viper007Bond3 years ago

There's also a ticket for using a shortcode for images I think so that the URL/size can easily be changed after it's embedded. A good example of this is when you change themes.

comment:20 follow-up: vteixeira3 years ago

I also thought there were already a ticket for this, that's why I searched before posting.

The ticket #8599 doesn't solve our problems since we would still need to register image sizes and all the images would be resized on all that sizes...

I first made this function because I was working on a website where I had more than 12 different 'add_image_size()' on my functions.php file.
Well, with the 3 other sizes that WordPress creates automatically, you can make the math...
For each image uploaded I had 15 different files plus the original - 16 files for one image!

Since I really didn't want to use timthumb I decided to make my own function using what's already available on WP.

But then I thought I could go one step further and make it available to resize any image, not just attachments.
And I also want the theme developer to have complete control over the html - no html generated!

That's it.

I think we need something like this in core for 3.1, everyone needs it.

comment:21 in reply to: ↑ 20 nacin3 years ago

  • Milestone changed from Awaiting Review to Future Release

Replying to vteixeira:

I also thought there were already a ticket for this, that's why I searched before posting.

The ticket #8599 doesn't solve our problems since we would still need to register image sizes and all the images would be resized on all that sizes...

I first made this function because I was working on a website where I had more than 12 different 'add_image_size()' on my functions.php file.
Well, with the 3 other sizes that WordPress creates automatically, you can make the math...
For each image uploaded I had 15 different files plus the original - 16 files for one image!

We still need a whitelist, so we wouldn't deviate from add_image_size(). Otherwise you could just ++ the desired size, and force the server to continue to eat up resources in resizing photos. It's practically a DOS and would be death on a shared host.

But what we could do, is generate those respective sizes on demand, when requested. This also allows for new ones to be generated on theme switch, again on demand.

I think we need something like this in core for 3.1, everyone needs it.

No, this is two months too late for 3.1, and big enough that it would need to be a blessed task to be included in a release.

Also, I found chatter in the IRC logs from March, where Mark was demonstrating what he was working on:
https://irclogs.wordpress.org/chanlog.php?channel=wordpress-dev&day=2010-03-11#m89606. Guess a ticket never came out of it.

comment:22 vteixeira3 years ago

Why the DOS? The images are resized and cached.

They are processed just on the first request and only for that specified size.
I'm not sure why it would eat up resources.

The idea is, like you said, to generate them on demand, and not every size on the upload.

Yes, your suggestion is ok, but we should also count for images that are not attachments (or we doesn't know the ID) like images in custom fields.
So I could register my image sizes and later on I could change those sizes and my images would be regenerated again when they are requested.
The point here is to generate the resized images only when they are requested and not on upload so I don't end up with lots of image files lying around.

comment:23 follow-up: Viper007Bond3 years ago

I think nacin is assuming that the width/height parameters can come from the URL rather than being hard coded into your PHP. If that was the case, you could just play with the GET values to make your code generate tons and tons of random sized images.

Anyway, the media API already supports both named and array width/height based parameters, so there's no good reason to deviate from the existing code and reinvent the wheel.

Infact your code would very, very easily be implemented as a plugin without a single theme change to call your function. On WordPress.com for example, we generate no thumbnails on upload and instead generate them on the fly as needed (although we use query strings to do so) and that's all done using hooks. You could do the same.

I'd still like to get this into core though, but we need to make sure to avoid issues like the resize failing and then each request attempting to resize it again.

comment:24 pross3 years ago

  • Cc pross@… added

comment:25 cais3 years ago

  • Cc cais added

comment:26 newkind3 years ago

  • Cc newkind added

comment:27 navjotjsingh3 years ago

  • Cc navjotjsingh@… added

comment:28 goto103 years ago

  • Cc goto10 added

comment:29 wlindley3 years ago

I faced this problem some years ago and wrote the AutoNav plugin -- http://wordpress.org/extend/plugins/autonav/ -- in response.

However I took a different approach, parts of which might be valuable in core. My plugin lets you specify a three sizes for thumbnails, depending on whether you want attachments or child pages listed in 2, 3, or 4 columns (those numbers maybe changed in the admin) but when the page is actually displayed, the plugin looks through the directory to find candidate images that, say, fit in 200 pixels wide or 150 pixels tall.

This plugin -- http://wordpress.org/extend/plugins/regenerate-thumbnails/ -- recreates all thumbnails, but wastes much time remaking existing downsized images without checking whether it needs to (presumably, one could check existing file times and skip downsized images with timestamps after their parent). The Wordpress database contains a list of image sizes for each attachment, created by wp's internal functions when the downsize functions create images for registered sizes; but this plugin blitzes that list and starts over.

Any resize operation should ideally add information about what it did, to the list of image sizes associated with the attachment. This should also include whether the downsize image was "fit" or "cropped" -- which isn't there now.

The biggest challenge I see with any of these schemes is the disconnect between what's in the database and what's on disk. A user could well hand-modify a particular attachment size to retouch the sharpness; how would we know not to overwrite it? An automatically-created downsized image for an "old" size might not be used anywhere on the site -- although we would probably have to somehow scan the text of every post to be sure! -- but can we delete an image without breaking possibly links on other sites?

In short, how can we delete obsolete images to free space, without any way of knowing which imagess really are unused?

comment:30 Viper007Bond3 years ago

This plugin -- http://wordpress.org/extend/plugins/regenerate-thumbnails/ -- recreates all thumbnails, but wastes much time remaking existing downsized images without checking whether it needs to (presumably, one could check existing file times and skip downsized images with timestamps after their parent). The Wordpress database contains a list of image sizes for each attachment, created by wp's internal functions when the downsize functions create images for registered sizes; but this plugin blitzes that list and starts over.

If my plugin were to do that, it would require maintaining a modified version of wp_generate_attachment_metadata() (the single function my currently uses to generate the thumbnails).

comment:31 paulomagalhaes3 years ago

  • Cc paulomagalhaes added

This function has been forgotten? WordPress 3.2 requirement: PHP 5.2.4... also would be nice to edit the image crop within the "Edit Media Library".

comment:32 johnnytee2 years ago

  • Cc johnnytee added

comment:33 aharner2 years ago

I had run into an issue where I used direct URLs to my images that I was generating from a custom database, and in those URLs I had converted spaces to '%20' for proper URLs to my images.

because the file structure had them as spaces, I had to do a quick str_replace to fix the problem.

figured I'd just make this note here incase anyone else ever runs into that issue:


//after this line:
$actual_file_path = ltrim( $file_path['path'], '/' );
$actual_file_path = rtrim( ABSPATH, '/' ).$file_path['path'];

//ADDED THIS to replace '%20' from the URL with spaces:
$actual_file_path = str_replace('%20', ' ', $actual_file_path);

comment:34 pauldewouters2 years ago

  • Cc pauldewouters added

comment:35 dboulet2 years ago

  • Cc dboulet added

comment:36 husobj2 years ago

  • Cc ben@… added

comment:37 technosailor2 years ago

  • Cc aaron@… added

comment:38 technosailor2 years ago

Love to see this targetted for 3.5. This really worked well for a project I just worked on.

comment:39 wpsmith2 years ago

  • Cc travis@… added

comment:40 sc0ttkclark2 years ago

  • Cc lol@… added

Used this too, works great, would love to see something in core for these types of things.. +1 for 3.5

comment:41 jeremyfelt2 years ago

  • Cc jeremy.felt@… added

comment:42 bainternet2 years ago

  • Cc admin@… added

comment:43 in reply to: ↑ 23 ; follow-ups: scribu2 years ago

Replying to Viper007Bond:

I'd still like to get this into core though, but we need to make sure to avoid issues like the resize failing and then each request attempting to resize it again.

Here's my take on the whole thing:

  1. Add an 'immediate' parameter to each intermediate size. 'immediate' => true means the file is generated right after the attachment is uploaded.
  1. For 'immediate' => false sizes, generate it on the fly, only if it's not present in the array returned by wp_get_attachment_metadata().

comment:44 in reply to: ↑ 43 sc0ttkclark2 years ago

Replying to scribu:

Here's my take on the whole thing:

  1. Add an 'immediate' parameter to each intermediate size. 'immediate' => true means the file is generated right after the attachment is uploaded.
  1. For 'immediate' => false sizes, generate it on the fly, only if it's not present in the array returned by wp_get_attachment_metadata().

This is totally acceptable for me and the use cases I've seen. Would this be added to add_image_size?

comment:45 scribu2 years ago

Yep, and I think the built-in image sizes should also go through add_image_size().

comment:46 jb5102 years ago

  • Cc jbrown510@… added

comment:47 mercime2 years ago

  • Cc mercijavier@… added

comment:48 daltonrooney23 months ago

  • Cc dalton@… added

comment:49 daltonrooney23 months ago

Thanks so much to Victor, this feature is something I've really been looking for in WordPress. I did find a small bug and hopefully a satisfactory solution. The cropped and non-cropped images are both created with the same dimensions, so if the cropped image already exists and you try to specify the non-cropped image instead, the cropped image is still returned. My solution is to calculate the final dimensions of the image earlier on.

Just before this:

$cropped_img_path = $no_ext_path.'-'.$width.'x'.$height.$extension; 

Add this:

/* Calculate the eventual height and width for accurate file name */

if ( $crop == false ) {
   $proportional_size = wp_constrain_dimensions( $image_src[1], $image_src[2], $width, $height );
   $width = $proportional_size[0];
   $height = $proportional_size[1];
}
	
$cropped_img_path = $no_ext_path.'-'.$width.'x'.$height.$extension;

comment:50 daltonrooney23 months ago

No way to revise/delete attachments, huh? I accidentally left an echo statement for troubleshooting in the previously attached file. Please delete line 64 if you download my updated version of the function.

comment:51 scribu23 months ago

You should be able to re-upload an attachment with the same name.

daltonrooney23 months ago

Small update to predict final image size before naming it.

comment:52 emzo22 months ago

  • Cc emzo added

comment:53 in reply to: ↑ description dimas1822 months ago

Hello buddies

i found this script in one of my current theme and it look very nice lightweight and presice,i wondering if this script can work with a sub domain example, i upload a image with my principal domain but, when it is request by visitor send a url with my sub domain linked to a folder where the image whas uploaded like img.subdomain.com

thanks

comment:54 techguytom22 months ago

  • Cc techguytom added

comment:55 bmonster9922 months ago

  • Cc bmonster99 added

comment:56 webord22 months ago

  • Cc webord.net@… added

comment:57 willmot21 months ago

  • Cc willmot added

comment:58 anointed21 months ago

+1 for considering adding to 3.5. I still use this function in all of my themes and it would be nice to have it checked for security and added to core for peace of mind.

comment:59 mdgl21 months ago

If this feature is being considered for 3.5, may I suggest we also consider proper support for uploaded SVG images at the same time? I think this may even help us achieve the most appropriate design for the proposed "dynamic image resizing" feature.

Presently, you can easily upload SVG files (by modifying the allowable MIME types through a plug-in) but they are not treated as "images", merely as opaque attachments. You can (perhaps) also embed SVG files in (X)HTML where they are effectively invisible to WP and not reusable.

I believe you should be able to upload SVG image files (with a default size), have them displayed and treated as images by WP and subsequently reuse them in different places and at different sizes through the HTML <img> tag.

The key to this I think is separating the "size" attributes from the stored image file and its use(s) in posts/pages. That is, when you upload an image file it is stored in the library with a default size (actual image size in the case of bitmaps, declared size in the case of SVG). When you make use of an image (e.g. by attaching it to a post) you should be able to declare the actual size to be used for the image in that particular instance. In these cases, WP can choose and/or dynamically generate an appropriate bitmap or simply let the browser scale the SVG automatically to the dimensions specified on the <img> tag.

foxinni21 months ago

Resize script to support MultiSite

comment:60 nemor21 months ago

foxinni, have you tried your multisite script on a local wordpress installation? I'm trying to use it, but it gives me this error:
Warning: getimagesize(C:/xampp/htdocs/wp-content/blogs.dir/3/files/2012/02/myimage.jpg) function.getimagesize: failed to open stream: No such file or directory in C:\xampp\htdocs\wordpress\wp-content\themes\supermassive\lib\scripts\image-resizer.php on line 52

The image is shown anyway, but in it's original size, not resized.

Last edited 21 months ago by nemor (previous) (diff)

comment:61 markoheijnen21 months ago

nemor: that is a problem on your local environment. There is also a change that this ticket will be invalidated/solved because of the work on #6821 to simplify some of the functions for better use cases like this.

Version 0, edited 21 months ago by markoheijnen (next)

comment:62 MatthewRuddy20 months ago

Anyway we can get this to work through a URL or an alternative? Currently using Ajax for getting resized versions of images to be replace via Javascript. Gets a bit much when there are a lot of images.

comment:64 alexvorn219 months ago

  • Cc alexvornoffice@… added

comment:66 ocean9019 months ago

#21961 was marked as a duplicate.

comment:67 follow-up: ocean9019 months ago

Interesting comment by scribu: ticket:21961#comment:3.

comment:68 in reply to: ↑ 67 Viper007Bond19 months ago

Replying to ocean90:

Interesting comment by scribu: ticket:21961#comment:3.

Good ol' race conditions.

At the hack day after WordCamp San Francisco, a bunch of us sat down and chatted about this for quite a while. The solution we came up we called "just too late" generation (as opposed to "just in time" aka on-demand). Missing thumbnails get served as browser-resized fullsize images and a thumbnail generation gets queued via WP Cron IIRC.

This issue is certainly highly complicated though and will need significant discussion before any code is actually written. The real work will be done via the planning rather than the code itself.

comment:69 viniciusmassuchetto19 months ago

Another reference: I wrote a plugin using 'phpThumb' and ImageMagick's 'convert' to generate and cache custom image sizes. It also supports shortcodes.

comment:70 jaredatch19 months ago

  • Cc jared@… added

prettyboymp19 months ago

Patch piggy backs off of 22100.2.diff in ticket @22100

comment:71 prettyboymp19 months ago

  • Cc mpretty@… added
  • Keywords has-patch added

Patch is based off of 22100.2.diff from #22100.

I do have concerns about the way I had to implement the callback since the image generation needs to happen under the wp-admin, so normal cron won't work. However, the post back will fail for sites that have the admin blocked with .htaccess. May want to consider setting a default static definition that turns off the ability to have late generated image sizes for this release and then creating a more robust way to run 'admin only' crons in a future release.

comment:72 MatthewRuddy18 months ago

Hey all, just thought I'd throw my own solution into the mix. I've developed a function that replicates Timthumb resizing exactly for seamless integration. I found the OP vt_resize function wouldn't crop the image in the same way to the exact dimensions specified.

I've been developing a slideshow plugin, so I needed images to be resized and cropped to exactly the dimensions I specified (just like Timthumb). I actually took the crop positioning calculations straight from Timthumb itself. You can have a look at the Github page below I've created for it.

http://matthewruddy.github.com/Wordpress-Timthumb-alternative

It has an alternative functions for Wordpress 3.5, which has added handy new image manipulation API. That said, I did find the new API to be slightly slower than the function provided for older Wordpress versions, but that's probably because there is a lot more going on (checks for GD or Imagemagik, etc).

comment:73 willmot18 months ago

Here's one of our plugins that implements on the fly image resizing.

https://github.com/humanmade/WPThumb

Under the hood it uses phpthumb which obviously wouldn't be appropriate for core but it would be easy to replace that with the new image resizing stuff in 3.5 (in-fact I think @markoheijnen is working on it, as are we).

It's well tested (40 odd unit tests) and runs on some pretty large sites (10's of millions of uniques per month).

comment:74 alexvorn218 months ago

the problem is that your plugins does not provide the image aligment: top/bottom as timthumb does. one static "image.jpg" should be dynamically resized to this name image-$width-$height-$aligment-$quality-$crop.jpg so after the image was resized, another image could be made if the settings of quality, cropped or not, alignment have been changed...

comment:75 follow-up: willmot18 months ago

I'm not sure what you mean by image alignment? Are you referring to the crop position? If so WP Thumb fully supports that (top, left, center, etc), it doesn't include the args in the resulting image name however as that can lead to long filenames and also could possibly be a security risk as you are exposing input data. You can generate as many different images from the same source as you want, each version is created and cached.

comment:76 in reply to: ↑ 75 alexvorn218 months ago

yes crop position, after the images was cropped and created, and if the user wants other crop position that he must first delete the old image before generating a new one.
I don't see a problem in long file and security risks? crop position or image quality can be a security risk?

comment:77 follow-up: willmot18 months ago

This probably isn't the best place to be arguing about our respective plugins :-), however, WP Thumb doesn't require you to delete the old image before generating a new one with a different crop position, have you used it? You can have as many different images as you want, each with different args (crop position, quality, etc.)

comment:78 in reply to: ↑ 77 alexvorn218 months ago

Replying to willmot:

This probably isn't the best place to be arguing about our respective plugins :-), however, WP Thumb doesn't require you to delete the old image before generating a new one with a different crop position, have you used it? You can have as many different images as you want, each with different args (crop position, quality, etc.)

You are right. I have not used it.

comment:79 aaronholbrook16 months ago

  • Cc aaron@… added

comment:80 esauvisky15 months ago

Is it possible to apply vt_resize automatically to every image that is displayed with lower dimensions than the original one?

For example, I have a 500x500px image, but I've used it with width:300px; height:300px. How can I automatically scale it without having to manually call vt_resize?

Last edited 15 months ago by esauvisky (previous) (diff)

comment:81 travisnorthcutt15 months ago

  • Cc travis@… added

comment:82 kraftbj15 months ago

  • Cc bk@… added

comment:83 bradyvercher15 months ago

  • Cc brady@… added

comment:84 francescolaffi15 months ago

  • Cc francesco.laffi@… added

comment:85 in reply to: ↑ 43 husobj13 months ago

  • Cc ben@… removed

Replying to scribu:

Here's my take on the whole thing:

  1. Add an 'immediate' parameter to each intermediate size. 'immediate' => true means the file is generated right after the attachment is uploaded.
  1. For 'immediate' => false sizes, generate it on the fly, only if it's not present in the array returned by wp_get_attachment_metadata().

I think adding this to the add_image_size() function would be an elegant way to implement new image sizes for generation on-demand (or just after)

comment:86 tar.gz12 months ago

  • Cc code@… added

comment:87 alex-ye12 months ago

  • Cc nashwan.doaqan@… added

comment:88 in reply to: ↑ 43 NickDC10 months ago

Replying to scribu:

  1. Add an 'immediate' parameter to each intermediate size. 'immediate' => true means the file is generated right after the attachment is uploaded.
  1. For 'immediate' => false sizes, generate it on the fly, only if it's not present in the array returned by wp_get_attachment_metadata().

This is a great approach. Is anyone working on a patch for this?

comment:89 SergeyBiryukov6 months ago

#25884 was marked as a duplicate.

comment:90 SergeyBiryukov6 months ago

#21295 was marked as a duplicate.

comment:91 drrobotnik5 months ago

Is anyone active on this issue? Since a lot of blogs are running on shared hosting media bloat can cause issues with maintenance. I've inherited a few photography projects where the hosting company has given a deadline to trim their media folder. Would everyone be in agreement that an on the fly solution would be the best place to start?

Media bloat Ref:#25884

comment:92 SergeyBiryukov6 weeks ago

#27395 was marked as a duplicate.

Note: See TracTickets for help on using tickets.