Every time you upload a JPEG, WordPress saves the thumbnails and the other image sizes at quality 82, and since WordPress 5.3 a large upload is also scaled down and saved again at that quality. Photographers, portfolio sites and shops with detailed product photos often see that as soft edges and banding. This snippet removes the WordPress default image compression for the sizes it creates, or sets your own quality per format.
The older version of this post said the default is 90%. That was true before WordPress 4.5; it has been 82 since then.
The snippet
<?php
/**
* Change the quality WordPress uses when it saves resized images (default 82).
*/
// ===== Config =====
function dpc_image_quality_config(): array {
return array(
// Quality 1-100 per format. Leave a format out to keep the WordPress default.
'image/jpeg' => 100,
'image/webp' => 100,
// 'image/avif' => 90,
);
}
// ===== End of config =====
add_filter( 'wp_editor_set_quality', 'dpc_image_quality', 10, 2 );
function dpc_image_quality( $quality, $mime_type = '' ) {
$config = dpc_image_quality_config();
if ( isset( $config[ $mime_type ] ) ) {
return max( 1, min( 100, (int) $config[ $mime_type ] ) );
}
return $quality;
}
How it works
- Every resized image goes through
WP_Image_Editor::set_quality(), which asks thewp_editor_set_qualityfilter for the quality of that image’s MIME type. The snippet returns your value for the formats in the config. - The older
jpeg_qualityfilter from the original post only covered JPEGs.wp_editor_set_qualityalso handles WebP and AVIF, which WordPress can create since 5.8 and 6.5. - Values are limited to 1–100, and formats that are not in the config keep the WordPress default.
- It works the same with GD and Imagick, whichever the server uses.
Add it with Scripts Organizer
In Scripts Organizer go to Code Blocks → Add New and give the block a name. Set Trigger location to Everywhere, tick PHP under Script location, paste the code into the PHP editor, edit the config and publish. Leave Action/Hook empty.
Images are resized in wp-admin, in the REST API requests the block editor uploads through, and sometimes in cron. Everywhere covers all of them.
The same code also works unchanged in a small plugin or an mu-plugin.
Customise it
- A balance between size and quality: 90 for JPEG is hard to tell apart from 100 and much smaller.
- PNG is lossless; its quality value only changes the compression level, so it is not in the config.
- Fewer copies of each upload: see Disable WordPress default Image Sizes.
Gotchas
- Only new uploads are affected. Regenerate thumbnails, for example with
wp media regenerate, to apply the new quality to existing images. - The original file you upload is never recompressed. Large uploads over 2560 px are scaled and saved as
-scaledcopies; that copy now uses your quality too. To keep the original as the main image, addadd_filter( 'big_image_size_threshold', '__return_false' );. - Quality 100 makes files much larger, often two to three times the size at 82. Check your page weight after the change.
- Image optimisation plugins and CDNs may recompress the files afterwards, which undoes this setting.
In the Scripts Organizer library Import it with one click from Scripts Organizer.