wp_get_attachment_image

The timeline below displays how wordpress function wp_get_attachment_image has changed across different WordPress versions. If a version is not listed, refer to the next available version below.

WordPress Version: 6.4

/**
 * Gets an HTML img element representing an image attachment.
 *
 * While `$size` will accept an array, it is better to register a size with
 * add_image_size() so that a cropped version is generated. It's much more
 * efficient than having to find the closest-sized image and then having the
 * browser scale down the image.
 *
 * @since 2.5.0
 * @since 4.4.0 The `$srcset` and `$sizes` attributes were added.
 * @since 5.5.0 The `$loading` attribute was added.
 * @since 6.1.0 The `$decoding` attribute was added.
 *
 * @param int          $attachment_id Image attachment ID.
 * @param string|int[] $size          Optional. Image size. Accepts any registered image size name, or an array
 *                                    of width and height values in pixels (in that order). Default 'thumbnail'.
 * @param bool         $icon          Optional. Whether the image should be treated as an icon. Default false.
 * @param string|array $attr {
 *     Optional. Attributes for the image markup.
 *
 *     @type string       $src      Image attachment URL.
 *     @type string       $class    CSS class name or space-separated list of classes.
 *                                  Default `attachment-$size_class size-$size_class`,
 *                                  where `$size_class` is the image size being requested.
 *     @type string       $alt      Image description for the alt attribute.
 *     @type string       $srcset   The 'srcset' attribute value.
 *     @type string       $sizes    The 'sizes' attribute value.
 *     @type string|false $loading  The 'loading' attribute value. Passing a value of false
 *                                  will result in the attribute being omitted for the image.
 *                                  Defaults to 'lazy', depending on wp_lazy_loading_enabled().
 *     @type string       $decoding The 'decoding' attribute value. Possible values are
 *                                  'async' (default), 'sync', or 'auto'. Passing false or an empty
 *                                  string will result in the attribute being omitted.
 * }
 * @return string HTML img element or empty string on failure.
 */
function wp_get_attachment_image($attachment_id, $size = 'thumbnail', $icon = false, $attr = '')
{
    $html = '';
    $image = wp_get_attachment_image_src($attachment_id, $size, $icon);
    if ($image) {
        list($src, $width, $height) = $image;
        $attachment = get_post($attachment_id);
        $hwstring = image_hwstring($width, $height);
        $size_class = $size;
        if (is_array($size_class)) {
            $size_class = implode('x', $size_class);
        }
        $default_attr = array('src' => $src, 'class' => "attachment-{$size_class} size-{$size_class}", 'alt' => trim(strip_tags(get_post_meta($attachment_id, '_wp_attachment_image_alt', true))));
        /**
         * Filters the context in which wp_get_attachment_image() is used.
         *
         * @since 6.3.0
         *
         * @param string $context The context. Default 'wp_get_attachment_image'.
         */
        $context = apply_filters('wp_get_attachment_image_context', 'wp_get_attachment_image');
        $attr = wp_parse_args($attr, $default_attr);
        $loading_attr = $attr;
        $loading_attr['width'] = $width;
        $loading_attr['height'] = $height;
        $loading_optimization_attr = wp_get_loading_optimization_attributes('img', $loading_attr, $context);
        // Add loading optimization attributes if not available.
        $attr = array_merge($attr, $loading_optimization_attr);
        // Omit the `decoding` attribute if the value is invalid according to the spec.
        if (empty($attr['decoding']) || !in_array($attr['decoding'], array('async', 'sync', 'auto'), true)) {
            unset($attr['decoding']);
        }
        /*
         * If the default value of `lazy` for the `loading` attribute is overridden
         * to omit the attribute for this image, ensure it is not included.
         */
        if (isset($attr['loading']) && !$attr['loading']) {
            unset($attr['loading']);
        }
        // If the `fetchpriority` attribute is overridden and set to false or an empty string.
        if (isset($attr['fetchpriority']) && !$attr['fetchpriority']) {
            unset($attr['fetchpriority']);
        }
        // Generate 'srcset' and 'sizes' if not already present.
        if (empty($attr['srcset'])) {
            $image_meta = wp_get_attachment_metadata($attachment_id);
            if (is_array($image_meta)) {
                $size_array = array(absint($width), absint($height));
                $srcset = wp_calculate_image_srcset($size_array, $src, $image_meta, $attachment_id);
                $sizes = wp_calculate_image_sizes($size_array, $src, $image_meta, $attachment_id);
                if ($srcset && ($sizes || !empty($attr['sizes']))) {
                    $attr['srcset'] = $srcset;
                    if (empty($attr['sizes'])) {
                        $attr['sizes'] = $sizes;
                    }
                }
            }
        }
        /**
         * Filters the list of attachment image attributes.
         *
         * @since 2.8.0
         *
         * @param string[]     $attr       Array of attribute values for the image markup, keyed by attribute name.
         *                                 See wp_get_attachment_image().
         * @param WP_Post      $attachment Image attachment post.
         * @param string|int[] $size       Requested image size. Can be any registered image size name, or
         *                                 an array of width and height values in pixels (in that order).
         */
        $attr = apply_filters('wp_get_attachment_image_attributes', $attr, $attachment, $size);
        $attr = array_map('esc_attr', $attr);
        $html = rtrim("<img {$hwstring}");
        foreach ($attr as $name => $value) {
            $html .= " {$name}=" . '"' . $value . '"';
        }
        $html .= ' />';
    }
    /**
     * Filters the HTML img element representing an image attachment.
     *
     * @since 5.6.0
     *
     * @param string       $html          HTML img element or empty string on failure.
     * @param int          $attachment_id Image attachment ID.
     * @param string|int[] $size          Requested image size. Can be any registered image size name, or
     *                                    an array of width and height values in pixels (in that order).
     * @param bool         $icon          Whether the image should be treated as an icon.
     * @param string[]     $attr          Array of attribute values for the image markup, keyed by attribute name.
     *                                    See wp_get_attachment_image().
     */
    return apply_filters('wp_get_attachment_image', $html, $attachment_id, $size, $icon, $attr);
}

WordPress Version: 6.3

/**
 * Gets an HTML img element representing an image attachment.
 *
 * While `$size` will accept an array, it is better to register a size with
 * add_image_size() so that a cropped version is generated. It's much more
 * efficient than having to find the closest-sized image and then having the
 * browser scale down the image.
 *
 * @since 2.5.0
 * @since 4.4.0 The `$srcset` and `$sizes` attributes were added.
 * @since 5.5.0 The `$loading` attribute was added.
 * @since 6.1.0 The `$decoding` attribute was added.
 *
 * @param int          $attachment_id Image attachment ID.
 * @param string|int[] $size          Optional. Image size. Accepts any registered image size name, or an array
 *                                    of width and height values in pixels (in that order). Default 'thumbnail'.
 * @param bool         $icon          Optional. Whether the image should be treated as an icon. Default false.
 * @param string|array $attr {
 *     Optional. Attributes for the image markup.
 *
 *     @type string       $src      Image attachment URL.
 *     @type string       $class    CSS class name or space-separated list of classes.
 *                                  Default `attachment-$size_class size-$size_class`,
 *                                  where `$size_class` is the image size being requested.
 *     @type string       $alt      Image description for the alt attribute.
 *     @type string       $srcset   The 'srcset' attribute value.
 *     @type string       $sizes    The 'sizes' attribute value.
 *     @type string|false $loading  The 'loading' attribute value. Passing a value of false
 *                                  will result in the attribute being omitted for the image.
 *                                  Defaults to 'lazy', depending on wp_lazy_loading_enabled().
 *     @type string       $decoding The 'decoding' attribute value. Possible values are
 *                                  'async' (default), 'sync', or 'auto'. Passing false or an empty
 *                                  string will result in the attribute being omitted.
 * }
 * @return string HTML img element or empty string on failure.
 */
function wp_get_attachment_image($attachment_id, $size = 'thumbnail', $icon = false, $attr = '')
{
    $html = '';
    $image = wp_get_attachment_image_src($attachment_id, $size, $icon);
    if ($image) {
        list($src, $width, $height) = $image;
        $attachment = get_post($attachment_id);
        $hwstring = image_hwstring($width, $height);
        $size_class = $size;
        if (is_array($size_class)) {
            $size_class = implode('x', $size_class);
        }
        $default_attr = array('src' => $src, 'class' => "attachment-{$size_class} size-{$size_class}", 'alt' => trim(strip_tags(get_post_meta($attachment_id, '_wp_attachment_image_alt', true))), 'decoding' => 'async');
        /**
         * Filters the context in which wp_get_attachment_image() is used.
         *
         * @since 6.3.0
         *
         * @param string $context The context. Default 'wp_get_attachment_image'.
         */
        $context = apply_filters('wp_get_attachment_image_context', 'wp_get_attachment_image');
        $attr = wp_parse_args($attr, $default_attr);
        $loading_attr = $attr;
        $loading_attr['width'] = $width;
        $loading_attr['height'] = $height;
        $loading_optimization_attr = wp_get_loading_optimization_attributes('img', $loading_attr, $context);
        // Add loading optimization attributes if not available.
        $attr = array_merge($attr, $loading_optimization_attr);
        // Omit the `decoding` attribute if the value is invalid according to the spec.
        if (empty($attr['decoding']) || !in_array($attr['decoding'], array('async', 'sync', 'auto'), true)) {
            unset($attr['decoding']);
        }
        /*
         * If the default value of `lazy` for the `loading` attribute is overridden
         * to omit the attribute for this image, ensure it is not included.
         */
        if (isset($attr['loading']) && !$attr['loading']) {
            unset($attr['loading']);
        }
        // If the `fetchpriority` attribute is overridden and set to false or an empty string.
        if (isset($attr['fetchpriority']) && !$attr['fetchpriority']) {
            unset($attr['fetchpriority']);
        }
        // Generate 'srcset' and 'sizes' if not already present.
        if (empty($attr['srcset'])) {
            $image_meta = wp_get_attachment_metadata($attachment_id);
            if (is_array($image_meta)) {
                $size_array = array(absint($width), absint($height));
                $srcset = wp_calculate_image_srcset($size_array, $src, $image_meta, $attachment_id);
                $sizes = wp_calculate_image_sizes($size_array, $src, $image_meta, $attachment_id);
                if ($srcset && ($sizes || !empty($attr['sizes']))) {
                    $attr['srcset'] = $srcset;
                    if (empty($attr['sizes'])) {
                        $attr['sizes'] = $sizes;
                    }
                }
            }
        }
        /**
         * Filters the list of attachment image attributes.
         *
         * @since 2.8.0
         *
         * @param string[]     $attr       Array of attribute values for the image markup, keyed by attribute name.
         *                                 See wp_get_attachment_image().
         * @param WP_Post      $attachment Image attachment post.
         * @param string|int[] $size       Requested image size. Can be any registered image size name, or
         *                                 an array of width and height values in pixels (in that order).
         */
        $attr = apply_filters('wp_get_attachment_image_attributes', $attr, $attachment, $size);
        $attr = array_map('esc_attr', $attr);
        $html = rtrim("<img {$hwstring}");
        foreach ($attr as $name => $value) {
            $html .= " {$name}=" . '"' . $value . '"';
        }
        $html .= ' />';
    }
    /**
     * Filters the HTML img element representing an image attachment.
     *
     * @since 5.6.0
     *
     * @param string       $html          HTML img element or empty string on failure.
     * @param int          $attachment_id Image attachment ID.
     * @param string|int[] $size          Requested image size. Can be any registered image size name, or
     *                                    an array of width and height values in pixels (in that order).
     * @param bool         $icon          Whether the image should be treated as an icon.
     * @param string[]     $attr          Array of attribute values for the image markup, keyed by attribute name.
     *                                    See wp_get_attachment_image().
     */
    return apply_filters('wp_get_attachment_image', $html, $attachment_id, $size, $icon, $attr);
}

WordPress Version: 6.2

/**
 * Gets an HTML img element representing an image attachment.
 *
 * While `$size` will accept an array, it is better to register a size with
 * add_image_size() so that a cropped version is generated. It's much more
 * efficient than having to find the closest-sized image and then having the
 * browser scale down the image.
 *
 * @since 2.5.0
 * @since 4.4.0 The `$srcset` and `$sizes` attributes were added.
 * @since 5.5.0 The `$loading` attribute was added.
 * @since 6.1.0 The `$decoding` attribute was added.
 *
 * @param int          $attachment_id Image attachment ID.
 * @param string|int[] $size          Optional. Image size. Accepts any registered image size name, or an array
 *                                    of width and height values in pixels (in that order). Default 'thumbnail'.
 * @param bool         $icon          Optional. Whether the image should be treated as an icon. Default false.
 * @param string|array $attr {
 *     Optional. Attributes for the image markup.
 *
 *     @type string       $src      Image attachment URL.
 *     @type string       $class    CSS class name or space-separated list of classes.
 *                                  Default `attachment-$size_class size-$size_class`,
 *                                  where `$size_class` is the image size being requested.
 *     @type string       $alt      Image description for the alt attribute.
 *     @type string       $srcset   The 'srcset' attribute value.
 *     @type string       $sizes    The 'sizes' attribute value.
 *     @type string|false $loading  The 'loading' attribute value. Passing a value of false
 *                                  will result in the attribute being omitted for the image.
 *                                  Defaults to 'lazy', depending on wp_lazy_loading_enabled().
 *     @type string       $decoding The 'decoding' attribute value. Possible values are
 *                                  'async' (default), 'sync', or 'auto'. Passing false or an empty
 *                                  string will result in the attribute being omitted.
 * }
 * @return string HTML img element or empty string on failure.
 */
