Auto-Convert Image to WebP in WordPress (Programmatically)

Ever felt like your site’s loading slower?

If you’re looking for ways to optimize your WordPress site without compromising on quality. One of the easiest ways to do that is by converting your images to the WebP format, which is a more efficient image format that can reduce file size without sacrificing quality. The best part? You can automate this process directly within WordPress!

In this blog tutorial, I’ll show you how to use a simple PHP script to automatically convert images to WebP format when uploading to the WordPress media library. Plus, I’ll guide you through different methods to integrate this script into your WordPress site. Let’s dive in!

Why Convert Images to WebP?

First things first – what is WebP? Before we jump into the code, let’s quickly talk about why WebP.

WebP is a modern image format developed by Google, offering superior lossless and lossy compression for images on the web. According to Google, WebP images are 25-35% smaller in size compared to JPEGs and PNGs. Smaller images mean faster load times, which translates to better SEO, a smoother user experience, and less bandwidth usage.

The PHP Script for Automatic WebP Conversion

Alright, here is the star of the show: a simple PHP script that automatically converts JPEG and PNG images to WebP format during upload.

<?php

/**
 * Converts uploaded images to WebP format if the server supports it.
 *
 * This function hooks into the WordPress upload process and converts uploaded images
 * (JPEG, PNG) to WebP format. It checks if the GD library with WebP support is available,
 * handles different image types, preserves transparency for PNGs, and replaces the original
 * image with the WebP version.
 *
 * @param array $file An array of uploaded file data.
 * @return array The modified file data with WebP information if conversion is successful.
 */
function nin_convert_to_webp_upload($file) {
    // Check if the uploaded file is an image
    if (strpos($file['type'], 'image') !== false) {
        $image_path = $file['tmp_name']; // Temporary path of the uploaded image
        $webp_path = $image_path . '.webp'; // Path for the converted WebP image

        // Extract the file extension from the original file name
        $file_extension = pathinfo($file['name'], PATHINFO_EXTENSION);
        $allowed_extensions = ['jpg', 'jpeg', 'png']; // Supported image formats for conversion

        // Check if the file extension is supported
        if (in_array(strtolower($file_extension), $allowed_extensions)) {
            // Verify that the GD library with WebP support is available
            if (function_exists('imagewebp')) {
                // Handle different image types using a switch statement
                switch (strtolower($file_extension)) {
                    case 'jpg':
                    case 'jpeg':
                        // Create an image resource from a JPEG file
                        $image = imagecreatefromjpeg($image_path);
                        break;
                    case 'png':
                        // Create an image resource from a PNG file
                        $image = imagecreatefrompng($image_path);
                        // Preserve transparency for PNG images
                        imagealphablending($image, false);
                        imagesavealpha($image, true);
                        break;
                    default:
                        // Return the original file if the image type is unsupported
                        return $file;
                }

                // Set the quality for the WebP image (0-100, higher is better)
                $webp_quality = 80; // Adjust this value as needed

                // Check if the image resource was created successfully
                if ($image !== false) {
                    // Attempt to convert the image to WebP format
                    if (imagewebp($image, $webp_path, $webp_quality)) {
                        // Free up memory by destroying the image resource
                        imagedestroy($image);

                        // Replace the original image with the WebP version
                        unlink($image_path); // Delete the original image
                        rename($webp_path, $image_path); // Rename the WebP image to the original name

                        // Update the file information to reflect the WebP format
                        $file['name'] = preg_replace('/\.(jpe?g|png)$/i', '.webp', $file['name']);
                        $file['type'] = 'image/webp';
                    } else {
                        // Log an error if the conversion fails
                        error_log("Failed to convert {$file['name']} to WebP");
                    }
                } else {
                    // Log an error if the image resource creation fails
                    error_log("Failed to create image resource for {$file['name']}");
                }
            } else {
                // Log an error if the GD library with WebP support is missing
                error_log("GD library with WebP support is not available");
            }
        }
    }

    // Return the file data (modified or unmodified)
    return $file;
}

// Hook the function into the WordPress upload process
add_filter('wp_handle_upload_prefilter', 'nin_convert_to_webp_upload');

/**
 * Checks if the server supports WebP conversion and displays a warning if not.
 *
 * This function checks if the GD library with WebP support is available. If not,
 * it displays an admin notice warning the user to enable the required support.
 */
function nin_check_webp_support() {
    // Check if the GD library with WebP support is available
    if (!function_exists('imagewebp')) {
        // Add an admin notice if WebP support is missing
        add_action('admin_notices', function() {
            echo '<div class="error"><p>WebP conversion is not available. Please enable GD library with WebP support.</p></div>';
        });
    }
}

// Hook the function into the admin initialization process
add_action('admin_init', 'nin_check_webp_support');
PHP
Expand

How This Script Works

This PHP script hooks into the WordPress upload process using the wp_handle_upload_prefilter filter. Here’s a quick rundown of what the script does:

  1. Checks for WebP Support on the Server: A new function, check_webp_support(), checks if your server supports WebP conversion and notifies you in the WordPress admin if it doesn’t.
  2. Checks if the uploaded file is an image: The script first checks if the uploaded file is an image by inspecting its MIME type.
  3. Verifies the file extension: It then checks if the image is in JPEG, JPG, or PNG format, as these are the formats we want to convert to WebP.
  4. Converts the image to WebP: The script uses a switch statement to handle different image types, ensuring the correct function is used to create an image resource. For PNG images, it even preserves transparency.
  5. Sets WebP Quality: The script allows you to adjust the WebP quality with the $webp_quality variable, giving you control over the balance between file size and image quality.
  6. Handles Errors Gracefully: The script includes error handling and logs any issues that occur during the conversion process, helping you troubleshoot if something goes wrong.
  7. Replaces the original image: If the conversion is successful, the script replaces the original image file with the newly created WebP version and updates the file information accordingly.

Adding the Script to Your WordPress Site

Now, there are a few different ways you can add he script to your wordpress site, depending on your preference and technical comfort level. Choose your weapon:

1. Create a Custom Plugin

If you want a more portable solution, creating a custom plugin is the way to go. This method keeps your code separate from your theme, so you won’t lose it if you change themes.

  1. Create a new folder webp-ninja in the wp-content/plugins directory.
  2. Inside the folder, create a new webp-ninja.php PHP file.
  3. Paste the script into this file:
<?php
/*
Plugin Name: WebP Ninja
Plugin URI: https://singhnitin.com/auto-convert-image-to-webp-in-wordpress-programmatically
Description: Automatically converts JPEG and PNG images to WebP format during upload.
Version: 1.0
Author: Nitin Singh
Author URI: https://singhnitin.com
Text Domain: webp-ninja
*/

/**
 * This function hooks into the WordPress upload process and converts uploaded images
 * (JPEG, PNG) to WebP format. It checks if the GD library with WebP support is available,
 * handles different image types, preserves transparency for PNGs, and replaces the original
 * image with the WebP version.
 *
 * @param array $file An array of uploaded file data.
 * @return array The modified file data with WebP information if conversion is successful.
 */
