Skip to content

Conversation

@jjgrainger
Copy link
Contributor

@jjgrainger jjgrainger commented Apr 17, 2022

Summary

Fixes #292

Relevant technical choices

  • Refines logic to select the smaller image file, regardless of mime type, when the webp_uploads_prefer_smaller_image_file filter is enabled.

Checklist

  • PR has either [Focus] or Infrastructure label.
  • PR has a [Type] label.
  • PR has a milestone or the no milestone label.

@jjgrainger jjgrainger added [Type] Enhancement A suggestion for improvement of an existing feature [Focus] Images no milestone PRs that do not have a defined milestone for release labels Apr 17, 2022
@jjgrainger jjgrainger requested a review from felixarntz April 17, 2022 18:13
Copy link
Member

@felixarntz felixarntz left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@jjgrainger Mostly looks good, it needs a few small refinements. Most importantly though, I think we should remove the function previously introduced since it's not really helpful or accurate anyway. The new approach here works good just by itself.

@jjgrainger jjgrainger force-pushed the feature/292-select-smaller-image-size branch from 8a72560 to a2719bb Compare April 25, 2022 12:46
Copy link
Member

@felixarntz felixarntz left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@jjgrainger This looks close, two follow-up comments though. One is actually critical, the PR currently doesn't cover the full sized image yet.

Last but not least, can you also add tests for the new logic?

Copy link
Member

@mitogh mitogh left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Besides the comment from @felixarntz this looks good to me @jjgrainger

Thanks.

@jjgrainger jjgrainger requested review from felixarntz and mitogh April 27, 2022 12:59
Copy link
Member

@felixarntz felixarntz left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@jjgrainger Production logic now looks good to me, just one nit-pick on the filter and a potential issue with the test.

Comment on lines 583 to 592
// File produces larger webp image, original jpg is smaller.
$attachment_id = $this->factory->attachment->create_upload_object( TESTS_PLUGIN_DIR . '/tests/testdata/modules/images/leafs.jpg' );
$metadata = wp_get_attachment_metadata( $attachment_id );
$tag = wp_get_attachment_image( $attachment_id, 'full', false, array( 'class' => "wp-image-{$attachment_id}" ) );
$updated_tag = webp_uploads_img_tag_update_mime_type( $tag, 'the_content', $attachment_id );

$mime_types = webp_uploads_get_mime_types_by_filesize( array( 'image/jpeg', 'image/webp' ), $attachment_id, 'the_content' );
// The full size WebP is smaller.
$expected_tag = str_replace( $metadata['sources']['image/jpeg']['file'], $metadata['sources']['image/webp']['file'], $tag );

$this->assertIsArray( $mime_types );
$this->assertNotContains( 'image/invalid', $mime_types );
$this->assertSame( array( 'image/jpeg', 'image/webp' ), $mime_types );
$this->assertSame( $expected_tag, $updated_tag );
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this test in fact doing what the comment above says? It says this test covers the case where JPEG is smaller than WebP, but then for the $expected_tag it replaces the JPEG version with WebP, so that seems not right. If the JPEG version is smaller, the test should expect that the JPEG version is still used even though a WebP version exists.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @felixarntz

I've updated the comments to make things clearer and reviewed the logic and can confirm it is correct. This image produces a smaller WebP file size of the full image. All sub sizes have a smaller JPG.

I've taken an example of the image code when the webp_uploads_prefer_smaller_image_file filter is set to true here:

<img loading="lazy" width="1080" height="720" src="http://localhost:8888/wp-content/uploads/2022/04/leafs.webp" alt="" class="wp-image-15" srcset="http://localhost:8888/wp-content/uploads/2022/04/leafs.webp 1080w, http://localhost:8888/wp-content/uploads/2022/04/leafs-300x200.jpg 300w, http://localhost:8888/wp-content/uploads/2022/04/leafs-1024x683.jpg 1024w, http://localhost:8888/wp-content/uploads/2022/04/leafs-768x512.jpg 768w" sizes="(max-width: 1080px) 100vw, 1080px">