function wp_get_attachment_image($attachment_id, $size = 'thumbnail', $icon = false, $attr = '')
{
    $html = '';
    $image = wp_get_attachment_image_src($attachment_id, $size, $icon);
    if ($image) {
        list($src, $width, $height) = $image;
        $attachment = get_post($attachment_id);
        $hwstring = image_hwstring($width, $height);
        $size_class = $size;
        if (is_array($size_class)) {
            $size_class = implode('x', $size_class);
        }
        $default_attr = array('src' => $src, 'class' => "attachment-{$size_class} size-{$size_class}", 'alt' => trim(strip_tags(get_post_meta($attachment_id, '_wp_attachment_image_alt', true))), 'decoding' => 'async');
        // Add `loading` attribute.
        if (wp_lazy_loading_enabled('img', 'wp_get_attachment_image')) {
            $default_attr['loading'] = wp_get_loading_attr_default('wp_get_attachment_image');
        }
        $attr = wp_parse_args($attr, $default_attr);
        // Omit the `decoding` attribute if the value is invalid according to the spec.
        if (empty($attr['decoding']) || !in_array($attr['decoding'], array('async', 'sync', 'auto'), true)) {
            unset($attr['decoding']);
        }
        // If the default value of `lazy` for the `loading` attribute is overridden
        // to omit the attribute for this image, ensure it is not included.
        if (array_key_exists('loading', $attr) && !$attr['loading']) {
            unset($attr['loading']);
        }
        // Generate 'srcset' and 'sizes' if not already present.
        if (empty($attr['srcset'])) {
            $image_meta = wp_get_attachment_metadata($attachment_id);
            if (is_array($image_meta)) {
                $size_array = array(absint($width), absint($height));
                $srcset = wp_calculate_image_srcset($size_array, $src, $image_meta, $attachment_id);
                $sizes = wp_calculate_image_sizes($size_array, $src, $image_meta, $attachment_id);
                if ($srcset && ($sizes || !empty($attr['sizes']))) {
                    $attr['srcset'] = $srcset;
                    if (empty($attr['sizes'])) {
                        $attr['sizes'] = $sizes;
                    }
                }
            }
        }
        /**
         * Filters the list of attachment image attributes.
         *
         * @since 2.8.0
         *
         * @param string[]     $attr       Array of attribute values for the image markup, keyed by attribute name.
         *                                 See wp_get_attachment_image().
         * @param WP_Post      $attachment Image attachment post.
         * @param string|int[] $size       Requested image size. Can be any registered image size name, or
         *                                 an array of width and height values in pixels (in that order).
         */
        $attr = apply_filters('wp_get_attachment_image_attributes', $attr, $attachment, $size);
        $attr = array_map('esc_attr', $attr);
        $html = rtrim("<img {$hwstring}");
        foreach ($attr as $name => $value) {
            $html .= " {$name}=" . '"' . $value . '"';
        }
        $html .= ' />';
    }
    /**
     * Filters the HTML img element representing an image attachment.
     *
     * @since 5.6.0
     *
     * @param string       $html          HTML img element or empty string on failure.
     * @param int          $attachment_id Image attachment ID.
     * @param string|int[] $size          Requested image size. Can be any registered image size name, or
     *                                    an array of width and height values in pixels (in that order).
     * @param bool         $icon          Whether the image should be treated as an icon.
     * @param string[]     $attr          Array of attribute values for the image markup, keyed by attribute name.
     *                                    See wp_get_attachment_image().
     */
    return apply_filters('wp_get_attachment_image', $html, $attachment_id, $size, $icon, $attr);
}

WordPress Version: 6.1

/**
 * Gets an HTML img element representing an image attachment.
 *
 * While `$size` will accept an array, it is better to register a size with
 * add_image_size() so that a cropped version is generated. It's much more
 * efficient than having to find the closest-sized image and then having the
 * browser scale down the image.
 *
 * @since 2.5.0
 * @since 4.4.0 The `$srcset` and `$sizes` attributes were added.
 * @since 5.5.0 The `$loading` attribute was added.
 * @since 6.1.0 The `$decoding` attribute was added.
 *
 * @param int          $attachment_id Image attachment ID.
 * @param string|int[] $size          Optional. Image size. Accepts any registered image size name, or an array
 *                                    of width and height values in pixels (in that order). Default 'thumbnail'.
 * @param bool         $icon          Optional. Whether the image should be treated as an icon. Default false.
 * @param string|array $attr {
 *     Optional. Attributes for the image markup.
 *
 *     @type string       $src      Image attachment URL.
 *     @type string       $class    CSS class name or space-separated list of classes.
 *                                  Default `attachment-$size_class size-$size_class`,
 *                                  where `$size_class` is the image size being requested.
 *     @type string       $alt      Image description for the alt attribute.
 *     @type string       $srcset   The 'srcset' attribute value.
 *     @type string       $sizes    The 'sizes' attribute value.
 *     @type string|false $loading  The 'loading' attribute value. Passing a value of false
 *                                  will result in the attribute being omitted for the image.
 *                                  Defaults to 'lazy', depending on wp_lazy_loading_enabled().
 *     @type string       $decoding The 'decoding' attribute value. Possible values are
 *                                  'async' (default), 'sync', or 'auto'.
 * }
 * @return string HTML img element or empty string on failure.
 */
function wp_get_attachment_image($attachment_id, $size = 'thumbnail', $icon = false, $attr = '')
{
    $html = '';
    $image = wp_get_attachment_image_src($attachment_id, $size, $icon);
    if ($image) {
        list($src, $width, $height) = $image;
        $attachment = get_post($attachment_id);
        $hwstring = image_hwstring($width, $height);
        $size_class = $size;
        if (is_array($size_class)) {
            $size_class = implode('x', $size_class);
        }
        $default_attr = array('src' => $src, 'class' => "attachment-{$size_class} size-{$size_class}", 'alt' => trim(strip_tags(get_post_meta($attachment_id, '_wp_attachment_image_alt', true))), 'decoding' => 'async');
        // Add `loading` attribute.
        if (wp_lazy_loading_enabled('img', 'wp_get_attachment_image')) {
            $default_attr['loading'] = wp_get_loading_attr_default('wp_get_attachment_image');
        }
        $attr = wp_parse_args($attr, $default_attr);
        // If the default value of `lazy` for the `loading` attribute is overridden
        // to omit the attribute for this image, ensure it is not included.
        if (array_key_exists('loading', $attr) && !$attr['loading']) {
            unset($attr['loading']);
        }
        // Generate 'srcset' and 'sizes' if not already present.
        if (empty($attr['srcset'])) {
            $image_meta = wp_get_attachment_metadata($attachment_id);
            if (is_array($image_meta)) {
                $size_array = array(absint($width), absint($height));
                $srcset = wp_calculate_image_srcset($size_array, $src, $image_meta, $attachment_id);
                $sizes = wp_calculate_image_sizes($size_array, $src, $image_meta, $attachment_id);
                if ($srcset && ($sizes || !empty($attr['sizes']))) {
                    $attr['srcset'] = $srcset;
                    if (empty($attr['sizes'])) {
                        $attr['sizes'] = $sizes;
                    }
                }
            }
        }
        /**
         * Filters the list of attachment image attributes.
         *
         * @since 2.8.0
         *
         * @param string[]     $attr       Array of attribute values for the image markup, keyed by attribute name.
         *                                 See wp_get_attachment_image().
         * @param WP_Post      $attachment Image attachment post.
         * @param string|int[] $size       Requested image size. Can be any registered image size name, or
         *                                 an array of width and height values in pixels (in that order).
         */
        $attr = apply_filters('wp_get_attachment_image_attributes', $attr, $attachment, $size);
        $attr = array_map('esc_attr', $attr);
        $html = rtrim("<img {$hwstring}");
        foreach ($attr as $name => $value) {
            $html .= " {$name}=" . '"' . $value . '"';
        }
        $html .= ' />';
    }
    /**
     * Filters the HTML img element representing an image attachment.
     *
     * @since 5.6.0
     *
     * @param string       $html          HTML img element or empty string on failure.
     * @param int          $attachment_id Image attachment ID.
     * @param string|int[] $size          Requested image size. Can be any registered image size name, or
     *                                    an array of width and height values in pixels (in that order).
     * @param bool         $icon          Whether the image should be treated as an icon.
     * @param string[]     $attr          Array of attribute values for the image markup, keyed by attribute name.
     *                                    See wp_get_attachment_image().
     */
    return apply_filters('wp_get_attachment_image', $html, $attachment_id, $size, $icon, $attr);
}

WordPress Version: 5.9