function nin_convert_to_webp_upload($file) {
    // Check if the uploaded file is an image
    if (strpos($file['type'], 'image') !== false) {
        $image_path = $file['tmp_name']; // Temporary path of the uploaded image
        $webp_path = $image_path . '.webp'; // Path for the converted WebP image

        // Extract the file extension from the original file name
        $file_extension = pathinfo($file['name'], PATHINFO_EXTENSION);
        $allowed_extensions = ['jpg', 'jpeg', 'png']; // Supported image formats for conversion

        // Check if the file extension is supported
        if (in_array(strtolower($file_extension), $allowed_extensions)) {
            // Verify that the GD library with WebP support is available
            if (function_exists('imagewebp')) {
                // Handle different image types using a switch statement
                switch (strtolower($file_extension)) {
                    case 'jpg':
                    case 'jpeg':
                        // Create an image resource from a JPEG file
                        $image = imagecreatefromjpeg($image_path);
                        break;
                    case 'png':
                        // Create an image resource from a PNG file
                        $image = imagecreatefrompng($image_path);
                        // Preserve transparency for PNG images
                        imagealphablending($image, false);
                        imagesavealpha($image, true);
                        break;
                    default:
                        // Return the original file if the image type is unsupported
                        return $file;
                }

                // Set the quality for the WebP image (0-100, higher is better)
                $webp_quality = 80; // Adjust this value as needed

                // Check if the image resource was created successfully
                if ($image !== false) {
                    // Attempt to convert the image to WebP format
                    if (imagewebp($image, $webp_path, $webp_quality)) {
                        // Free up memory by destroying the image resource
                        imagedestroy($image);

                        // Replace the original image with the WebP version
                        unlink($image_path); // Delete the original image
                        rename($webp_path, $image_path); // Rename the WebP image to the original name

                        // Update the file information to reflect the WebP format
                        $file['name'] = preg_replace('/\.(jpe?g|png)$/i', '.webp', $file['name']);
                        $file['type'] = 'image/webp';
                    } else {
                        // Log an error if the conversion fails
                        error_log("Failed to convert {$file['name']} to WebP");
                    }
                } else {
                    // Log an error if the image resource creation fails
                    error_log("Failed to create image resource for {$file['name']}");
                }
            } else {
                // Log an error if the GD library with WebP support is missing
                error_log("GD library with WebP support is not available");
            }
        }
    }

    // Return the file data (modified or unmodified)
    return $file;
}

// Hook the function into the WordPress upload process
add_filter('wp_handle_upload_prefilter', 'nin_convert_to_webp_upload');

/**
 * Checks if the server supports WebP conversion and displays a warning if not.
 *
 * This function checks if the GD library with WebP support is available. If not,
 * it displays an admin notice warning the user to enable the required support.
 */
function nin_check_webp_support() {
    // Check if the GD library with WebP support is available
    if (!function_exists('imagewebp')) {
        // Add an admin notice if WebP support is missing
        add_action('admin_notices', function() {
            echo '<div class="error"><p>WebP conversion is not available. Please enable GD library with WebP support.</p></div>';
        });
    }
}

// Hook the function into the admin initialization process
add_action('admin_init', 'nin_check_webp_support');
PHP
  1. Save the file and activate your plugin from the WordPress dashboard.

2. Add to Your Theme’s ‘functions.php’ File

This is probably the most straightforward method. Simply open your theme’s functions.php file and paste the script at the bottom.

  1. Find and open your child theme’s functions.php.
  2. Scroll to the bottom of the file and paste the PHP script.
  3. Save the functions.php file.

3. Use a Code Snippets Plugin

If you’re not comfortable editing theme files or creating custom plugins, a code snippets plugin can be a great alternative. These plugins allow you to add custom code to your site without touching any files.

  • Install and activate a code snippets plugin like Code Snippets or FluentSnippets
  • Create a new snippet and paste the PHP script into the code editor.
  • Save and activate the snippet.

Final Thoughts

Optimizing your WordPress site’s performance is a continuous process, and converting images to WebP is a powerful way to make an immediate impact. With the script provided in this post, you can automate the conversion process and ensure that your images are always served in the most efficient format possible.

Whether you decide to add the script to your theme’s functions.php file, create a custom plugin, or use a code snippets plugin, the choice is yours. Just pick the method that fits best with your workflow and technical skill level.

And remember, always test your site thoroughly after making any changes, especially when working with image files. You don’t want to accidentally break something that was working perfectly before.

Happy coding! If you have any questions or run into any issues, feel free to drop a message.

Leave a Reply