13

As our users regularly upload ~6MB images to use on the website (and aren't too familiar with how to resize them first), WordPress stores the originals as well as resizing them to several different sizes.

I'd like a function or plugin that takes the uploaded image, resizes it down to something more manageable and then replaces the original.

I've seen some functions that delete the original but do not replace it, meaning it is impossible to regenerate the thumbnails at a later date. I need this to be replaced so the user can upload a large image and it is automatically resized down and stored for future resizing if needed.

4 Answers 4

12
+50

Add this to the functions.php file in the theme folder. It replaces the original image with the large image set in settings. You might want to setup a new image format and use that as the new original size though.

function replace_uploaded_image($image_data) {
      // if there is no large image : return
  if (!isset($image_data['sizes']['large'])) return $image_data;

  // paths to the uploaded image and the large image
  $upload_dir = wp_upload_dir();
  $uploaded_image_location = $upload_dir['basedir'] . '/' .$image_data['file'];
  // $large_image_location = $upload_dir['path'] . '/'.$image_data['sizes']['large']['file']; // ** This only works for new image uploads - fixed for older images below.
  $current_subdir = substr($image_data['file'],0,strrpos($image_data['file'],"/"));
  $large_image_location = $upload_dir['basedir'] . '/'.$current_subdir.'/'.$image_data['sizes']['large']['file'];

  // delete the uploaded image
  unlink($uploaded_image_location);

  // rename the large image
  rename($large_image_location,$uploaded_image_location);

  // update image metadata and return them
  $image_data['width'] = $image_data['sizes']['large']['width'];
  $image_data['height'] = $image_data['sizes']['large']['height'];
  unset($image_data['sizes']['large']);

  return $image_data;
}

add_filter('wp_generate_attachment_metadata','replace_uploaded_image');
13
  • 1
    If this solution works, it would be very useful to make a plugin.
    – Alexey
    Oct 15, 2012 at 16:13
  • I've just tried this again, and but first I added a new size (called 'fullsize') which was 2048x1536 (twice as big as I need it) and now it is all working, the original images are saved as just twice as big as I need them (which I want to keep for future) instead of many times. Thanks!
    – Shaun
    Feb 6, 2013 at 15:28
  • Great stuff, glad it worked out for you! Feb 9, 2013 at 9:01
  • This code deleted everything from my functions.php file. I checked in the WP editor and in FTP and the file was empty. Had to restore the file from a backup. :(
    – jlg
    Jan 7, 2014 at 16:39
  • 1
    @Ciprian You'd have to set up a script to iterate through them all. I'm sure there's a WordPress way of getting all the attachment info but $wpdb->get_col('SELECT id FROM wp_posts WHERE post_type="attachment" ORDER BY id'); would work to get a list of post Ids for the images. Maybe add: AND post_mime_type="image/jpeg" too to limit to just jpegs. The actual location of each image is held in wp_postmeta. Jun 2, 2016 at 17:33
3

There's one nasty bug in the solution above. The solution works as a charm for new images, but for old images, you should never compare to $upload_dir['path'] because that's the current upload folder of the current month.

Replace the following:

//$large_image_location = $upload_dir['path'] . '/'.$image_data['sizes']['large']['file'];
$large_image_location = $upload_dir['basedir'] . '/'.$image_data['sizes']['large']['path'];
2

May I suggest an update to the code of the above answer? Unfortunately in newer versions of Wordpress the key 'path' is no longer provided for the file sizes. So to make it work on older post uploads, we should first get the current subdir from the original image and use this to make the location path for the large image.

So replace this line:

$large_image_location = $upload_dir['basedir'] . '/'.$image_data['sizes']['large']['path'];

by these 2 lines:

$current_subdir = substr($image_data['file'],0,strrpos($image_data['file'],"/"));
$large_image_location = $upload_dir['basedir'] . '/'.$current_subdir.'/'.$image_data['sizes']['large']['file'];
0

I posted this on another very similar question here but thought it's worth reposting.

I had issues with the code above and what worked for me was essentially changing these lines.:

unlink($uploaded_image_location);
rename($large_image_location, $uploaded_image_location);

with:

    $file_to_be_copied = $large_image_location; 
    $copied_file_name = $uploaded_image_location;
  //make a copy of the large image and name that the title of the original image
    if (!copy($file_to_be_copied, $copied_file_name)) {
        echo "failed to copy $file...\n";
    }

I posted my full code and more explanation here: Delete original image - keep thumbnail?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

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