/**
 * Get an HTML img element representing an image attachment.
 *
 * While `$size` will accept an array, it is better to register a size with
 * add_image_size() so that a cropped version is generated. It's much more
 * efficient than having to find the closest-sized image and then having the
 * browser scale down the image.
 *
 * @since 2.5.0
 * @since 4.4.0 The `$srcset` and `$sizes` attributes were added.
 * @since 5.5.0 The `$loading` attribute was added.
 *
 * @param int          $attachment_id Image attachment ID.
 * @param string|int[] $size          Optional. Image size. Accepts any registered image size name, or an array
 *                                    of width and height values in pixels (in that order). Default 'thumbnail'.
 * @param bool         $icon          Optional. Whether the image should be treated as an icon. Default false.
 * @param string|array $attr {
 *     Optional. Attributes for the image markup.
 *
 *     @type string       $src     Image attachment URL.
 *     @type string       $class   CSS class name or space-separated list of classes.
 *                                 Default `attachment-$size_class size-$size_class`,
 *                                 where `$size_class` is the image size being requested.
 *     @type string       $alt     Image description for the alt attribute.
 *     @type string       $srcset  The 'srcset' attribute value.
 *     @type string       $sizes   The 'sizes' attribute value.
 *     @type string|false $loading The 'loading' attribute value. Passing a value of false
 *                                 will result in the attribute being omitted for the image.
 *                                 Defaults to 'lazy', depending on wp_lazy_loading_enabled().
 * }
 * @return string HTML img element or empty string on failure.
 */
function wp_get_attachment_image($attachment_id, $size = 'thumbnail', $icon = false, $attr = '')
{
    $html = '';
    $image = wp_get_attachment_image_src($attachment_id, $size, $icon);
    if ($image) {
        list($src, $width, $height) = $image;
        $attachment = get_post($attachment_id);
        $hwstring = image_hwstring($width, $height);
        $size_class = $size;
        if (is_array($size_class)) {
            $size_class = implode('x', $size_class);
        }
        $default_attr = array('src' => $src, 'class' => "attachment-{$size_class} size-{$size_class}", 'alt' => trim(strip_tags(get_post_meta($attachment_id, '_wp_attachment_image_alt', true))));
        // Add `loading` attribute.
        if (wp_lazy_loading_enabled('img', 'wp_get_attachment_image')) {
            $default_attr['loading'] = wp_get_loading_attr_default('wp_get_attachment_image');
        }
        $attr = wp_parse_args($attr, $default_attr);
        // If the default value of `lazy` for the `loading` attribute is overridden
        // to omit the attribute for this image, ensure it is not included.
        if (array_key_exists('loading', $attr) && !$attr['loading']) {
            unset($attr['loading']);
        }
        // Generate 'srcset' and 'sizes' if not already present.
        if (empty($attr['srcset'])) {
            $image_meta = wp_get_attachment_metadata($attachment_id);
            if (is_array($image_meta)) {
                $size_array = array(absint($width), absint($height));
                $srcset = wp_calculate_image_srcset($size_array, $src, $image_meta, $attachment_id);
                $sizes = wp_calculate_image_sizes($size_array, $src, $image_meta, $attachment_id);
                if ($srcset && ($sizes || !empty($attr['sizes']))) {
                    $attr['srcset'] = $srcset;
                    if (empty($attr['sizes'])) {
                        $attr['sizes'] = $sizes;
                    }
                }
            }
        }
        /**
         * Filters the list of attachment image attributes.
         *
         * @since 2.8.0
         *
         * @param string[]     $attr       Array of attribute values for the image markup, keyed by attribute name.
         *                                 See wp_get_attachment_image().
         * @param WP_Post      $attachment Image attachment post.
         * @param string|int[] $size       Requested image size. Can be any registered image size name, or
         *                                 an array of width and height values in pixels (in that order).
         */
        $attr = apply_filters('wp_get_attachment_image_attributes', $attr, $attachment, $size);
        $attr = array_map('esc_attr', $attr);
        $html = rtrim("<img {$hwstring}");
        foreach ($attr as $name => $value) {
            $html .= " {$name}=" . '"' . $value . '"';
        }
        $html .= ' />';
    }
    /**
     * HTML img element representing an image attachment.
     *
     * @since 5.6.0
     *
     * @param string       $html          HTML img element or empty string on failure.
     * @param int          $attachment_id Image attachment ID.
     * @param string|int[] $size          Requested image size. Can be any registered image size name, or
     *                                    an array of width and height values in pixels (in that order).
     * @param bool         $icon          Whether the image should be treated as an icon.
     * @param string[]     $attr          Array of attribute values for the image markup, keyed by attribute name.
     *                                    See wp_get_attachment_image().
     */
    return apply_filters('wp_get_attachment_image', $html, $attachment_id, $size, $icon, $attr);
}

WordPress Version: 5.6

/**
 * Get an HTML img element representing an image attachment.
 *
 * While `$size` will accept an array, it is better to register a size with
 * add_image_size() so that a cropped version is generated. It's much more
 * efficient than having to find the closest-sized image and then having the
 * browser scale down the image.
 *
 * @since 2.5.0
 * @since 4.4.0 The `$srcset` and `$sizes` attributes were added.
 * @since 5.5.0 The `$loading` attribute was added.
 *
 * @param int          $attachment_id Image attachment ID.
 * @param string|int[] $size          Optional. Image size. Accepts any registered image size name, or an array
 *                                    of width and height values in pixels (in that order). Default 'thumbnail'.
 * @param bool         $icon          Optional. Whether the image should be treated as an icon. Default false.
 * @param string|array $attr {
 *     Optional. Attributes for the image markup.
 *
 *     @type string       $src     Image attachment URL.
 *     @type string       $class   CSS class name or space-separated list of classes.
 *                                 Default `attachment-$size_class size-$size_class`,
 *                                 where `$size_class` is the image size being requested.
 *     @type string       $alt     Image description for the alt attribute.
 *     @type string       $srcset  The 'srcset' attribute value.
 *     @type string       $sizes   The 'sizes' attribute value.
 *     @type string|false $loading The 'loading' attribute value. Passing a value of false
 *                                 will result in the attribute being omitted for the image.
 *                                 Defaults to 'lazy', depending on wp_lazy_loading_enabled().
 * }
 * @return string HTML img element or empty string on failure.
 */
function wp_get_attachment_image($attachment_id, $size = 'thumbnail', $icon = false, $attr = '')
{
    $html = '';
    $image = wp_get_attachment_image_src($attachment_id, $size, $icon);
    if ($image) {
        list($src, $width, $height) = $image;
        $attachment = get_post($attachment_id);
        $hwstring = image_hwstring($width, $height);
        $size_class = $size;
        if (is_array($size_class)) {
            $size_class = implode('x', $size_class);
        }
        $default_attr = array('src' => $src, 'class' => "attachment-{$size_class} size-{$size_class}", 'alt' => trim(strip_tags(get_post_meta($attachment_id, '_wp_attachment_image_alt', true))));
        // Add `loading` attribute.
        if (wp_lazy_loading_enabled('img', 'wp_get_attachment_image')) {
            $default_attr['loading'] = 'lazy';
        }
        $attr = wp_parse_args($attr, $default_attr);
        // If the default value of `lazy` for the `loading` attribute is overridden
        // to omit the attribute for this image, ensure it is not included.
        if (array_key_exists('loading', $attr) && !$attr['loading']) {
            unset($attr['loading']);
        }
        // Generate 'srcset' and 'sizes' if not already present.
        if (empty($attr['srcset'])) {
            $image_meta = wp_get_attachment_metadata($attachment_id);
            if (is_array($image_meta)) {
                $size_array = array(absint($width), absint($height));
                $srcset = wp_calculate_image_srcset($size_array, $src, $image_meta, $attachment_id);
                $sizes = wp_calculate_image_sizes($size_array, $src, $image_meta, $attachment_id);
                if ($srcset && ($sizes || !empty($attr['sizes']))) {
                    $attr['srcset'] = $srcset;
                    if (empty($attr['sizes'])) {
                        $attr['sizes'] = $sizes;
                    }
                }
            }
        }
        /**
         * Filters the list of attachment image attributes.
         *
         * @since 2.8.0
         *
         * @param string[]     $attr       Array of attribute values for the image markup, keyed by attribute name.
         *                                 See wp_get_attachment_image().
         * @param WP_Post      $attachment Image attachment post.
         * @param string|int[] $size       Requested image size. Can be any registered image size name, or
         *                                 an array of width and height values in pixels (in that order).
         */
        $attr = apply_filters('wp_get_attachment_image_attributes', $attr, $attachment, $size);
        $attr = array_map('esc_attr', $attr);
        $html = rtrim("<img {$hwstring}");
        foreach ($attr as $name => $value) {
            $html .= " {$name}=" . '"' . $value . '"';
        }
        $html .= ' />';
    }
    /**
     * HTML img element representing an image attachment.
     *
     * @since 5.6.0
     *
     * @param string       $html          HTML img element or empty string on failure.
     * @param int          $attachment_id Image attachment ID.
     * @param string|int[] $size          Requested image size. Can be any registered image size name, or
     *                                    an array of width and height values in pixels (in that order).
     * @param bool         $icon          Whether the image should be treated as an icon.
     * @param string[]     $attr          Array of attribute values for the image markup, keyed by attribute name.
     *                                    See wp_get_attachment_image().
     */
    return apply_filters('wp_get_attachment_image', $html, $attachment_id, $size, $icon, $attr);
}

WordPress Version: 5.1

/**
 * Get an HTML img element representing an image attachment
 *
 * While `$size` will accept an array, it is better to register a size with
 * add_image_size() so that a cropped version is generated. It's much more
 * efficient than having to find the closest-sized image and then having the
 * browser scale down the image.
 *
 * @since 2.5.0
 * @since 4.4.0 The `$srcset` and `$sizes` attributes were added.
 * @since 5.5.0 The `$loading` attribute was added.
 *
 * @param int          $attachment_id Image attachment ID.
 * @param string|array $size          Optional. Image size. Accepts any valid image size, or an array of width
 *                                    and height values in pixels (in that order). Default 'thumbnail'.
 * @param bool         $icon          Optional. Whether the image should be treated as an icon. Default false.
 * @param string|array $attr {
 *     Optional. Attributes for the image markup.
 *
 *     @type string       $src     Image attachment URL.
 *     @type string       $class   CSS class name or space-separated list of classes.
 *                                 Default `attachment-$size_class size-$size_class`,
 *                                 where `$size_class` is the image size being requested.
 *     @type string       $alt     Image description for the alt attribute.
 *     @type string       $srcset  The 'srcset' attribute value.
 *     @type string       $sizes   The 'sizes' attribute value.
 *     @type string|false $loading The 'loading' attribute value. Passing a value of false
 *                                 will result in the attribute being omitted for the image.
 *                                 Defaults to 'lazy', depending on wp_lazy_loading_enabled().
 * }
 * @return string HTML img element or empty string on failure.
 */
function wp_get_attachment_image($attachment_id, $size = 'thumbnail', $icon = false, $attr = '')
{
    $html = '';
    $image = wp_get_attachment_image_src($attachment_id, $size, $icon);
    if ($image) {
        list($src, $width, $height) = $image;
        $attachment = get_post($attachment_id);
        $hwstring = image_hwstring($width, $height);
        $size_class = $size;
        if (is_array($size_class)) {
            $size_class = join('x', $size_class);
        }
        $default_attr = array('src' => $src, 'class' => "attachment-{$size_class} size-{$size_class}", 'alt' => trim(strip_tags(get_post_meta($attachment_id, '_wp_attachment_image_alt', true))));
        // Add `loading` attribute.
        if (wp_lazy_loading_enabled('img', 'wp_get_attachment_image')) {
            $default_attr['loading'] = 'lazy';
        }
        $attr = wp_parse_args($attr, $default_attr);
        // If the default value of `lazy` for the `loading` attribute is overridden
        // to omit the attribute for this image, ensure it is not included.
        if (array_key_exists('loading', $attr) && !$attr['loading']) {
            unset($attr['loading']);
        }
        // Generate 'srcset' and 'sizes' if not already present.
        if (empty($attr['srcset'])) {
            $image_meta = wp_get_attachment_metadata($attachment_id);
            if (is_array($image_meta)) {
                $size_array = array(absint($width), absint($height));
                $srcset = wp_calculate_image_srcset($size_array, $src, $image_meta, $attachment_id);
                $sizes = wp_calculate_image_sizes($size_array, $src, $image_meta, $attachment_id);
                if ($srcset && ($sizes || !empty($attr['sizes']))) {
                    $attr['srcset'] = $srcset;
                    if (empty($attr['sizes'])) {
                        $attr['sizes'] = $sizes;
                    }
                }
            }
        }
        /**
         * Filters the list of attachment image attributes.
         *
         * @since 2.8.0
         *
         * @param array        $attr       Array of attribute values for the image markup, keyed by attribute name.
         *                                 See wp_get_attachment_image().
         * @param WP_Post      $attachment Image attachment post.
         * @param string|array $size       Requested size. Image size or array of width and height values
         *                                 (in that order). Default 'thumbnail'.
         */
        $attr = apply_filters('wp_get_attachment_image_attributes', $attr, $attachment, $size);
        $attr = array_map('esc_attr', $attr);
        $html = rtrim("<img {$hwstring}");
        foreach ($attr as $name => $value) {
            $html .= " {$name}=" . '"' . $value . '"';
        }
        $html .= ' />';
    }
    return $html;
}

WordPress Version: 5.5

/**
 * Get an HTML img element representing an image attachment
 *
 * While `$size` will accept an array, it is better to register a size with
 * add_image_size() so that a cropped version is generated. It's much more
 * efficient than having to find the closest-sized image and then having the
 * browser scale down the image.
 *
 * @since 2.5.0
 *
 * @param int          $attachment_id Image attachment ID.
 * @param string|array $size          Optional. Image size. Accepts any valid image size, or an array of width
 *                                    and height values in pixels (in that order). Default 'thumbnail'.
 * @param bool         $icon          Optional. Whether the image should be treated as an icon. Default false.
 * @param string|array $attr {
 *     Optional. Attributes for the image markup.
 *
 *     @type string $src    Image attachment URL.
 *     @type string $class  CSS class name or space-separated list of classes.
 *                          Default `attachment-$size_class size-$size_class`,
 *                          where `$size_class` is the image size being requested.
 *     @type string $alt    Image description for the alt attribute.
 *     @type string $srcset The 'srcset' attribute value.
 *     @type string $sizes  The 'sizes' attribute value.
 * }
 * @return string HTML img element or empty string on failure.
 */
