JPEG thumbnails for PNG images in WordPress and other image-related issues

November 21, 2016

So far the biggest issue for me with WordPress is poor support for media files:

  • No built-in support for any categorisation of media files.

  • No built-in support for Retina.

  • Limited support for intermediate image sizes. For example I need 320px-wide images for screenshots in portrait orientation only, but if I add such custom image size, it will be created for all of my uploads, including photos and other images that will never need this size.

  • The standard "Add Media" function in the post editor inserts image with hard-coded image dimensions and absolute URLs including host name and scheme (!)

  • Need to manually update existing posts content after changing an intermediate image size. Currently I have blog post width set to 750px and have defined a custom image size with that width. If I decided to change the blog width, I'd need to update existing posts because paths to image files in them include the exact dimensions.

To avoid the last two problems, I use a shortcode that takes image name and size name and outputs the correct path, but that has its own downsides too. Since image file names include both the actual image width and height, I can't just take an original file name and construct the name of the 750px-wide version (because I don't know image height), so a database query is required for each image on the page to get the resized file name.

Of course there are plugins that solve some of these problems, but again that means you need to try dozens of bugged/ugly/paid plugins for a task to find the one that works for you, if any.

And finally, another problem is that WordPress always creates intermediate image sizes with the same format as the original images. I'm uploading a lot of PNG screenshots, but I definitely do not want to serve heavy losslessly-compressed files for smaller image versions, most of which are linked to their originals anyway. Below is a simple filter that I now use to convert smaller image versions from PNG to JPEG:

function mifki_png_to_jpg($filename)
{ 
    $ext = strrchr($filename, '.');
    if ($ext == '.png')
    {
        $new_filename = substr($filename, 0, -strlen($ext)).'.jpg';

        $editor = wp_get_image_editor($filename);

        if (is_wp_error($editor))
            return $filename;

        $resized_file = $editor->save($new_filename, 'image/jpeg');

        if (!is_wp_error($resized_file) && $resized_file)
        {
            unlink($filename);      
            return $new_filename;
        }
    }

    return $filename;
}

add_filter( 'image_make_intermediate_size', 'mifki_png_to_jpg', 10, 1 ); 

The only downside of this method is that the image is first created in PNG format and only then converted to JPEG, but this happens only once and there's no quality loss, so it's acceptable, though not ideal.

Actually, now I'm thinking I might try to use this filter also to change file names to include size name instead of exact dimensions - that way I'll be able to use file names directly in post content. And after that I'll probably work on dynamic image resizing so that image sizes I will not use are not generated.