How does WP media uploader create the 3 different sized images, and how can I duplicate it

The question:

I have finally!! got this thing I’ve tried about 12 times to make and 12 different ways, but finally got it to work,… sort of.

I made a custom metabox for uploading and attaching images to posts, and it doesn’t require you to use the horrible thickbox media uploader built into WP. I hate that thing. No, what I’ve done is just a group of inputs (title, description, file), which you can also duplicate, to add additional attachments if you want. So you fill in the fields, select an image to upload, and save draft or publish the post. Once there are attachments added to a post, the metabox will display the input fields, along with a preview image of the attached image for each attachment you added. The title and description fields are used to generate the file meta data, nothing is saved as the post_meta, that I know of. That’s currently all that I have gotten working so far.

I need to make it so that when you save/publish a post, inturn upload/create the attachment files, it will create the three image sizes as the default wp uploader would, thumbnail, medium, large, and keeping the full size image too. If that’s possible somehow. If not, I would like to otherwise use add_image_size() to create/define new custom sizes, and generate them that way instead, upon uploading.

I’m not sure which function is the most ideal to use in this case, maybe the image_make_intermediate_size() function would be better, or wp_create_thumbnail() or wp_crop_image()… who knows!!

I cannot figure out how to go about doing that, if I need to run the wp_handle_upload() function for each one, or maybe something involving the wp_generate_attachment_metadata() function. It’s confusing to me since the 3 image sizes are to be associated as variants of the same attachment, and how to go about doing that.

I have scoured the web, read the source of every wp media/upload/image related file, and played with just about every function there is for the media upload stuff and cannot find how WP creates the 3 image sizes anywhere, or how to do it myself.

In wp-includes/media.php the image_resize() function looks like it would be best since it’s exactly what it should be. I just can’t figure out for the life of me what the hell I’m missing or have tried doing but did wrong to make the image thumbnails.

Here’s my working function that does the wp_handle_upload() stuff and things, but it also needs to create the 100px thumb, and make a resize version of the image that is max-width like 500px, and saved as new files of the uploaded one.

function update_attachment(){
  global $post;

  wp_update_attachment_metadata( $post->ID, $_POST['a_image'] );

  if( !empty( $_FILES['a_image']['name'] )) { //New upload
    require_once( ABSPATH . 'wp-admin/includes/file.php' );

    $override['action'] = 'editpost';
    $url = wp_handle_upload( $_FILES['a_image'], $override );

    // $medium = image_make_intermediate_size( $uploaded_file['url'], 500, 400, true );
    // $thumb = = image_make_intermediate_size( $uploaded_file['url'], 100, 100, true );

    if ( isset( $file['error'] )) {
      return new WP_Error( 'upload_error', $file['error'] );
    }

    $array_type = wp_check_filetype
    $allowed_file_types = array('image/jpg','image/jpeg','image/gif','image/png');

    $name_parts = pathinfo( $name );
    $name = trim( substr( $name, 0, - ( 1 + strlen( $name_parts['extension'] )) ));

    $type = $file['type'];
    $file = $file['file'];
    $title = $_POST['a_title'] ? $_POST['a_title'] : $name;
    $content = $_POST['a_desc']

    $post_id = $post->ID;
    $attachment = array(
      'post_title' => $title,
      'post_type' => 'attachment',
      'post_content' => $content,
      'post_parent' => $post_id,
      'post_mime_type' => $type,
      'guid' => $url['url']
    );


    // Save the data
    $id = wp_insert_attachment( $attachment, $_FILES['a_image'][ 'file' ]/*, $post_id - for post_thumbnails*/);

    if ( !is_wp_error( $id )) {
      $attach_meta = wp_generate_attachment_metadata( $id, $uploaded_file['url'] );
      wp_update_attachment_metadata( $attach_id, $attach_meta );
    }
    update_post_meta( $post->ID, 'a_image', $uploaded_file['url'] );
  }
}

Anyone able to help me finally fix this so it works proper would be loved. I’ve spent so many ridiculous countless hours numerous different times trying to develop this thing and the documentation sucks, and there’s not really any good posts anywhere on how to do it.

Thanks

The Solutions:

Below are the methods you can try. The first solution is probably the best. Try others if the first one doesn’t work. Senior developers aren’t just copying/pasting – they read the methods carefully & apply them wisely to each case.

Method 1

Hi @jaredwilli:

Dude! Valiant effort, and nice work. All-in-all it could be a great addition to WordPress.

You were so close, but you had somewhere between 5 and 10 little failed assumptions or code that looks like you started it but didn’t get back to it because it wasn’t working. I reworked your function only as much as I needed to correct it. The solution follows, and I’ll leave the side-by-side comparison to your or someone less burned-out. 🙂

function update_attachment() {
  global $post;
  wp_update_attachment_metadata( $post->ID, $_POST['a_image'] );
  if( !empty( $_FILES['a_image']['name'] )) { //New upload
    require_once( ABSPATH . 'wp-admin/includes/file.php' );

    $override['action'] = 'editpost';
    $file = wp_handle_upload( $_FILES['a_image'], $override );

    if ( isset( $file['error'] )) {
      return new WP_Error( 'upload_error', $file['error'] );
    }

    $file_type = wp_check_filetype($_FILES['a_image']['name'], array(
      'jpg|jpeg' => 'image/jpeg',
      'gif' => 'image/gif',
      'png' => 'image/png',
    ));
    if ($file_type['type']) {
      $name_parts = pathinfo( $file['file'] );
      $name = $file['filename'];
      $type = $file['type'];
      $title = $_POST['a_title'] ? $_POST['a_title'] : $name;
      $content = $_POST['a_desc'];

      $post_id = $post->ID;
      $attachment = array(
        'post_title' => $title,
        'post_type' => 'attachment',
        'post_content' => $content,
        'post_parent' => $post_id,
        'post_mime_type' => $type,
        'guid' => $file['url'],
      );

      foreach( get_intermediate_image_sizes() as $s ) {
        $sizes[$s] = array( 'width' => '', 'height' => '', 'crop' => true );
        $sizes[$s]['width'] = get_option( "{$s}_size_w" ); // For default sizes set in options
        $sizes[$s]['height'] = get_option( "{$s}_size_h" ); // For default sizes set in options
        $sizes[$s]['crop'] = get_option( "{$s}_crop" ); // For default sizes set in options
      }

      $sizes = apply_filters( 'intermediate_image_sizes_advanced', $sizes );

      foreach( $sizes as $size => $size_data ) {
        $resized = image_make_intermediate_size( $file['file'], $size_data['width'], $size_data['height'], $size_data['crop'] );
        if ( $resized )
          $metadata['sizes'][$size] = $resized;
      }

      $attach_id = wp_insert_attachment( $attachment, $file['file'] /*, $post_id - for post_thumbnails*/);

      if ( !is_wp_error( $id )) {
        $attach_meta = wp_generate_attachment_metadata( $attach_id, $file['file'] );
        wp_update_attachment_metadata( $attach_id, $attach_meta );
      }
      update_post_meta( $post->ID, 'a_image', $file['url'] );
    }
  }
}

Hey, why not splurge and get yourself a copy of PhpStorm? You could have easily solved this yourself, you were sooo close, if you could have just traced through the code like I now can. If you do, don’t waste your time on the very buggy XDEBUG and instead download Zend Debugger.

P.S. This is my former answer. I posted this before I realized what exactly Jared was asking. It is correct, but not related to his question. 🙂


I think what you are looking for is add_image_size():

add_image_size( $size_id, $width, $height, $crop );

For example:

add_image_size('headshot', 130, 150);
add_image_size('large-headshot', 260, 300);

By setting this WordPress will create those sizes automatically. What that what you needed?

Method 2

if i understand you question you need to get the list of sizes first like this:

$image_sizes = get_intermediate_image_sizes();

this returns an array of all image sizes registered (defaults: large, medium, thumbnail , any custom size registered using “add_image_size()”
then all you have to do is loop trough each one of the sizes and create an image for that size like this:

$foreach ($image_sizes as $size){
    images[] = image_make_intermediate_size($file, $size['width'], $size['height'], $crop); 
}

replace $file with the uploaded file path and $crop with true or false if you want to crop the image to the new dimensions or false to resize.


All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0

Leave a Comment