WordPress Image Editing Tutorial (WP_Image_Editor Class Examples)

Note: this article is intended for developers. If you are an end user looking for a WordPress image editing plugin, try Scissors and Watermark.

The WordPress 3.5 team has given us a super easy way to edit photos programmatically using the wp_image_editor class. This WordPress image editing tutorial will give usage examples of all image editing methods available in this class:

  • Resize images
  • Crop images
  • Rotate images
  • Flip images
  • Set image quality (compression levels)
  • Generate image filenames
  • Create image suffix
  • Get image sizes
  • Stream images to browser
  • Save images
  • Save images to multiple sizes (resolutions)
  • Check image mime-type support

Using WP_Image_Editor_Supports to Check Server Support

These photo editing functions require server side support via the widely available GD and/or ImageMagick libraries. So just because you or your theme/plugin users have WordPress 3.5.0+ installed, it doesn’t necessarily mean that these methods will be available. That’s where the WP_Image_Editor_Supports function comes in. You might want to stop here and read the WP_Image_Editor_Supports tutorial first.

Calling the Image Editor Function & Image Library Selection

The wp_image_editor class is never called directly. When you are writing your code, you will use the wp_get_image_editor function (note the “get” in the function name, this refers to the “getting” of an available image library for use).

Here is our first line of code:

This wp_get_image_editor function checks to see if the image libraries are available and selects one to use. Since ImageMagick is superior to GD, the function starts out by running a test to check if the ImageMagick extensions are installed and available in your hosting environment. If that test fails, it will check for GD support. If GD support fails, the function will error out. Failure to find an image library should never happen as you will have already checked for full support using the WP_Image_Editor_Supports function!

The argument used in this function is is the path to the image. The ABSPATH returns the absolute path to your WordPress directory (ie: home/username/public_html/wordpress/).

Using the Methods

We will try out all the available methods using the 1024 x 583 pixel test picture below. I’ll cover all available arguments and data returned for each method.

Many Bengal Cats playing in Snow

Our Test Image

You can download the test image and view license information here.

#1 Streaming Image to Browser

We’ll start out with how to stream an image to the browser. I will include this streaming method for much of the rest of the tutorial. That way we can see what we are doing.

This method actually sets the page header content-type [ie: ( ‘Content-Type: image/jpeg’ ); ], so you can’t just slap it into the middle of html content on your page and expect an image to be streamed out.

We will use a WordPress page template for our testing. Put the following code (and nothing more) into a blank WordPress page template file and preview the page:

As long as your image path is correct, your image will be streamed out to the browser like so:

WP_Image_Editor Streamed Image

The one argument available with this method is for setting the mime_type that is output. The function will check for mime-type support and keep the existing extension (as long as it’s compatible with the requested mime-type). If the requested mime-type is in a different format than the the image, then the image will be converted on the fly. So if you were to set the mime-type in the stream code above to this:

Then our jpg image would be converted to, and output as, a png.

What if I have to stream the image into a page of content?

In order to get this stream method to work in a “normal” page with other content, we would need to include the page of code above within another page like so:

Data returned by the stream method:

The image is returned. Nothing else.

#2 Resize an Image

The most popular one! Image resizing is what most people are here for. Here it is:

This code will resize the image to 500px (width) by 500px (height) with cropping on (true). Our example image is a wide, landscape oriented image, so the height is fewer pixels than the width. Therefore, it will take the height, the smallest of the two dimensions, and reduce it to 500px tall. The width will be scaled down also, so the aspect ratio is maintained. The remaining edges that fall outside our 500px width will be chopped off (cropped). The crop will cut equal amounts of the left and right side, gravitating toward the center of the image.


This will create a 500px by 500px cropped image:

500 by 500, cropped.

This will take the longest dimension of the image and resize it to 500px. Cropping is turned off. The aspect ratio is maintained. For our example image, this results in a 500px wide image with a height of 284px:

Many Bengal Cats playing in Snow

Here is an extended example with streaming turned off and resulting resize dimensions output instead:

Can I enlarge my images using resize?

No, but stay tuned. If you set the resize dimensions larger than the original image dimensions, no resizing or cropping will be performed. You can use the crop method to enlarge photos and make pixelated wonders.

Can I resize with only a width OR height requirement?

Yes, just make the dimension you don’t want touched NULL:

Data returned by the resize method:

$img->resize will return true if successful. No other information is returned. If you want to verify the size, use the get_size method (as seen is the example above).

#3 Resize an Image to Multiple Dimensions and Save

This method is just like the resize method, only it allows you to create many different image sizes at once, generates a filename, and saves them to the current image directory:

