Understanding image_url options

Short description of issue

I’m looking for more detailed information on how the image_url filter applies width/height/crop options.

Reproduction steps

If I have some liquid like this:

image_url: width: 2048, height: 2048

The docs say this defaults to crop: 'center' behavior, where crop is for “which part of the image to show if the specified dimensions result in an aspect ratio that differs from the original.” The URL it produces seems to match that, since it looks like ...jpg?crop=center&height=2048&width=2048....

But the image itself doesn’t seem to reflect this. My images are 3:2 aspect ratio and much larger than 2048x2048, so I would think this would mean the image would come back as 2048x2048 and cropped. But what I actually get from those URLs is 1365x2048, so, they’re fit into a 2048x2048 bounding box with no cropping applied wait, no, it’s giving me 1000x1500, apparently.

Additional info

As it turns out, the aspect ratio behavior I see is what I want, since it matches the behavior I have from my use of the old img_url filter I’m migrating away from. But… isn’t it supposed to be cropped? Or am I reading the docs wrong? And how are these output dimensions determined? I want to make sure I have a handle on how this “new” filter works.

What type of topic is this

General discussion

I think I see what my issue is. I wasn’t paying enough attention to the test images I was working with, and I was maxing out the actual dimensions of the original data. The docs also say, “Regardless of the specified dimensions, an image can never be resized to be larger than its original dimensions,” and that matches what I’m seeing. If I test with a variety of smaller sizes with image_url it does the cropping just as described, up until it hits a size where one dimension would be larger than the original and then it leaves the aspect ratio as-is.

Testing a bit more, I realize this means I still don’t know how to get the same behavior from image_url I’ve been getting with img_url, though. Previously the width and height specified a bounding box and the output image kept its aspect ratio to fit within that box. But now it’s always cropping.

So for example, with a 1200x920 original image, img_url: '100x100' would actually give me a 100x77 jpeg, but image_url: width: 100, height: 100 gives me a 100x100 jpeg with center cropping. I could specify just one dimension or the other, but whether the remaining dimension ends up bigger or smaller would then depend on whether the original image is landscape or portrait, so it’s not quite the same. Can I still get the old bounding box behavior somehow?

In terms of Liquid used and the resulting image URLs:

img_url: '100x100':                 .../file_100x100.jpg
image_url: width: 100:              .../file.jpg?width=100
image_url: height: 100:             .../filejpg?height=100
image_url: width: 100, height: 100: .../file.jpg?crop=center&height=100&width=100

Looking at all that, I realized I can manually try this:

.../file.jpg?height=100&width=100

…and that does give me a 100x77 px jpeg like the old deprecated filter does. I just don’t know how to get image_url to produce that output.

Hi,

Have you tried specifying the width only so the height is automatically calculated based on the image’s dimensions?

Yep! But that lets the height grow larger than the width (or smaller, whatever the case may be) rather than constraining both dimensions like the URL from img_url can. The key difference to me is that if you give both width and height, the old filter constrains in a bounding box and keeps the original aspect ratio, where the new filter crops and enforces a new aspect ratio.

I realized I can put all of this in a couple concise code blocks to show what I mean and round out what I gave earlier. Stripping out the full path and the v= part for simplicity, these liquid filter calls give URLs like these:

    Liquid                              URL
    img_url: 100x                       file_100x.jpg
    img_url: x100                       file_x100.jpg
    img_url: 100x100                    file_100x100.jpg
    image_url: width: 100               file.jpg?width=100
    image_url: height: 100              file.jpg?height=100
    image_url: width: 100, height: 100  file.jpg?crop=center&height=100&width=100

The actual image dimensions those URLs give you depend on the aspect ratio of the image, but for an example landscape image it gives:

img_url: 100x                       100x77
img_url: x100                       130x100
img_url: 100x100                    100x77
image_url: width: 100               100x77
image_url: height: 100              130x100
image_url: width: 100, height: 100  100x100   ✗ cropped at 1:1

But if I manually remove crop=center in that URL, it works:

(image_url URL but no crop=center)  100x77    ✓ what I want

So the problem for me is, I can’t seem to get the deprecated img_url tag’s behavior that can constrain the image within a specified width and height without cropping. And again, the reason I can’t just leave the height unspecified is that it would let a portrait image be taller than I want.

To make a long story short, I want to make image_url give me a URL that looks like this:

.../file.jpg?height=100&width=100

…but I can’t see how.

I find that when I remove crop=center from the URL, the result is the same as if I didn’t specify height:

Is there maybe some styles in your theme that is resulting in a different result?

1 Like

Thanks for delving into this on your end! I think we’re seeing and describing the same thing. What you get in the lower left image after first manually editing the URL is just the output I want to see from image_url, but none of the filter options seem to allow that (there’s nothing like crop: 'none' or something). Manually fiddling with the URL like we’re doing is as far as I’ve been able to get.

And then when you take away the height option for image_url, it does infer the height as 67px (so far so good) but it would have been larger than 100px for an image with a portrait aspect ratio… so there’s no way to keep the output within a 100x100 box for any given image, it seems, like the old img_url can do.

The reason I’m even harping on this so much is that I’m trying to drag a lot of old theme code into modern Liquid usage, and I was aiming to just migrate img_url to image_url as one step and leave more overhaul of my styling and image handling as another step. But if the new filter doesn’t have all the same functionality (I’m guessing?) I might just have to rework a bigger chunk of the code in one go. Whatever the case, thanks for your help.

1 Like

Oh I see what you mean now!
You want a single filter to work across both portrait and landscape images.

At the moment you would need:
image_url: width: 100 for landscape images
image_url: height: 100 for portrait images

Where previously you just simply used:
img_url: '100x100' for landscape and portrait images

Is that right?

Agree that you’re looking at reworking a chunk of your styles to achieve that effect.

Yep, that’s right! Is there any way to get that behavior with image_url? (If not, oh well, I’ll just take that into account when reworking the theme.)

I looked into it but wasn’t able to find a way to get that behavior anymore. You may have to take it into account when reworking the theme.

From what I’ve seen, many developers work around these kind of limitations by defining recommended image sizes and ratios.

Thanks for looking through all this! I think I’m clear on how things work now, so I can work with this while updating my theme.

1 Like