wp_calculate_image_srcset

A helper function to calculate the image sources to include in a 'srcset' attribute.

Description

(string|bool) wp_calculate_image_srcset( (array) $size_array, (string) $image_src, (array) $image_meta, (int) $attachment_id = 0 ); 

Returns (string|bool)

The 'srcset' attribute value. False on error or when only one source exists.

Parameters (4)

0. $size_array (array)
Array of width and height values in pixels (in that order).
1. $image_src (string)
The src of the image.
2. $image_meta (array)
The image meta data as returned by wp_get_attachment_metadata()..
3. $attachment_id — Optional. (int)
The image attachment ID to pass to the filter. Default 0.

Usage

  1. if ( !function_exists( 'wp_calculate_image_srcset' ) ) { 
  2. require_once ABSPATH . WPINC . '/media.php'; 
  3.  
  4. // Array of width and height values in pixels (in that order). 
  5. $size_array = array(); 
  6.  
  7. // The 'src' of the image. 
  8. $image_src = ''; 
  9.  
  10. // The image meta data as returned by 'wp_get_attachment_metadata()'. 
  11. $image_meta = array(); 
  12.  
  13. // Optional. The image attachment ID to pass to the filter. Default 0. 
  14. $attachment_id = -1; 
  15.  
  16. // NOTICE! Understand what this does before running. 
  17. $result = wp_calculate_image_srcset($size_array, $image_src, $image_meta, $attachment_id); 
  18.  

Defined (1)

The function is defined in the following location(s).

/wp-includes/media.php  
  1. function wp_calculate_image_srcset( $size_array, $image_src, $image_meta, $attachment_id = 0 ) { 
  2. /** 
  3. * Let plugins pre-filter the image meta to be able to fix inconsistencies in the stored data. 
  4. * @param array $image_meta The image meta data as returned by 'wp_get_attachment_metadata()'. 
  5. * @param array $size_array Array of width and height values in pixels (in that order). 
  6. * @param string $image_src The 'src' of the image. 
  7. * @param int $attachment_id The image attachment ID or 0 if not supplied. 
  8. */ 
  9. $image_meta = apply_filters( 'wp_calculate_image_srcset_meta', $image_meta, $size_array, $image_src, $attachment_id ); 
  10.  
  11. if ( empty( $image_meta['sizes'] ) || ! isset( $image_meta['file'] ) || strlen( $image_meta['file'] ) < 4 ) { 
  12. return false; 
  13.  
  14. $image_sizes = $image_meta['sizes']; 
  15.  
  16. // Get the width and height of the image. 
  17. $image_width = (int) $size_array[0]; 
  18. $image_height = (int) $size_array[1]; 
  19.  
  20. // Bail early if error/no width. 
  21. if ( $image_width < 1 ) { 
  22. return false; 
  23.  
  24. $image_basename = wp_basename( $image_meta['file'] ); 
  25.  
  26. /** 
  27. * WordPress flattens animated GIFs into one frame when generating intermediate sizes. 
  28. * To avoid hiding animation in user content, if src is a full size GIF, a srcset attribute is not generated. 
  29. * If src is an intermediate size GIF, the full size is excluded from srcset to keep a flattened GIF from becoming animated. 
  30. */ 
  31. if ( ! isset( $image_sizes['thumbnail']['mime-type'] ) || 'image/gif' !== $image_sizes['thumbnail']['mime-type'] ) { 
  32. $image_sizes[] = array( 
  33. 'width' => $image_meta['width'],  
  34. 'height' => $image_meta['height'],  
  35. 'file' => $image_basename,  
  36. ); 
  37. } elseif ( strpos( $image_src, $image_meta['file'] ) ) { 
  38. return false; 
  39.  
  40. // Retrieve the uploads sub-directory from the full size image. 
  41. $dirname = _wp_get_attachment_relative_path( $image_meta['file'] ); 
  42.  
  43. if ( $dirname ) { 
  44. $dirname = trailingslashit( $dirname ); 
  45.  
  46. $upload_dir = wp_get_upload_dir(); 
  47. $image_baseurl = trailingslashit( $upload_dir['baseurl'] ) . $dirname; 
  48.  
  49. /** 
  50. * If currently on HTTPS, prefer HTTPS URLs when we know they're supported by the domain 
  51. * (which is to say, when they share the domain name of the current request). 
  52. */ 
  53. if ( is_ssl() && 'https' !== substr( $image_baseurl, 0, 5 ) && parse_url( $image_baseurl, PHP_URL_HOST ) === $_SERVER['HTTP_HOST'] ) { 
  54. $image_baseurl = set_url_scheme( $image_baseurl, 'https' ); 
  55.  
  56. /** 
  57. * Images that have been edited in WordPress after being uploaded will 
  58. * contain a unique hash. Look for that hash and use it later to filter 
  59. * out images that are leftovers from previous versions. 
  60. */ 
  61. $image_edited = preg_match( '/-e[0-9]{13}/', wp_basename( $image_src ), $image_edit_hash ); 
  62.  
  63. /** 
  64. * Filters the maximum image width to be included in a 'srcset' attribute. 
  65. * @since 4.4.0 
  66. * @param int $max_width The maximum image width to be included in the 'srcset'. Default '1600'. 
  67. * @param array $size_array Array of width and height values in pixels (in that order). 
  68. */ 
  69. $max_srcset_image_width = apply_filters( 'max_srcset_image_width', 1600, $size_array ); 
  70.  
  71. // Array to hold URL candidates. 
  72. $sources = array(); 
  73.  
  74. /** 
  75. * To make sure the ID matches our image src, we will check to see if any sizes in our attachment 
  76. * meta match our $image_src. If no matches are found we don't return a srcset to avoid serving 
  77. * an incorrect image. See #35045. 
  78. */ 
  79. $src_matched = false; 
  80.  
  81. /** 
  82. * Loop through available images. Only use images that are resized 
  83. * versions of the same edit. 
  84. */ 
  85. foreach ( $image_sizes as $image ) { 
  86. $is_src = false; 
  87.  
  88. // Check if image meta isn't corrupted. 
  89. if ( ! is_array( $image ) ) { 
  90. continue; 
  91.  
  92. // If the file name is part of the `src`, we've confirmed a match. 
  93. if ( ! $src_matched && false !== strpos( $image_src, $dirname . $image['file'] ) ) { 
  94. $src_matched = $is_src = true; 
  95.  
  96. // Filter out images that are from previous edits. 
  97. if ( $image_edited && ! strpos( $image['file'], $image_edit_hash[0] ) ) { 
  98. continue; 
  99.  
  100. /** 
  101. * Filters out images that are wider than '$max_srcset_image_width' unless 
  102. * that file is in the 'src' attribute. 
  103. */ 
  104. if ( $max_srcset_image_width && $image['width'] > $max_srcset_image_width && ! $is_src ) { 
  105. continue; 
  106.  
  107. // If the image dimensions are within 1px of the expected size, use it. 
  108. if ( wp_image_matches_ratio( $image_width, $image_height, $image['width'], $image['height'] ) ) { 
  109. // Add the URL, descriptor, and value to the sources array to be returned. 
  110. $source = array( 
  111. 'url' => $image_baseurl . $image['file'],  
  112. 'descriptor' => 'w',  
  113. 'value' => $image['width'],  
  114. ); 
  115.  
  116. // The 'src' image has to be the first in the 'srcset', because of a bug in iOS8. See #35030. 
  117. if ( $is_src ) { 
  118. $sources = array( $image['width'] => $source ) + $sources; 
  119. } else { 
  120. $sources[ $image['width'] ] = $source; 
  121.  
  122. /** 
  123. * Filters an image's 'srcset' sources. 
  124. * @since 4.4.0 
  125. * @param array $sources { 
  126. * One or more arrays of source data to include in the 'srcset'. 
  127. * @type array $width { 
  128. * @type string $url The URL of an image source. 
  129. * @type string $descriptor The descriptor type used in the image candidate string,  
  130. * either 'w' or 'x'. 
  131. * @type int $value The source width if paired with a 'w' descriptor, or a 
  132. * pixel density value if paired with an 'x' descriptor. 
  133. * } 
  134. * } 
  135. * @param array $size_array Array of width and height values in pixels (in that order). 
  136. * @param string $image_src The 'src' of the image. 
  137. * @param array $image_meta The image meta data as returned by 'wp_get_attachment_metadata()'. 
  138. * @param int $attachment_id Image attachment ID or 0. 
  139. */ 
  140. $sources = apply_filters( 'wp_calculate_image_srcset', $sources, $size_array, $image_src, $image_meta, $attachment_id ); 
  141.  
  142. // Only return a 'srcset' value if there is more than one source. 
  143. if ( ! $src_matched || count( $sources ) < 2 ) { 
  144. return false; 
  145.  
  146. $srcset = ''; 
  147.  
  148. foreach ( $sources as $source ) { 
  149. $srcset .= str_replace( ' ', '%20', $source['url'] ) . ' ' . $source['value'] . $source['descriptor'] . ', '; 
  150.  
  151. return rtrim( $srcset, ', ' );