Skip to content

Select the smaller image size from the list of available sources #186

Closed

Description

@mitogh

Context

Every image metadata would contain a sources property for every single size available. The property is an associative array where each key on the array represents a mime type and each value on the array would be an associative array with 2 properties on it, the file and filesize of each mime type. For instance, this would like the following data for the medium size

// slice of a metadata from an image  stored in `_wp_attachment_metadata`
array(
  // ...additional image sizes
  'medium'  => array (
    'file' => '7rMFIAVGlVg-240x300.jpeg'
    'width' => 240,
    'height' => 300,
    'mime-type' => 'image/jpeg',
    'sources' => array(
      'image/jpeg' => array(
        'file' => '7rMFIAVGlVg-240x300.jpeg',
        'filesize' => 3831,
      ),
      'image/webp' => array(
        'file' => '7rMFIAVGlVg-240x300.webp',
        'filesize' => 2016
      )
    ),
  )
/// ...additional image sizes
)

The size of each image is expressed in bytes as returned by the filesize function.

Feature Description

Based on the work from:

And considering the scenario where multiple mime-types coexists for the same image, load the image with the smaller size instead of a specific format. As there might be a case where a specific image compresses better in JPEG than WebP (or if another format is available like AVIF in those cases make sure that the image that is delivered to the client is the image with the smaller file size instead of defined image size.

Logic to deliver an image to the client

  • If sources are available
  • order sources by filesize
  • deliver the first one in the list if is supported otherwise move to the next one on the list until a supported format is found.
  • otherwise deliver the former image for the specified size.

Activity

  1. added
    Needs DevAnything that requires development (e.g. a pull request)
    on Feb 28, 2022
  2. removed
    Needs DevAnything that requires development (e.g. a pull request)
    on Mar 1, 2022
  3. mitogh commented on Mar 2, 2022

    @mitogh
    MemberAuthor

    Background

    The information can be found on the metadata of an image using wp_get_attachment_metadata or directly reading the meta key _wp_attachment_metadata.

    All image sizes contain a new property, named sources, this property is an array where each key on the array represents a mime for the image created for that particular size and mime. Each mime is stored as an array with 2 keys:

    • file
    • filesize

    For the full image size the property can be found at the root level of the metadata of the file:

    See:

    Suggested approach

    Currently, the approach is to simply render if available a WebP image, (see #187 for more details), however, the intended approach with this ticket is to ensure the smaller image size is delivered regardless of the mime type. Having a general approach to deliver the smaller image size regardless of the mime type gives room for growth as the logic would ensure only the smaller image size is delivered to the client (the browser). So in the case where a new mime type is added as part of the supported mime types or in the event where a JPEG is smaller in size than a WebP then that file would be served.

    Note: One important note when comparing the images is to ensure that images, where the file size does not exist or is set to zero, due zero, is the default values when the file size can't be determined is skipped from the comparison, in that situation a logic should be added in order to either skip into a format with a file size available or if no other size available use this file as the last resource. As if we compare any filesize to zero as a number the smaller always would be a file where the filesize was not set.

    When rendering an image size, order the images from the smallest file size to the highest one, considering the use case when a filesize has a zero or not set value in that instance:

    1. Consider the 0 as PHP_INT_MAX
    2. Return the first items on the mime types, given that the order was done in an ascending ordering in filesize.

    This logic should be added in place only when rendering the content and replacing the images see:

  4. felixarntz commented on Mar 2, 2022

    @felixarntz
    Member

    @mitogh Overall your suggestion from above sounds reasonable to me. Since this indeed ties in deeply with #187 though, we should first make a decision on that one as well before proceeding with a PR.

    I just suggested an alternative filter in #187 (comment) which focuses on the valid image formats for the frontend rather than just enforcing a single one. That would allow developers to choose one or more formats they are okay with using in the frontend, and then the logic proposed above could decide which one to actually use.

  5. mxbclang commented on Mar 16, 2022

    @mxbclang
    Contributor

    @jjgrainger Noting per our discussion that this is ready to move ahead with engineering; let @felixarntz and @mitogh know if you have any questions on approach. Thanks!

  6. felixarntz commented on Apr 8, 2022

    @felixarntz
    Member

    @jjgrainger @mitogh I have a potential concern with the implementation there. It feels like a neat idea to use the existing filter, but the problem with that is that it now universally prefers one MIME type over the other per attachment, which may not be the best solution. Let me clarify:

    • The current implementation only looks at the full image and decides based on that which MIME type should be preferred.
    • But what if e.g. for most image sizes (including full) the WebP image is smaller, but for e.g. thumbnail the JPEG image is smaller? The current implementation would still always use WebP in that scenario, but it would be better to use JPEG for the thumbnail size.
    • So I'm thinking maybe we need to enhance this to more deeply integrate into the replacement logic, per image size, rather than the overall MIME types filter.

    Let me know what you think about that, if you agree, let's open a follow-up issue for this enhancement.

    Regardless of that though, I think we should make this feature opt-in. Not because it's experimental or anything, but simply because it's not part of the core implementation, so it's somewhat an additional thing. The WP core implementation proposal as of now doesn't include storing and using the file sizes, so as long as that's the case I think this behavior in the plugin should be opt-in. I've opened #286 for that, with PR #287 ready for review.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions