Programmatically Resize Images in WordPress

If you're experienced with programmatically uploading files, you may wish to skip down to the code.

I’m finishing up an application that’s built on WordPress that has required that I programmatically resize images. When it comes to building themes or plugins, it’s relatively easy to specify add_image_size and then let the user interface and core application do it’s thing.

But in my case, the end user will have no idea that the actual application is built on WordPress and the image resizing function needed to be a little more tailored for specific templates (or views)

So rather than use the typical WordPress facilities for uploading and resizing images, here’s how to programmatically resize images in WordPress.

The Process For Uploading Images

I’m not going to bother detailing the entire application (because there are a few helper methods that I use for doing things like validating file types and so on), but the general process is as follows:

  • The user clicks on an ‘Upload Image’ element in a form that uses JavaScript to prompt them to select an image
  • Once selected, the path to the file is kept in a hidden file input box
  • When the user as completed the rest of the form, they submit the form during which the image is uploaded

At this point, the server-side will upload the image then also set a second, resized version of the image. For this particular project, there’s a specific-size that the image needs to be so I’m able to hardcode those values.

With that said, here’s how I’m doing it.

Programmatically Resizing Images

For the most part, uploading the image is business as usual:

  • I check to see if the $_FILES array is set
  • Using a helper method, I determine if the file is a valid file type
  • I upload the file
  • I set the URL to the image on the post meta

Note that a ‘goal’ that you’ll see in the code is referring to a custom post type. Anyway, the code comments should be pretty clear, but here’s the code before I’m actually resizing the image:

// If the user uploaded an image, let's upload it to the server
if( ! empty( $_FILES ) && isset( $_FILES['goalImage'] ) {

	// Store the parts of the file name into an array
	$file_name_parts = explode( '.', $_FILES['goalImage']['name'] );

	// If the file is valid, upload the image, and store the path in the goal
	if( is_valid_file_type( $file_name_parts[ count( $file_name_parts ) - 1 ] ) ) {

		// Upload the goal image to the uploads directory, resize the image, then upload the resized version
		$goal_image_file = wp_upload_bits( $_FILES['goalImage']['name'], null, file_get_contents( $_FILES['goalImage']['tmp_name'] ) );

		// Set post meta about this image. Need the comment ID and need the path.
		if( false == $goal_image_file['error'] ) {

			// Since we've already added the key for this, we'll just update it with the file.
			update_post_meta( $goal_id, 'goal_image', $goal_image_file['url'] );

		} // end if/else

	} // end if

} // end if

At this point, I’ve taken the image that the user has uploaded and placed it in the uploads directory. No resizing has occurred.

Programmatically Resize Images

To programmatically resize images using the WordPress API, I used the image_resize function. To resize the image, I pass it the following parameters:

  • The file that the user has set to upload
  • The dimensions to which I want to resize the image
  • A boolean that I do not want it cropped (I want it resized)

The following code snippet shows exactly how I’m doing it:

$file_destination = image_resize( $goal_image_file['file'], 640, 480, false );

This will return a path to the file with the dimensions appended to the file name.

The challenge with this function is that the destination that it returns is essentially the fully qualified filename including the path. Of course, when uploading files, I only care about the filename itself.

To combat this, I then needed to take the returned destination, separate the various parts of the path, and just grab the filename:

// Get the actual filename (rather than the directory + filename)
$filename = explode( '/', $file_destination );
$filename = $filename[ count( $filename ) - 1 ]

From here, I can then take the filename and make a second call to wp_upload_bits and upload the resized version of the file to the uploads directory.

$goal_image_file = wp_upload_bits( $filename, null, file_get_contents( $_FILES['goalImage']['tmp_name'] ) );

At this point, we’re back to the usual process of making sure no error occurred and then doing whatever we need to do once the upload is complete.

The Full Function

Here’s the full block of code that I’ve written to upload an image, resize it, store the resized version in the uploads directory, and then associate the path to the file with the post meta:

// Finally, if the user uploaded an image, let's upload it to the server
if( ! empty( $_FILES ) && isset( $_FILES[ 'goalImage' ] ) ) {

	// Store the parts of the file name into an array
	$file_name_parts = explode( '.', $_FILES['goalImage']['name'] );

	// If the file is valid, upload the image, and store the path in the goal
	if( is_valid_file_type( $file_name_parts[ count( $file_name_parts ) - 1 ] ) ) {

		// Upload the goal image to the uploads directory, resize the image, then upload the resized version
		$goal_image_file = wp_upload_bits( $_FILES['goalImage']['name'], null, file_get_contents( $_FILES['goalImage']['tmp_name'] ) );

		// Resize the image to fit the single goal's page dimensions
		$file_destination = image_resize( $goal_image_file['file'], 458, 321, false );

		// Get the actual filename (rather than the directory + filename)
		$filename = explode( '/', $file_destination );
		$filename = $filename[ count( $filename ) - 1];

		// Upload the resized version of the file
		$goal_image_file = wp_upload_bits( $filename, null, file_get_contents( $_FILES['goalImage']['tmp_name'] ) );

		// Set post meta about this image. Need the comment ID and need the path.
		if( false == $goal_image_file['error'] ) {

			// Since we've already added the key for this, we'll just update it with the file.
			update_post_meta( $goal_id, 'goal_image', $goal_image_file['url'] );

		} // end if/else

	} // end if

} // end if

Note that I’m not handling the case for when an error occurs – that’s beyond the scope of this post, but it’s something that should be handled in your own work.

I’ll be the first to admit that this is new territory for me. Other than that, The solution works and it appears to work well, but if any of you have suggestions for improving the actual resizing, I’m all ears.

8 Comments

Hey Tom. Thanks for the tip. Please don’t mind me asking this stupid question but does the above code go in functions.php?

    Not a stupid question at all!

    It really depends on your implementation – if it’s meant to be run as a script, no. If it’s hooked into an action or is part of a plugin, then it’d need to be wrapped in a function.

    All depends on your use case.

I used something very simular for dynamically creating images. It is good to know I was not very far off at all! ;)