The foreach section loops through the returned array and will give you the filename, width, height, and mime-type of each image.

The code above created these images:

#1 (user_img-100×100.jpg)

Many Bengal Cats playing in Snow

#2 (user_img-175×100.jpg)

Many Bengal Cats playing in Snow

#3 (user_img-351×200.jpg)

Many Bengal Cats playing in Snow

#4 (user_img-450×256.jpg)

Many Bengal Cats playing in Snow

This method will overwrite any images in the current image directory that have the same output file name.

The save path and file name cannot be altered using this multi_resize method. If you need to control that, use the individual resize method multiple times.

Data returned by the multi_resize method:

A multidimensional array that includes the filename, width, height, and mime-type of each image is returned. An example of looping through these results is shown in the method example above.

#4 Set the Image Quality (compression)

ImageMagick’s compression works on a variety of image formats, but you will see the best results with the lossy jpeg format. The compression level can be set anywhere between 1 and 100. The default is 90.

We’ve resized our image to 500px wide, no cropping, and set the quality at 100 percent. The image produced is 191kb:

Many Bengal Cats playing in Snow

Now lets set the quality to 80. The image produced is 59kb:

Many Bengal Cats playing in Snow

At a quality of 60, our image becomes 48kb:

Many Bengal Cats playing in Snow

At a quality of 40, our image becomes 42kb:

Many Bengal Cats playing in Snow

At a quality of 20, it becomes 37kb:

Many Bengal Cats playing in Snow

As you can see, keeping the quality around 80 or above is probably a good idea.

Data returned by set_quality:

This method will return TRUE if successful. Nothing else is returned.

#5 Crop an Image ($img->crop)

There are a number of parameters on this method (src=source, dst=destination):

  1. $src_x (required) – determines the starting X position (left to right) to crop from.
  2. $src_y (required) – determines the starting Y position (top to bottom) to crop from.
  3. $src_w (required) – the width to crop
  4. $src_h (required) – the height to crop
  5. $dst_w (optional – default is null) – resizes to this width after cropping
  6. $dst_h (optional – default is null) – resizes to this height after cropping
  7. $src_abs (optional – default is false) – Does something interesting… see below.

Confused yet? This will example will clear it up. The red box is what we want to keep:


Shaded Box: src_x = 130px, src_y = 110px
Red Box: src_w = 107px, src_h = 145px

So we want to start our source X crop (src_x) 130px from the left and our source Y crop (src_y) 110px from the top. From this X/Y coordinate point that has been established (the bottom right of the shaded box), we want to create an image 107px wide (src_w) and 145px high (src_h).

Here is the code required to execute this crop:

Here is the result:

Many Bengal Cats playing in Snow

So now that we’ve covered 1-4 of the arguments, let cover 5 and 6.

dst_w and dst_h resizes the cropped image. If we wanted to double the size of our resulting crop (which at this time is 107x145px), we would make dst_w = 214 and our dst_h = 290:

That doubles the size of our image:

Many Bengal Cats playing in Snow

The last parameter (src_abs), if true, alters the src_w and src_h using this formula::

$src_w = $src_w – $src_x;
$src_h = $src_h – $src_y;

So it subtracts src_x and src_y amounts from the final image. I don’t know why you would want to use this, it makes no sense to me. The comments in the code say “If the source crop points are absolute“. Please leave a comment if you have found a scenario where this is useful.

Data returned by by crop:

Crop will return false on failure. Nothing else is returned.

#6 Rotate an Image

This method allows you to rotate an image counter-clockwise by degrees. Here is a 270 degree counter-clockwise rotation (same as a 90 degree clockwise rotation):

Many Bengal Cats playing in Snow

If you make a non-square rotation (ie: anything other than 90, 180, 270), the image will be angled and black background will fill in the image. Here is a 60 degree rotation:

Many Bengal Cats playing in Snow

Data returned by rotate method:

Rotate will return false if it fails. Nothing else is returned.

 #7 Flip an Image

This method allows you to flip an image on the vertical axis and on the horizontal axis. So if you change $horz to true, the image will be flipped on the horizontal axis, resulting in a vertical flip:

That code will give us this vertically flipped image:

Many Bengal Cats playing in Snow

To flip the image horizontally (vertical axis), we change the second argument to true:

Which gives us this:

Many Bengal Cats playing in Snow

You can set both arguments to true to flip both axes:

Many Bengal Cats playing in Snow

Data returned by the flip method:

The flip method returns true if successful. Nothing else is returned.

#8 Generating an image filename

This method generated an image file name suffix, path, and extension:

We have used the generate_filename method to set the filname and path used in the “save” method’s argument. The code above will rename our “user_img.jpg” to “user_img-final.jpg” and save it into “/final/” directory in our uploads folder.

If we wanted to convert the image to a png, we can set the their argument to “png” in the code above:

Data returned from the generate_filename method:

The full image path is returned as a string.

#9 Get an Image Filename Suffix

Whenever an image is resized (using any of the various methods) the filename suffix is updated with the new dimensions appended. As you have seen by now, whenever we resize the test image to a width of 300 pixels, the automatically generated filename looks like this: user_img-300×170.jpg. If we wanted to get this new suffix programmatically, we use get_suffix.

Refresh the page and you will see “Our new filename suffix is: 300×170

Data returned by the resize method:

The filename suffix is returned as a string.

#10 Get an Image Width and Height

Want to know what the width and height of the image currently is? This method will tell you:

The code above will output this:

Image is currently 1024 by 583
After resize, image is 500 by 284

Data returned by the get_size() method:

The image [width] and [height] is returned in an array.

 #11 Save Image

This method will save your current image with the destination, filename, and mime-type of your choosing. The first argument is for the destination directory and filename. If left NULL, the current image directory will be used and a filename will be generated automatically. The second argument is for mime-type. You can convert the image or leave it NULL to keep the current mime-type. In this example we will resize the image then save it with default settings:

If we wanted to set the save method arguments for destination and change the mime-type to png, we would do something like this:

Note that when selecting a destination directory, the directory must already exist. This method will not create a new directory for you.

Data returned by the save method:

An array with the image full path, filename, width, height, and mime-type are returned.

#12 Mime Type Support Check (supports_mime_type)

There is a dedicated support function available for checking mime-type and other photo editing method support. I would think you would want to get the mime-type using get_mime_type, then check it using the support function. But, if you want to do it this way instead of using wp_image_editor_supports, here is what you would do:

ImageMagick supports every image mime-type you will ever need. GD supports ‘image/jpeg’, ‘image/png’, and ‘image/gif’. If the editor is able to read the image format, but not output it, then ‘image/jpeg’ will be used as the default fallback output format.

Data returned by the supports_mime_type method:

If the mime-type is not supported, $img->supports_mime_type will return false.

Why even check the mime-type? Why not just check the extension?

You can rename interesting.exe to interesting.png. That doesn’t convert the executable to an image, it just messes up the extension. The mime-type check is a more reliable way to check the file type. That said, it’s not foolproof and can be faked.

Also, I’ve had a well-meaning client add “.jpg” to the end of their (non jpeg) photo file names when renaming images and emailing them to me (simply because he thought all images were supposed to end with .jpg). Mime-type checks will help in those situations.

How do I check for errors after each method is called?

Using wp_error.

Also, Mike Schroder, one of the developers, has some great information on the wp_image_editor class, including filters that can be used.

That’s it! Do you have a question about this WordPress image editing tutorial? Let me know in the comments.

41 thoughts on “WordPress Image Editing Tutorial (WP_Image_Editor Class Examples)

  1. What if you don’t have an absolute path? I’m trying to get my head around if someone uploads a PDF, then I can use these examples to create a thumbnail from it & link them up (even if I just add .jpg to the file name and add that to the thumbnail when called)

    1. You can use other types of paths. Both of these will work:

      $img = wp_get_image_editor( ‘http://upload.wikimedia.org/wikipedia/commons/b/b6/Felis_catus-cat_on_snow.jpg’ );

      $img = wp_get_image_editor( ‘wp/wp-content/uploads/temp/mypdf.pdf’ );

      After you get the path right, you would want to do something like this:
      $img = wp_get_image_editor( ‘my/temp/uploads/path/mypdf.pdf’ );
      $img->resize( 50, 50, true );
      $filename = $img->generate_filename( ‘thumb’, ‘wp/wp-content/uploads/thumbs/’, ‘jpg’ );
      $img->save($filename, ‘image/jpeg’);

      That will:
      1. Resize the PDF to 50x50px and crop it square
      2. Append ‘-thumb’ to the end of the filename, set the save path, set the file type extension
      3. Execute the save and convert to jpg.

  2. Your article was really helpful to me man… I didn’t know WordPress could manipulate thumbnails. Learning how to checking for errors, saving the file, and figuring out that $output->stream() outputs header info really helped! I’m using wp_image_editor for my client’s canvas wrapping business website. Sharing this, thanks 😀

  3. Thank you for this article.
    Unfortunately I can’t get wp_get_image_editor to work properly.

    He always gives me an invalid image error: “file is not an image”.
    But when I open the url to the image directly in the browser, the image opens as in your stream example.

    Is there a solution to this?
    I did the WP_Image_Editor_Supports Check as described.

    Thank you

    1. Make sure you are using a valid image type. Test using a jpg image. Then make sure your image path is valid using a simple test like this:

      $imagepath = ABSPATH."wp-content/uploads/temp/user_image.jpg";
      $type = 'image/jpeg';

      Running that will stream the image out to the browser (as long as the image exists and the path is correct). If it isn’t working, echo out $imagepath and make sure your image path is valid.

  4. Hi Brandon,

    Useful article – I notice the formula for the Crop ABS parameter. It seems to me that by absolute, they mean that the width and height parameters are actually passed as right and bottom. The formula for width is therefore:

    width = right – left + 1

    People will therefore have to presume that the WordPress formula expects that the bottom right corner location is passed as one pixel beyond the actual image dimension.

    In practice, the conversion is a bit simple, so the ABS parameter may not prove to be that useful.

    Mark Rabjohn
    Integrated Arts

  5. Check out our streaming image:

    I dont understand this part. Can care to elaborate a bit more. Thx

  6. Sorry the html tag was stripped out:

    What if I have to stream the image into a page of content?
    In order to get this stream method to work in a “normal” page with other content, we would need to include the page of code above within another page like so:

    Check out our streaming image:
    The image tag : src=wordpress-page-with-streaming-image-code-url


    I dont understand the top part. Can care to elaborate a bit more. Thx

  7. Is it possible to update a custom thumbnail size with an image cropped using this code? I have a custom thumbnail size, and I would like to update only one thumbnail size.

  8. Is it possible to use variable containing image path in argument of wp_get_image_editor function?

  9. Is there any chance to check that the resized images are exists? I don’t want to use the process (resize, crop) every time. My gallery seems too slow.

  10. Dear, I have a question. It’s about delete image? when i delete image in media. Image is created by wp_get_image_editor not delete

  11. Hi Brandon, Right now developing a WordPress theme for Wallpapers and there I need image to be resized and croped but I do not want to save these images on the folder. We only want the Images to be viewd and downloaded by the user. How can we do that using this class.

    1. Hi Rakesh, the “Streaming Image to Browser” section covers what you need. Once you are done resizing and/or cropping, use “stream()” instead of “save()” to output the reworked image to the user’s browser without saving it to your server:

      $img = wp_get_image_editor( ABSPATH.’wp-content/wallpapers/original_huge_4k_wallpaper_file.jpg’ );
      $img->resize( 1024, 768, true );

      Once the image is streamed to your user, it will leave the server’s memory.

  12. I tried this methode but the final result is an image that can not be saved by site visitors.

  13. Please, help. I’m a beginner. I did everything according to instructions, but i get error.what is the problem?
    if( has_post_thumbnail()) {
    $path = wp_get_image_editor( ‘home/potap/test_img.jpg’ );
    if ( ! is_wp_error( $path ) ) {
    $imgcropped->resize( 316, 316, false );
    $imgcropped->set_quality( 75 );
    echo ‘errors’;

  14. Heya!
    I used your tutorial in a recent project. Great one btw!!!!
    But does anybody here happen to know, does it have any trouble manipulating inages over 10Mb? We have increased memory and execution time and still nada. Smaller then 10Mb inages work just fine, so only courious if anybody knows of such a limits, as I have found nothing else related online.
    Thank you!

  15. Hi pls help me on this.

    i try to used this code:

    $img = wp_get_image_editor( ABSPATH.’wp-content/themes/evohairsubiaco/images/random-stuff2.jpg’ );
    if ( ! is_wp_error( $img ) ) {

    It display like this:
    Warning: Cannot modify header information – headers already sent by (output started at C:\xampp\htdocs\evohairsubiaco\wp-includes\class.wp-styles.php:125) in C:\xampp\htdocs\evohairsubiaco\wp-includes\class-wp-image-editor-gd.php on line 448 and then special character.


    1. Streaming an image sets the headers content type so it can’t be used within a website page.

      Re-sizing images each time a page loads would put a lot of strain on your server. Normally you should resize the image on upload, save the re-sized image to your server, then use the saved image on your website.

      1. Hi,

        I just noticed that the wp-image-editor() cannot resize from small image to big image?. Is there’s a way or another code to handle this problem?


  16. GREAT breakdown of the function – thanks. One question: are images created via this class automatically added to the media library? Or logged as an image size and associated with the original image?

  17. Hi there, nice tut, however when I do a $img->stream()

    it returns a load of strange characters instead of the image, please advise


Comments are closed.