How to include image scaling in the build pipeline

I’m serving a self-hosted website with a blog component using jekyll.

For the blog there’s an overview of articles which includes pictures. After the build, I want those pictures to be the actual size that they’re used on that page. However, I also want them to be able to survive design changes in the future that change the size of the pictures.

I’d like to be able to have high resolution pictures in my sources, then have them resized to the acutal size needed during the build phase. I want there to be a single central point where I can change the resolution these pictures will be converted to.

I don’t exactly know how to properly include this in jekyll’s pipeline. I’m not much use when it comes to Ruby, but willing to learn. I found jekyll-assets, but it seems a bit overwhelming and tough to get into for a ruby beginner.

I was thinking about just including gulp and doing it that way, but it seems a bit unnecessary when I’m confident there should be a way to use the jekyll pipeline for it.

Hi. I have a similar situation to you which I solved.

The idea is to keep large files in version control and then make a copy at say 800px wide without losing the original. And to make say a 200px version easily.

Firstly you want to avoid resizing the images by hand. You can use a shell tool but there’s an easier way to handle this in Jekyll.

Secondly you want to avoid adding the resized images to version control. They have no purpose there. You only need to track changes to the full sized files such as higher contrast. The resized images can be thrown away and recreated at each build. No need for history there

I can recomend using the jekyll-resize plugin.

It works with Jekyll 3 and 4.

This is my fork. The original only works on Jekyll 3.

The plugin is used to reference an image in version control by path and the size you want e.g. 800x800. This won’t make a square but it will set max height and max width at 800px when performing the resize.

Then when you run Jekyll build or sevre, the plugin will resize only the images you told it to and add them to a cache directory. No need to run any shell commands besides Jekyll.

This directory must be ignored from version control but persisted in the build so your HTML page can request it.

The plugin also generates a link to the resized image for you, for use in img tag.

All the instructions are in the docs. :slight_smile: There’s a demo I linked there which you can see on Netlify or you can clone locally to see how the tag is used and works.

If you want you can see the Jekyll image tag plugin which I linked in the doc. That serves the same purpose but has features you and configuration you may not needed. It is more widely used.

1 Like

Oh wow, that looks like exactly what I need. Thank you, that’s amazing!

I’m running Jekyll 3.8.5 so the original should be fine. Unless you added some more features?

Edit: Nevermind, the original seems dead and yours actually has some documentation on it, so I’d rather use that. Thanks for that.

2 Likes

Edit: I found the issue looking at your source code.
The problem is that I had the code below in a loop, but hadn’t yet provided the preview.jpeg for every element in the loop. So your plugin would encounter a file path where the file does not exist. Your plugin decides, this is a severe error and raises exception stopping the build process. So I had to provide a dummy preview picture for all other elements in the loop to get it working.

It does not get to actually display the warning it’s supposed to:

raise "#{source_[path]} is not readable" unless File.readable?(source_path)

because the variable source_ apparently does not exist.

You might want to consider to just out put a red warning in the log instead of stopping to build altogether. Other than that, great work, thanks!

Original:
Hey, I tried your plugin, but I’m getting an error that might be just me not knowing the right syntax or an actual bug. Here’s what happens:

This is the code I use to show the preview thumbnails:

        {% assign postDir = post.date | date: "%Y-%m-%d-" | append: post.slug %}
        {% assign imgPath = "assets/images/posts/" | append: postDir | append: "/preview.jpeg" %}
        <div class="image" style="background-image: url({{imgPath | resize: "800x800"}})">
        </div>

This causes build error:

Liquid Exception: undefined local variable or method `source_' for #<#<Class:0x00000000074501d0>:0x00000000093e7f70> Did you mean? source in E:/Repos/my_page/_pages/blog.html
             Error: undefined local variable or method `source_' for #<#<Class:0x00000000074501d0>:0x00000000093e7f70> Did you mean? source
             Error: Run jekyll build --trace for more information.

However, without the filter it works fine and the image is displayed:

        {% assign postDir = post.date | date: "%Y-%m-%d-" | append: post.slug %}
        {% assign imgPath = "assets/images/posts/" | append: postDir | append: "/preview.jpeg" %}
        <div class="image" style="background-image: url({{imgPath}})">
        </div>

And when I just hardcode the string it works as well and the actual downscaled image is displayed:

        {% assign postDir = post.date | date: "%Y-%m-%d-" | append: post.slug %}
        {% assign imgPath = "assets/images/posts/" | append: postDir | append: "/preview.jpeg" %}
        <div class="image" style="background-image: url({{"/assets/images/posts/2020-06-23-my-post/preview.jpeg" | resize: "800x800"}})">
        </div>

I think the behavior is correct. If you deleted or renamed an image and your Jekyll code points to a bad path, you want to know at build time. You don’t want to know only when browsing the site after its deployed because the warning message appear in the CI logs which you never looked at because it threw no error.

Before I look at my plugin, can you confirm that you are indeed sending a non empty string to it?

Add inspect here and tell me what you see.

{% assign imgPath = "assets/images/posts/" | append: postDir | append: "/preview.jpeg" %}
{{ imgPath | inspect }}

You did say that the image displays fine within resize. But would still be good to see.

That was the part you had before this

<div class="image" style="background-image: url({{ imgPath | resize: '800x800' }})">
        </div>

Would also recommend single quotes as above just in case.

Oh this is a syntax error in the plugin, inherited from the original.

source_[path]

I’ve fixed that now.

Do an upgrade for latest on master and tell me what you see logged. It will tell us the path it sees.

The issue might be that your path needs a leading forwardslash.

{% assign imgPath =  "/assets/images/posts/...

Okay, I updated it. It shows the correct error now. I think everything works really well now. And you’re probaly right, I want to know about the missing file during build. Thanks for your help!

1 Like