I do have a question though…

Is the call to wp_upload_bits necessary? According to the description of image_resize, “Scale down an image to fit a particular size and save a new copy of the image.“.

And if you look at the source code for image_resize, it does some chmoding at the end, like the file already exists there.

    For my specific needs, I need to keep the original version of the file on the server.

    I’ve never had success with just using image_resize to upload and manage the file. Another alternative would be to copy the file from one location to another, but wp_upload_bits uses the WordPress uploads directory and I like to keep consistent with that.

    Finally, I’m also associated the URL of the file with user meta data later in my project. But that’s my specific use case which is why I left it out (though that may help you with a bit more context).

Hi Tom, a couple of things that I would note are that your files are stored in the uploads directory, but they don’t appear to be exposed in the media library as attachments, and they’re not associated with their parent goal (aside from the meta data containing the resized image’s URL). It probably doesn’t matter that they’re not exposed in the media library from the end user’s perspective since they’re not aware WordPress is being used, but it would make management easier.

What I would suggest is passing the index in the $_FILES array to media_handle_upload() and let that take care of validating and uploading the image.

For your resized image, you could either use add_image_size(), which should be handled automatically by the above function, or even generate the resized image dynamically when it’s requested as demonstrated in this Gist. Or with a little more work, you could hook into wp_handle_upload and resize the image manually and store it in the _wp_attachment_metadata field of the original image.

The reason I’d recommend handling the resized image that way is so that the data is more portable and easily accessible with the available API functions. If you’re storing just the URL to the resized image, it’s not associated with the original image, which can’t be determined without reverse engineering the file name and looking up the original file, which can become a little more complicated than necessary. For those reasons, I’ve found it’s usually better to store an attachment ID rather than a file URL or path in a meta field.

Anyways, those are just a couple of observations I’ve made while working with files/images in similar scenarios in the past and those functions should help reduce the amount of code you need to write to securely handle uploads, create attachments, and access the resulting data in the rest of your application.

    As far as attachments concerned, you’re absolutely right – I’m storing the files there, but I’m not creating posts associated with them because the requirements don’t call for that.

    This particular project is literally sitting on top of WordPress, so no one ever really sees the admin dashboard (except for those that will have the backend keys).

    That said, I’m all for add_image_size, especially when working with themes and plugins – that way, it does exactly what you suggest: validation, attachment, sizing, and meta association.

    I probably should’ve been clearer about my particular context in the post, but I’m glad you left this comment. It’s especially useful for those that are looking to utilize the media library and the standard WordPress image functionality as well as when they’re working with themes, plugins, or some other similar project.

    Always dig your comments :).

hi, this sound perfect way to deal with image where i havent decide which themes to use,
ie; i m using default 2012 theme now and i upload my image and attach to a particular post with width of 600px,
after i had make-up my mind to change a 3 column theme, and i had to change ALL the image to 550px, will this work?

Leave a Reply

Name and email address are required. Your email address will not be published.

You may use these HTML tags and attributes:

<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>