Beginner's Guide for WordPress - Start your WordPress Blog in minutes.
Choosing the Best
WordPress Hosting
How to Easily
Install WordPress
WordPress Plugins
View all Guides

How to Grayscale Images in WordPress

Last updated on by
Elegant Themes
How to Grayscale Images in WordPress

Did you ever wonder if there was a way to automatically grayscale images in WordPress when you upload them? Well the wondering time is over. In this article, we will show you how you can use some simple PHP image manipulation tools and WordPress functions to automatically grayscale images upon upload. You can use grayscale images for hover, sliders, gallery, or anything else you like.

Grayscale Images in WordPress

First thing you need to do is open your theme’s functions.php file and add the following code:

function themename_bw_size() {
	add_image_size('themename-bw-image', 100, 100, true);

The code above simply adds an additional image size for the uploader. The size is set to 100 x 100px with hard cropping. You may change the dimensions to fit your needs. Once you have done that, you need to add the following code:

function themename_bw_filter($meta) {
	$file = wp_upload_dir();
	$file = trailingslashit($file['path']).$meta['sizes']['themename-bw-image']['file'];
	list($orig_w, $orig_h, $orig_type) = @getimagesize($file);
	$image = wp_load_image($file);
	imagefilter($image, IMG_FILTER_GRAYSCALE);
	switch ($orig_type) {
			imagegif( $image, $file );
			imagepng( $image, $file );
			imagejpeg( $image, $file );
	return $meta;

The code above pretty much tells the uploader to create an extra size of the image you uploaded. Crop it to the size you have specified in the previous step. Then apply the image filter: Grayscale.

If you were doing this for your post thumbnails, then you can display it like this in your theme:

<?php the_post_thumbnail( 'themename-bw-image' ); ?>

If you want to do this for a specific attachment, then you can use wp_get_attachment_image function.

Note: You should change themename to your theme’s name.

All credits for this awesome trick goes to Otto.

Editorial Staff at WPBeginner is a team of WordPress lovers led by Syed Balkhi. Page maintained by Syed Balkhi.

WPBeginner's Video Icon
Our HD-Quality tutorial videos for WordPress Beginners will teach you how to use WordPress to create and manage your own website in about an hour. Get started now »


  1. geertvdheide says:

    One addition: I’ve added a few lines to get around the issue of having two images with the same file name, caused by having two add_image_size calls with the same size. The additional code was found here:

    • mklemme says:


      If you wanted to add multiple size support, try what I use:

      if ( function_exists( ‘add_theme_support’ ) ){

      add_theme_support( ‘post-thumbnails’ );

      set_post_thumbnail_size( 50, 50, true );

      add_image_size( ‘medium-thumb’, 660, ”, true );

      add_image_size( ‘large-thumb’, 960, ”, true );

      add_image_size( ‘small-thumb’, 100, ”, true );


      (The height is not defined, only the width.)

      you would have to add the different names to make the function apply to them all:

      ['medium-thumb' , 'large-thumb' , 'small-thumb'] in the filter code.

      Calling the thumbnail in your theme is the same listed in the article:

  2. geertvdheide says:

    Thanks for sharing this code! Except I’m running into a weird issue when trying to implement it. It’s related to the uploaded image’s size (pixel size, meaning its dimensions). Copied the code literally to my theme’s functions.php, and it works a charm with images larger than the size specified in the add_image_size call. But when using an image smaller than or equal to the size specified, the uploader in WordPress gives me errors and doesn’t process the image size (either from the media section of the admin environment, or from a specific post or page). The error:

    Warning: imagefilter() expects parameter 1 to be resource, string given.

    Ssome other stuff in the error as well, but this seems to be the main cause. The image data given to the imagefilter function must not be valid or doesn’t exist?

    Any idea what’s causing this? The only real difference between my situation and a clean install is that I’ve also added a few other add_image_size calls for other purposes in my site. I’m also adding the same size twice (one black/white, one regular), but that doesn’t seem to be a problem with the larger images.

    • Ed Nailor says:


      and for others that need this:

      When the script is converting the image to greyscale and the file uploaded does not fit the file size, this causes the script to break. To prevent this, simply add a quick if() conditional to make sure you have the $file.

      $file = trailingslashit($file['path']).$meta['sizes']['themename-bw-image']['file'];
      if( $file ) {
      list($orig_w, $orig_h, $orig_type) = @getimagesize($file);
      ——– remainder of code until ——–
      return $meta;

      This will check to make sure the file size you have requested exists before it tries to convert it.

      Hope that helps!

  3. frankiegershwin says:

    @Otto42 Thanks for offering. I will.

  4. Otto42 says:

    @frankiegershwin bummer! Feel free to email me directly for code help.

  5. frankiegershwin says:

    @Otto42 thank you! I had a bit of a hard time, actually and had to undoe it :( will pick it up tomorrow. It’s a good way to mix it up onsite

  6. Otto42 says:

    @frankiegershwin Lemme know if you need help. I added a way to do sepia tones too in my comments on the original post:

  7. rodhk says:

    @rodriguezhernan vaya idiotez de truco…. madremua tocar el codigo para eso

  8. wpbeginner says:

    @Otto Thanks for the comment Otto. Updated the post as well :)

  9. Otto says:

    Note that people should change “themename” to be the name of their theme instead.

Add a Comment

We're glad you have chosen to leave a comment. Please keep in mind that all comments are moderated according to our comment policy, and all links are nofollow. Do NOT use keywords in the name field. Let's have a personal and meaningful conversation.