From the srcset you can see all sub sizes use the JPG version as they are smaller than their WebP version.

The replace updates the original image tag, which uses only JPG, to replace the full size with the WebP version in order to match the output of webp_uploads_img_tag_update_mime_type when the webp_uploads_prefer_smaller_image_file is set to true.

I've also created a shorthand version of the metadata array to compare filesizes and this is correct.

Array
(
    [file] => 2022/04/leafs.jpg
    [full] => Array
        (
            [image/jpeg] => 336884
            [image/webp] => 328322
        )

    [medium] => Array
        (
            [image/jpeg] => 19820
            [image/webp] => 22332
        )

    [large] => Array
        (
            [image/jpeg] => 237115
            [image/webp] => 257974
        )

    [thumbnail] => Array
        (
            [image/jpeg] => 8082
            [image/webp] => 9008
        )

    [medium_large] => Array
        (
            [image/jpeg] => 135786
            [image/webp] => 153226
        )
)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, thanks for clarifying. That makes sense, in that case indeed the updated comments look better.

Copy link
Member

@felixarntz felixarntz left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great work @jjgrainger

@felixarntz
Copy link
Member

@adamsilverstein @mitogh Can one of you please review this as well so we can get it merged?

Copy link
Member

@adamsilverstein adamsilverstein left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Change looks good to me (although I think webp_uploads_prefer_smaller_image_file could start true here), I'll work on adding something similar to the core patch.

if ( apply_filters( 'webp_uploads_prefer_smaller_image_file', false ) ) {
$target_mimes = webp_uploads_get_mime_types_by_filesize( $target_mimes, $attachment_id );
}
$prefer_smaller_image_file = apply_filters( 'webp_uploads_prefer_smaller_image_file', false );
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

working on adding to core patch so this could be true

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@adamsilverstein Not sure we should add this to the initial core patch as it feels like an extra enhancement. The main patch has a ton of code already and this enhancement could easily be separate.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, I'll add it as a separate patch

if (
$prefer_smaller_image_file &&
! empty( $metadata['sources'][ $target_mime ]['filesize'] ) &&
! empty( $metadata['sources'][ $original_mime ]['filesize'] ) &&
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looking at this part I realized that there could potentially be several mime types in the sources array (eg. JPEG, WebP, AVIF), we should probably check all of them for the smallest size, rather than just the original and the mapped type.

What do you think @felixarntz ? Fine to address in a follow up so we can get this merged since it covers our primary use case as is.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@adamsilverstein That's a good point, I think eventually that would make sense. It would require a bit more complex reworking though indeed, for example right now we only have a single $target_mime, and then there will need to be a list, all of which we would need to go through.

+1 to doing it in a separate issue.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm taking the "look thru every mime type for the smallest" approach for the (follow up) core patch, basically go thru all sources to find the smallest and use that:

foreach( $metadata['sources'] as $source ) {
		if ( empty( $source['filesize'] ) ) {
			continue;
		}
		if ( $source['filesize'] < $target_file['filesize'] ) {
			$target_file = $source;
		}
	}

@felixarntz felixarntz merged commit 90ec7bf into trunk May 3, 2022
@felixarntz felixarntz deleted the feature/292-select-smaller-image-size branch May 3, 2022 22:45
@felixarntz felixarntz changed the title add logic to select smaller image size when enabled Refine logic to select smaller image file in the frontend based on webp_uploads_prefer_smaller_image_file filter May 3, 2022
@felixarntz felixarntz added this to the 1.1.0 milestone May 3, 2022
@felixarntz felixarntz removed the no milestone PRs that do not have a defined milestone for release label May 3, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

[Type] Enhancement A suggestion for improvement of an existing feature

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Refine logic to select smaller image size

5 participants