function wp_get_attachment_image($attachment_id, $size = 'thumbnail', $icon = false, $attr = '')
{
    $html = '';
    $image = wp_get_attachment_image_src($attachment_id, $size, $icon);
    if ($image) {
        list($src, $width, $height) = $image;
        $attachment = get_post($attachment_id);
        $hwstring = image_hwstring($width, $height);
        $size_class = $size;
        if (is_array($size_class)) {
            $size_class = join('x', $size_class);
        }
        $default_attr = array('src' => $src, 'class' => "attachment-{$size_class} size-{$size_class}", 'alt' => trim(strip_tags(get_post_meta($attachment_id, '_wp_attachment_image_alt', true))));
        // Add `loading` attribute.
        if (wp_lazy_loading_enabled('img', 'wp_get_attachment_image')) {
            $default_attr['loading'] = 'lazy';
        }
        $attr = wp_parse_args($attr, $default_attr);
        // If `loading` attribute default of `lazy` is overridden for this
        // image to omit the attribute, ensure it is not included.
        if (array_key_exists('loading', $attr) && !$attr['loading']) {
            unset($attr['loading']);
        }
        // Generate 'srcset' and 'sizes' if not already present.
        if (empty($attr['srcset'])) {
            $image_meta = wp_get_attachment_metadata($attachment_id);
            if (is_array($image_meta)) {
                $size_array = array(absint($width), absint($height));
                $srcset = wp_calculate_image_srcset($size_array, $src, $image_meta, $attachment_id);
                $sizes = wp_calculate_image_sizes($size_array, $src, $image_meta, $attachment_id);
                if ($srcset && ($sizes || !empty($attr['sizes']))) {
                    $attr['srcset'] = $srcset;
                    if (empty($attr['sizes'])) {
                        $attr['sizes'] = $sizes;
                    }
                }
            }
        }
        /**
         * Filters the list of attachment image attributes.
         *
         * @since 2.8.0
         *
         * @param array        $attr       Array of attribute values for the image markup, keyed by attribute name.
         *                                 See wp_get_attachment_image().
         * @param WP_Post      $attachment Image attachment post.
         * @param string|array $size       Requested size. Image size or array of width and height values
         *                                 (in that order). Default 'thumbnail'.
         */
        $attr = apply_filters('wp_get_attachment_image_attributes', $attr, $attachment, $size);
        $attr = array_map('esc_attr', $attr);
        $html = rtrim("<img {$hwstring}");
        foreach ($attr as $name => $value) {
            $html .= " {$name}=" . '"' . $value . '"';
        }
        $html .= ' />';
    }
    return $html;
}

WordPress Version: 5.4

/**
 * Get an HTML img element representing an image attachment
 *
 * While `$size` will accept an array, it is better to register a size with
 * add_image_size() so that a cropped version is generated. It's much more
 * efficient than having to find the closest-sized image and then having the
 * browser scale down the image.
 *
 * @since 2.5.0
 *
 * @param int          $attachment_id Image attachment ID.
 * @param string|array $size          Optional. Image size. Accepts any valid image size, or an array of width
 *                                    and height values in pixels (in that order). Default 'thumbnail'.
 * @param bool         $icon          Optional. Whether the image should be treated as an icon. Default false.
 * @param string|array $attr {
 *     Optional. Attributes for the image markup.
 *
 *     @type string $src    Image attachment URL.
 *     @type string $class  CSS class name or space-separated list of classes.
 *                          Default `attachment-$size_class size-$size_class`,
 *                          where `$size_class` is the image size being requested.
 *     @type string $alt    Image description for the alt attribute.
 *     @type string $srcset The 'srcset' attribute value.
 *     @type string $sizes  The 'sizes' attribute value.
 * }
 * @return string HTML img element or empty string on failure.
 */
function wp_get_attachment_image($attachment_id, $size = 'thumbnail', $icon = false, $attr = '')
{
    $html = '';
    $image = wp_get_attachment_image_src($attachment_id, $size, $icon);
    if ($image) {
        list($src, $width, $height) = $image;
        $hwstring = image_hwstring($width, $height);
        $size_class = $size;
        if (is_array($size_class)) {
            $size_class = join('x', $size_class);
        }
        $attachment = get_post($attachment_id);
        $default_attr = array('src' => $src, 'class' => "attachment-{$size_class} size-{$size_class}", 'alt' => trim(strip_tags(get_post_meta($attachment_id, '_wp_attachment_image_alt', true))));
        $attr = wp_parse_args($attr, $default_attr);
        // Generate 'srcset' and 'sizes' if not already present.
        if (empty($attr['srcset'])) {
            $image_meta = wp_get_attachment_metadata($attachment_id);
            if (is_array($image_meta)) {
                $size_array = array(absint($width), absint($height));
                $srcset = wp_calculate_image_srcset($size_array, $src, $image_meta, $attachment_id);
                $sizes = wp_calculate_image_sizes($size_array, $src, $image_meta, $attachment_id);
                if ($srcset && ($sizes || !empty($attr['sizes']))) {
                    $attr['srcset'] = $srcset;
                    if (empty($attr['sizes'])) {
                        $attr['sizes'] = $sizes;
                    }
                }
            }
        }
        /**
         * Filters the list of attachment image attributes.
         *
         * @since 2.8.0
         *
         * @param string[]     $attr       Array of attribute values for the image markup, keyed by attribute name.
         *                                 See wp_get_attachment_image().
         * @param WP_Post      $attachment Image attachment post.
         * @param string|array $size       Requested size. Image size or array of width and height values
         *                                 (in that order). Default 'thumbnail'.
         */
        $attr = apply_filters('wp_get_attachment_image_attributes', $attr, $attachment, $size);
        $attr = array_map('esc_attr', $attr);
        $html = rtrim("<img {$hwstring}");
        foreach ($attr as $name => $value) {
            $html .= " {$name}=" . '"' . $value . '"';
        }
        $html .= ' />';
    }
    return $html;
}

WordPress Version: 4.7

/**
 * Get an HTML img element representing an image attachment
 *
 * While `$size` will accept an array, it is better to register a size with
 * add_image_size() so that a cropped version is generated. It's much more
 * efficient than having to find the closest-sized image and then having the
 * browser scale down the image.
 *
 * @since 2.5.0
 *
 * @param int          $attachment_id Image attachment ID.
 * @param string|array $size          Optional. Image size. Accepts any valid image size, or an array of width
 *                                    and height values in pixels (in that order). Default 'thumbnail'.
 * @param bool         $icon          Optional. Whether the image should be treated as an icon. Default false.
 * @param string|array $attr          Optional. Attributes for the image markup. Default empty.
 * @return string HTML img element or empty string on failure.
 */
function wp_get_attachment_image($attachment_id, $size = 'thumbnail', $icon = false, $attr = '')
{
    $html = '';
    $image = wp_get_attachment_image_src($attachment_id, $size, $icon);
    if ($image) {
        list($src, $width, $height) = $image;
        $hwstring = image_hwstring($width, $height);
        $size_class = $size;
        if (is_array($size_class)) {
            $size_class = join('x', $size_class);
        }
        $attachment = get_post($attachment_id);
        $default_attr = array('src' => $src, 'class' => "attachment-{$size_class} size-{$size_class}", 'alt' => trim(strip_tags(get_post_meta($attachment_id, '_wp_attachment_image_alt', true))));
        $attr = wp_parse_args($attr, $default_attr);
        // Generate 'srcset' and 'sizes' if not already present.
        if (empty($attr['srcset'])) {
            $image_meta = wp_get_attachment_metadata($attachment_id);
            if (is_array($image_meta)) {
                $size_array = array(absint($width), absint($height));
                $srcset = wp_calculate_image_srcset($size_array, $src, $image_meta, $attachment_id);
                $sizes = wp_calculate_image_sizes($size_array, $src, $image_meta, $attachment_id);
                if ($srcset && ($sizes || !empty($attr['sizes']))) {
                    $attr['srcset'] = $srcset;
                    if (empty($attr['sizes'])) {
                        $attr['sizes'] = $sizes;
                    }
                }
            }
        }
        /**
         * Filters the list of attachment image attributes.
         *
         * @since 2.8.0
         *
         * @param array        $attr       Attributes for the image markup.
         * @param WP_Post      $attachment Image attachment post.
         * @param string|array $size       Requested size. Image size or array of width and height values
         *                                 (in that order). Default 'thumbnail'.
         */
        $attr = apply_filters('wp_get_attachment_image_attributes', $attr, $attachment, $size);
        $attr = array_map('esc_attr', $attr);
        $html = rtrim("<img {$hwstring}");
        foreach ($attr as $name => $value) {
            $html .= " {$name}=" . '"' . $value . '"';
        }
        $html .= ' />';
    }
    return $html;
}

WordPress Version: 4.6

/**
 * Get an HTML img element representing an image attachment
 *
 * While `$size` will accept an array, it is better to register a size with
 * add_image_size() so that a cropped version is generated. It's much more
 * efficient than having to find the closest-sized image and then having the
 * browser scale down the image.
 *
 * @since 2.5.0
 *
 * @param int          $attachment_id Image attachment ID.
 * @param string|array $size          Optional. Image size. Accepts any valid image size, or an array of width
 *                                    and height values in pixels (in that order). Default 'thumbnail'.
 * @param bool         $icon          Optional. Whether the image should be treated as an icon. Default false.
 * @param string|array $attr          Optional. Attributes for the image markup. Default empty.
 * @return string HTML img element or empty string on failure.
 */
function wp_get_attachment_image($attachment_id, $size = 'thumbnail', $icon = false, $attr = '')
{
    $html = '';
    $image = wp_get_attachment_image_src($attachment_id, $size, $icon);
    if ($image) {
        list($src, $width, $height) = $image;
        $hwstring = image_hwstring($width, $height);
        $size_class = $size;
        if (is_array($size_class)) {
            $size_class = join('x', $size_class);
        }
        $attachment = get_post($attachment_id);
        $default_attr = array('src' => $src, 'class' => "attachment-{$size_class} size-{$size_class}", 'alt' => trim(strip_tags(get_post_meta($attachment_id, '_wp_attachment_image_alt', true))));
        if (empty($default_attr['alt'])) {
            $default_attr['alt'] = trim(strip_tags($attachment->post_excerpt));
        }
        // If not, Use the Caption
        if (empty($default_attr['alt'])) {
            $default_attr['alt'] = trim(strip_tags($attachment->post_title));
        }
        // Finally, use the title
        $attr = wp_parse_args($attr, $default_attr);
        // Generate 'srcset' and 'sizes' if not already present.
        if (empty($attr['srcset'])) {
            $image_meta = get_post_meta($attachment_id, '_wp_attachment_metadata', true);
            if (is_array($image_meta)) {
                $size_array = array(absint($width), absint($height));
                $srcset = wp_calculate_image_srcset($size_array, $src, $image_meta, $attachment_id);
                $sizes = wp_calculate_image_sizes($size_array, $src, $image_meta, $attachment_id);
                if ($srcset && ($sizes || !empty($attr['sizes']))) {
                    $attr['srcset'] = $srcset;
                    if (empty($attr['sizes'])) {
                        $attr['sizes'] = $sizes;
                    }
                }
            }
        }
        /**
         * Filters the list of attachment image attributes.
         *
         * @since 2.8.0
         *
         * @param array        $attr       Attributes for the image markup.
         * @param WP_Post      $attachment Image attachment post.
         * @param string|array $size       Requested size. Image size or array of width and height values
         *                                 (in that order). Default 'thumbnail'.
         */
        $attr = apply_filters('wp_get_attachment_image_attributes', $attr, $attachment, $size);
        $attr = array_map('esc_attr', $attr);
        $html = rtrim("<img {$hwstring}");
        foreach ($attr as $name => $value) {
            $html .= " {$name}=" . '"' . $value . '"';
        }
        $html .= ' />';
    }
    return $html;
}

WordPress Version: 4.4

/**
 * Get an HTML img element representing an image attachment
 *
 * While `$size` will accept an array, it is better to register a size with
 * add_image_size() so that a cropped version is generated. It's much more
 * efficient than having to find the closest-sized image and then having the
 * browser scale down the image.
 *
 * @since 2.5.0
 *
 * @param int          $attachment_id Image attachment ID.
 * @param string|array $size          Optional. Image size. Accepts any valid image size, or an array of width
 *                                    and height values in pixels (in that order). Default 'thumbnail'.
 * @param bool         $icon          Optional. Whether the image should be treated as an icon. Default false.
 * @param string|array $attr          Optional. Attributes for the image markup. Default empty.
 * @return string HTML img element or empty string on failure.
 */
function wp_get_attachment_image($attachment_id, $size = 'thumbnail', $icon = false, $attr = '')
{
    $html = '';
    $image = wp_get_attachment_image_src($attachment_id, $size, $icon);
    if ($image) {
        list($src, $width, $height) = $image;
        $hwstring = image_hwstring($width, $height);
        $size_class = $size;
        if (is_array($size_class)) {
            $size_class = join('x', $size_class);
        }
        $attachment = get_post($attachment_id);
        $default_attr = array('src' => $src, 'class' => "attachment-{$size_class} size-{$size_class}", 'alt' => trim(strip_tags(get_post_meta($attachment_id, '_wp_attachment_image_alt', true))));
        if (empty($default_attr['alt'])) {
            $default_attr['alt'] = trim(strip_tags($attachment->post_excerpt));
        }
        // If not, Use the Caption
        if (empty($default_attr['alt'])) {
            $default_attr['alt'] = trim(strip_tags($attachment->post_title));
        }
        // Finally, use the title
        $attr = wp_parse_args($attr, $default_attr);
        // Generate 'srcset' and 'sizes' if not already present.
        if (empty($attr['srcset'])) {
            $image_meta = get_post_meta($attachment_id, '_wp_attachment_metadata', true);
            if (is_array($image_meta)) {
                $size_array = array(absint($width), absint($height));
                $srcset = wp_calculate_image_srcset($size_array, $src, $image_meta, $attachment_id);
                $sizes = wp_calculate_image_sizes($size_array, $src, $image_meta, $attachment_id);
                if ($srcset && ($sizes || !empty($attr['sizes']))) {
                    $attr['srcset'] = $srcset;
                    if (empty($attr['sizes'])) {
                        $attr['sizes'] = $sizes;
                    }
                }
            }
        }
        /**
         * Filter the list of attachment image attributes.
         *
         * @since 2.8.0
         *
         * @param array        $attr       Attributes for the image markup.
         * @param WP_Post      $attachment Image attachment post.
         * @param string|array $size       Requested size. Image size or array of width and height values
         *                                 (in that order). Default 'thumbnail'.
         */
        $attr = apply_filters('wp_get_attachment_image_attributes', $attr, $attachment, $size);
        $attr = array_map('esc_attr', $attr);
        $html = rtrim("<img {$hwstring}");
        foreach ($attr as $name => $value) {
            $html .= " {$name}=" . '"' . $value . '"';
        }
        $html .= ' />';
    }
    return $html;
}

WordPress Version: 4.2

/**
 * Get an HTML img element representing an image attachment
 *
 * While `$size` will accept an array, it is better to register a size with
 * add_image_size() so that a cropped version is generated. It's much more
 * efficient than having to find the closest-sized image and then having the
 * browser scale down the image.
 *
 * @since 2.5.0
 *
 * @param int          $attachment_id Image attachment ID.
 * @param string|array $size          Optional. Registered image size or flat array of height and width
 *                                    dimensions. Default 'thumbnail'.
 * @param bool         $icon          Optional. Whether the image should be treated as an icon. Default false.
 * @param string|array $attr          Optional. Attributes for the image markup. Default empty.
 * @return string HTML img element or empty string on failure.
 */
function wp_get_attachment_image($attachment_id, $size = 'thumbnail', $icon = false, $attr = '')
{
    $html = '';
    $image = wp_get_attachment_image_src($attachment_id, $size, $icon);
    if ($image) {
        list($src, $width, $height) = $image;
        $hwstring = image_hwstring($width, $height);
        $size_class = $size;
        if (is_array($size_class)) {
            $size_class = join('x', $size_class);
        }
        $attachment = get_post($attachment_id);
        $default_attr = array('src' => $src, 'class' => "attachment-{$size_class}", 'alt' => trim(strip_tags(get_post_meta($attachment_id, '_wp_attachment_image_alt', true))));
        if (empty($default_attr['alt'])) {
            $default_attr['alt'] = trim(strip_tags($attachment->post_excerpt));
        }
        // If not, Use the Caption
        if (empty($default_attr['alt'])) {
            $default_attr['alt'] = trim(strip_tags($attachment->post_title));
        }
        // Finally, use the title
        $attr = wp_parse_args($attr, $default_attr);
        /**
         * Filter the list of attachment image attributes.
         *
         * @since 2.8.0
         *
         * @param array        $attr       Attributes for the image markup.
         * @param WP_Post      $attachment Image attachment post.
         * @param string|array $size       Requested size.
         */
        $attr = apply_filters('wp_get_attachment_image_attributes', $attr, $attachment, $size);
        $attr = array_map('esc_attr', $attr);
        $html = rtrim("<img {$hwstring}");
        foreach ($attr as $name => $value) {
            $html .= " {$name}=" . '"' . $value . '"';
        }
        $html .= ' />';
    }
    return $html;
}

WordPress Version: 4.1

/**
 * Get an HTML img element representing an image attachment
 *
 * While $size will accept an array, it is better to register a size with
 * add_image_size() so that a cropped version is generated. It's much more
 * efficient than having to find the closest-sized image and then having the
 * browser scale down the image.
 *
 * @since 2.5.0
 *
 * @see add_image_size()
 *
 * @param int          $attachment_id Image attachment ID.
 * @param string|array $size          Optional. Default 'thumbnail'.
 * @param bool         $icon          Optional. Whether it is an icon. Default false.
 * @param string|array $attr          Optional. Attributes for the image markup. Default empty string.
 * @return string HTML img element or empty string on failure.
 */
function wp_get_attachment_image($attachment_id, $size = 'thumbnail', $icon = false, $attr = '')
{
    $html = '';
    $image = wp_get_attachment_image_src($attachment_id, $size, $icon);
    if ($image) {
        list($src, $width, $height) = $image;
        $hwstring = image_hwstring($width, $height);
        $size_class = $size;
        if (is_array($size_class)) {
            $size_class = join('x', $size_class);
        }
        $attachment = get_post($attachment_id);
        $default_attr = array('src' => $src, 'class' => "attachment-{$size_class}", 'alt' => trim(strip_tags(get_post_meta($attachment_id, '_wp_attachment_image_alt', true))));
        if (empty($default_attr['alt'])) {
            $default_attr['alt'] = trim(strip_tags($attachment->post_excerpt));
        }
        // If not, Use the Caption
        if (empty($default_attr['alt'])) {
            $default_attr['alt'] = trim(strip_tags($attachment->post_title));
        }
        // Finally, use the title
        $attr = wp_parse_args($attr, $default_attr);
        /**
         * Filter the list of attachment image attributes.
         *
         * @since 2.8.0
         *
         * @param array        $attr       Attributes for the image markup.
         * @param WP_Post      $attachment Image attachment post.
         * @param string|array $size       Requested size.
         */
        $attr = apply_filters('wp_get_attachment_image_attributes', $attr, $attachment, $size);
        $attr = array_map('esc_attr', $attr);
        $html = rtrim("<img {$hwstring}");
        foreach ($attr as $name => $value) {
            $html .= " {$name}=" . '"' . $value . '"';
        }
        $html .= ' />';
    }
    return $html;
}

WordPress Version: 3.9

/**
 * Get an HTML img element representing an image attachment
 *
 * While $size will accept an array, it is better to register a size with
 * add_image_size() so that a cropped version is generated. It's much more
 * efficient than having to find the closest-sized image and then having the
 * browser scale down the image.
 *
 * @since 2.5.0
 *
 * @see add_image_size()
 * @uses wp_get_attachment_image_src() Gets attachment file URL and dimensions
 *
 * @param int $attachment_id Image attachment ID.
 * @param string $size Optional, default is 'thumbnail'.
 * @param bool $icon Optional, default is false. Whether it is an icon.
 * @param mixed $attr Optional, attributes for the image markup.
 * @return string HTML img element or empty string on failure.
 */
function wp_get_attachment_image($attachment_id, $size = 'thumbnail', $icon = false, $attr = '')
{
    $html = '';
    $image = wp_get_attachment_image_src($attachment_id, $size, $icon);
    if ($image) {
        list($src, $width, $height) = $image;
        $hwstring = image_hwstring($width, $height);
        if (is_array($size)) {
            $size = join('x', $size);
        }
        $attachment = get_post($attachment_id);
        $default_attr = array('src' => $src, 'class' => "attachment-{$size}", 'alt' => trim(strip_tags(get_post_meta($attachment_id, '_wp_attachment_image_alt', true))));
        if (empty($default_attr['alt'])) {
            $default_attr['alt'] = trim(strip_tags($attachment->post_excerpt));
        }
        // If not, Use the Caption
        if (empty($default_attr['alt'])) {
            $default_attr['alt'] = trim(strip_tags($attachment->post_title));
        }
        // Finally, use the title
        $attr = wp_parse_args($attr, $default_attr);
        /**
         * Filter the list of attachment image attributes.
         *
         * @since 2.8.0
         *
         * @param mixed $attr          Attributes for the image markup.
         * @param int   $attachment_id Image attachment ID.
         */
        $attr = apply_filters('wp_get_attachment_image_attributes', $attr, $attachment);
        $attr = array_map('esc_attr', $attr);
        $html = rtrim("<img {$hwstring}");
        foreach ($attr as $name => $value) {
            $html .= " {$name}=" . '"' . $value . '"';
        }
        $html .= ' />';
    }
    return $html;
}

WordPress Version: 3.7

/**
 * Get an HTML img element representing an image attachment
 *
 * While $size will accept an array, it is better to register a size with
 * add_image_size() so that a cropped version is generated. It's much more
 * efficient than having to find the closest-sized image and then having the
 * browser scale down the image.
 *
 * @see add_image_size()
 * @uses apply_filters() Calls 'wp_get_attachment_image_attributes' hook on attributes array
 * @uses wp_get_attachment_image_src() Gets attachment file URL and dimensions
 * @since 2.5.0
 *
 * @param int $attachment_id Image attachment ID.
 * @param string $size Optional, default is 'thumbnail'.
 * @param bool $icon Optional, default is false. Whether it is an icon.
 * @param mixed $attr Optional, attributes for the image markup.
 * @return string HTML img element or empty string on failure.
 */
function wp_get_attachment_image($attachment_id, $size = 'thumbnail', $icon = false, $attr = '')
{
    $html = '';
    $image = wp_get_attachment_image_src($attachment_id, $size, $icon);
    if ($image) {
        list($src, $width, $height) = $image;
        $hwstring = image_hwstring($width, $height);
        if (is_array($size)) {
            $size = join('x', $size);
        }
        $attachment = get_post($attachment_id);
        $default_attr = array('src' => $src, 'class' => "attachment-{$size}", 'alt' => trim(strip_tags(get_post_meta($attachment_id, '_wp_attachment_image_alt', true))));
        if (empty($default_attr['alt'])) {
            $default_attr['alt'] = trim(strip_tags($attachment->post_excerpt));
        }
        // If not, Use the Caption
        if (empty($default_attr['alt'])) {
            $default_attr['alt'] = trim(strip_tags($attachment->post_title));
        }
        // Finally, use the title
        $attr = wp_parse_args($attr, $default_attr);
        $attr = apply_filters('wp_get_attachment_image_attributes', $attr, $attachment);
        $attr = array_map('esc_attr', $attr);
        $html = rtrim("<img {$hwstring}");
        foreach ($attr as $name => $value) {
            $html .= " {$name}=" . '"' . $value . '"';
        }
        $html .= ' />';
    }
    return $html;
}