A reference of miscellaneous snippets for manipulating WordPress image sizes. It’s a good idea to check which sizes the current site uses and whether some of them can be removed or consolidated into one size to save on disk space.
Listing available sizes
Here’s a handy function for listing WordPress image sizes, extracted from the Force Regenerate Thumbnails plugin:
/**
* @return array<string, array{width: int, height: int, crop: bool}>
*/
function get_image_sizes() {
$sizes = wp_get_registered_image_subsizes();
global $wpdb;
$latest_upload = (int)$wpdb->get_var("SELECT ID FROM $wpdb->posts WHERE post_type = 'attachment' AND post_mime_type LIKE '%%image%%' ORDER BY ID DESC LIMIT 1");
if($latest_upload) {
$image_meta = wp_get_attachment_metadata($latest_upload);
$sizes = apply_filters('intermediate_image_sizes_advanced', $sizes, $image_meta, $latest_upload);
}
uasort($sizes, fn($a, $b) => $a['width'] <=> $b['width']);
return $sizes;
}PHPThere seems to be some nuance to the intermediate_image_sizes_advanced filter, with it requiring the image meta from the latest upload – I haven’t looked into why, all that matters is that it will produce an array listing all the current image sizes, such as:
array(6) {
["thumbnail"] => array(3) {
["width"] => int(150)
["height"] => int(150)
["crop"] => bool(true)
}
["medium"] => array(3) {
["width"] => int(300)
["height"] => int(300)
["crop"] => bool(false)
}
["medium_large"] => array(3) {
["width"] => int(768)
["height"] => int(0)
["crop"] => bool(false)
}
["large"] => array(3) {
["width"] => int(1024)
["height"] => int(1024)
["crop"] => bool(false)
}
["1536x1536"] => array(3) {
["width"] => int(1536)
["height"] => int(1536)
["crop"] => bool(false)
}
["2048x2048"] => array(3) {
["width"] => int(2048)
["height"] => int(2048)
["crop"] => bool(false)
}
}Every image will also have the full size by default.
If you find that you have too many image sizes and the WP installation is getting too large to conveniently back up and move around, you can remove some of the sizes that are unused:
add_filter('intermediate_image_sizes_advanced', function($sizes) {
unset($sizes['medium_large']);
unset($sizes['large']);
unset($sizes['1536x1536']);
unset($sizes['2048x2048']);
return $sizes;
});After doing that, running Force Regenerate Thumbnails plugin is recommended to clean up all the old unused sizes.
WooCommerce
If you’re using WC then you’ll also have some additional image sizes:
array(9) {
...
["woocommerce_thumbnail"] => array(3) {
["width"] => int(300)
["height"] => int(300)
["crop"] => bool(true)
}
["woocommerce_gallery_thumbnail"] => array(3) {
["width"] => int(300)
["height"] => int(300)
["crop"] => bool(true)
}
["woocommerce_single"] => array(3) {
["width"] => int(600)
["height"] => int(0)
["crop"] => bool(false)
}
...
}To reduce your installation size you can modify the WC image sizes such that they overlap with existing image sizes, therefore so many different-sized images won’t be generated.
// Modify loop product image size
add_filter('woocommerce_get_image_size_thumbnail', function($size) {
...
return $size;
});
// Modify single product gallery image size
add_filter('woocommerce_get_image_size_gallery_thumbnail', function($size) {
...
return $size;
});
// Modify single product main image size
add_filter('woocommerce_get_image_size_single', function($size) {
// Use "large" image size
$size['width'] = 1024;
$size['height'] = 1024;
$size['crop'] = false;
return $size;
});PHPKeep in mind when using the same dimensions, but crop value doesn’t match, then the image sizes don’t match.
Attachments
The wp_count_attachments() function can give a quick overview of how many uploads of which types there are in the WordPress Media Library:
var_dump((array)wp_count_attachments());PHParray(7) {
["audio/mpeg"] => string(1) "2"
["image/jpeg"] => string(3) "257"
["image/png"] => string(2) "35"
["image/webp"] => string(1) "1"
["text/plain"] => string(1) "1"
["video/mp4"] => string(1) "5"
["trash"] => string(1) "0"
}Image dimensions EXIF data fix
PhotoSwipe is a brilliant lightbox solution for images – WooCommerce uses it by default, and I have used it for other purposes as well. Although for it to produce a cool zoom-in effect, it requires to know the image dimensions ahead of time as data-pswp-width and data-pswp-height attributes in the markup.
There is the WordPress wp_getimagesize() function that can be used for it, but I ran into issues where the dimensions for a few images were flipped – some images are rotated via EXIF data, but are actually sideways. Here’s a helper function that has proven to be useful for correcting for it:
/**
* @param string $url
* @return array|false
*/
public function get_image_dimensions($url) {
if(str_starts_with($url, '/')) {
$url = home_url($url);
}
if($image_size = wp_getimagesize($url)) {
[$width, $height] = $image_size;
/** Using logic from `wp_safe_redirect` to determine if URL is internal before trying `exif_read_data`. */
$url = wp_validate_redirect($url, '');
if($url) {
// Can produce "file not supported" warning.
if($exif = @exif_read_data($url)) { // phpcs:ignore WordPress.PHP.NoSilencedErrors.Discouraged
if(isset($exif['Orientation']) && in_array($exif['Orientation'], [6, 8], true)) {
/** Image is rotated 90deg, swap dimensions. */
return ['width' => $height, 'height' => $width];
}
}
}
return ['width' => $width, 'height' => $height];
}
return false;
}This EXIF data rotation can also cause issues when optimizing images – when converting images to WebP all EXIF data is usually stripped, the ImageMagick converter, for example, requires the -auto-orient command argument to be used to correctly rotate the image.
Block Editor
In the Block Editor Image sizes can be retrieved from the editor settings, how ever they don’t include any intermediate dimensions:
wp.data.select('core/editor').getEditorSettings().imageDimensionsJavaScript{
"thumbnail": {
"width": 150,
"height": 150,
"crop": true
},
"medium": {
"width": 300,
"height": 300,
"crop": false
},
"large": {
"width": 1024,
"height": 1024,
"crop": false
}
}Here’s a PHP function that retrieves all the other dimensions (including WooCommerce image sizes):
/**
* @return array<string, array{width: number, height: number, crop: bool}>
*/
function get_intermediate_image_dimensions() {
$dimensions = [];
$additional_sizes = wp_get_additional_image_sizes();
foreach(get_intermediate_image_sizes() as $size) {
if(in_array($size, ['medium_large'], true)) {
$width = (int)get_option("{$size}_size_w");
$height = (int)get_option("{$size}_size_h");
$crop = (bool)get_option("{$size}_crop");
} elseif(isset($additional_sizes[$size])) {
$width = (int)$additional_sizes[$size]['width'];
$height = (int)$additional_sizes[$size]['height'];
$crop = (bool)$additional_sizes[$size]['crop'];
} else {
continue;
}
$dimensions[$size] = [
'width' => $width,
'height' => $height,
'crop' => $crop,
];
}
return $dimensions;
}You would have to use wp_localize_script() or similar function to pass the value on to the JavaScript environment and then combine it with the imageDimensions from editor settings to get a full list of available image sizes in the block editor.
Leave a Reply