Textpattern CMS support forum
You are not logged in. Register | Login | Help
- Topics: Active | Unanswered
Automatic thumbnails for Textpattern
Yes, yes, I know it’s only a week or so to release but this has been bugging me forever and I wanted another big ticket item to give people an incentive to upgrade.
Enter core dynamic thumbnails. Goodbye smd_thumbnail plugin.
Out of the box, there’s no obvious change. Thumbs continue to work as they did. Set default sizes, upload, faff, etc. But that all changes if you do the following:
- Uninstall smd_thumbnail if you’re using it.
- Visit Admin->Prefs [Admin] and ensure the Virtual thumb directory is set to some value that doesn’t clash with a directory on your server (default: txp_thumb).
- Open up any image, scroll down to the Thumbnail area and toggle the Thumbnail Type selector to Automatic (or use the multi-edit tool to do it en masse) and Save. Txp will create a dynamic thumbnail for that image. That just means your admin theme governs how the thumbnail behaves on the back-end.
- Check Admin -> Prefs [Admin theme] to alter the thumbnail dimensions and cropping factor (width x height). Any images you have set to Automatic will have thumbs auto-generated on the admin side so they all look neat. It’s the default on new installs so thumbnails are really fire and forget as far as the admin-side is concerned.
For admin theme designers and plugin authors, this and the new Theme Prefs feature give you the ability to muck about with exposing thumbnail sizing to your theme. There are grid-based plugins out there, and the feature plays nicely with those to make beautiful admin-side images on demand. You can also alter the fallback dimensions by defining TEXTPATTERN_THUMB_WIDTH, TEXTPATTERN_THUMB_HEIGHT and/or TEXTPATTERN_THUMB_CROPPING in your config.php.
But why stop there?
The <txp:thumbnail> (or <txp:image thumbnail> and <txp:image_url thumbnail>) tags can now render any image in any aspect at any size on-the-fly, and cache it for next use. No need to mess with uploading them, or lengthy operations, or jaggy upscales, or pre-defining sizes for every image whether they need that size or not.
If you change your mind and want the thumbnails 10px bigger, just change your tag: your thumbnails will be automatically rescaled (even if their ‘type’ is not Automatic: that’s mainly an admin-side convenience). You can always force your tag to use automatic mode by specifying the thumbnail="2" attribute. (thumbnail="1" retains the existing custom size thumbs behaviour, and thumbnail="0" means ‘no thumb’).
Want to write a dynamic srcset tag for multi-device support? Just do it. Sprinkle your <txp:thumbnail> tags at varying sizes and the images will be automatically created and rendered to the device at those dimensions, and cached. Any images that aren’t used for a length of time will be garbage collected.
You can still choose to override any thumbnail and use your own. If you do that, just be sure not to specify any dimensions in your tag or it’ll trigger the automatic mode (unless you force it with thumbnail="1" then it’ll leave it alone and resize your custom thumbnail, as it does now).
That’s not all.
Since the SLIR library upon which this is based (hat-tip: giz) was rather outdated and abandoned by its author, I’ve taken the opportunity to rewrite chunks of it to Textpatternise it a bit. There’s still more work to go (and a future aim in Txp 5 is to write a companion Imagick class alongside the current GD one so we can do more with images) but the engine underneath now:
- Is as bug-free as I can make it on current PHP versions.
- Is namespaced properly.
- Supports, AVIF and standard WebP, as well as the usual suite of image types.
- Supports SVG and, in fact, Txp no longer makes thumbnails from them. The original vectors are scaled and cached when you call your tags with a
width/height. Same on the admin-side. - Works in subdir installs, and in both clean and messy permlink modes.
- Handles encrypted image generation to avoid abuse by spamming the
thumb_dirwith values.
There are a couple of little caveats:
- Really large images can make the engine spit its dummy out and refuse to render thumbnails. You’ll just get the alt tag shown because it can run out of memory. So don’t upload 20MB super hi-res pics and expect miracles. Or, if you do, whack your php.ini settings up a lot [Edit: giz notes that Images over about 3000px in one dimension tend to cause problems].
- Animated WebP are not supported. That’s a restriction placed upon us by PHP/GD because it can’t render a thumb from them. I’ve coded around it. Maybe when the Imagick class is built, this might become reality. Most animated GIFs and PNGs should be fine, and it’ll render a static representation of those.
- At the moment, EXIF and IPTC information is not processed. The library has the ability to do it, but relies on yet another abandoned library called PEL to do so. That was perhaps a step too far to tackle at this stage in the dev cycle, so I’ve chosen to leave it disabled for now.
On the security front, I’ve taken the step (at great expense to my sanity and remaining few hairs) to encrypt every single dynamic image request. This means that you cannot just spam your /txp_thumb/w400-h400-c1x1/images/NN.jpg path and have it spit an image back. It’ll just give you a white screen. However, if the request comes from a tag (specifically from the new imageBuildURL() function) it generates a token in the database and adds that to the tag on your behalf. Then, when it comes time to fetch the image less than a second later, it looks up the token and, if it exists, will render the image. If the token is mangled or the image path is altered, you get nothing out.
Further, these tokens are very (very) short lived. Default: 30 seconds. These tokens are subject to garbage collection after 2 days. So if you render a webpage, it’ll show fine but if you leave the page alone, come back and right click a thumbnail image after a few days to try to view it or download it, you’ll get a white screen because the token will have expired. You can control the timeout by defining THUMB_VALIDITY_SECONDS in your config.php. If you make it too short, you run the risk of the site not finishing to render the web page before the token expires so you’ll get empty images spat back. You shouldn’t need to mess with that setting, but it’s there if you do.
Thumbnail requests are linked to a browser session, simply because two people requesting the same image at the same time would overwrite one another’s token. So I’ve had to use the session ID to mitigate that. You’ll notice your txp_token table fill up with image_verify entries, but they should be automatically garbage collected after a day or so, to keep the table bloat down. Please report if not.
Yes, validating every image request adds to the processing time, server load, and does delay the rendering of images a fraction. But I didn’t notice any significant slowdowns. I made it as fast as I can and there may be some optimsations still to go. I tweaked SLIR to disregard the token when it looks at the URL, so it will go directly to its cache instead of recreating the thumbnail when it has a different token. That keeps the speed up quite nicely, but it still has to validate the token to check the request came from a tag and not a URL hacking attempt.
If you do have any issues with tokens, you can turn this feature off with a hidden pref but it’s very very ill-advised. I’ve left the door open for maybe a halfway house implementation which, perhaps, validates only the page once with a single token and allows any requests from it for a limited time. That’s semi-secure, but would give the ability for an attacker to open a page, view the source, grab the token and then spam URLs to fill up your disk cache or DDOS your site for however long the token remains valid, so I’m not sure if that’s a good idea.
Anyway, I hope this feels like a natural and helpful addition to core. It’s only a couple of hundred KB of extra code so I thought was well worth it. I hope it can stay in 4.9.0 but if anyone feels it’s not stable enough then it can be ripped out and delayed till Txp 5.
Please please test this and report any issues. And, most of all, have fun.
P.S. the demo server won’t have this thumbnail ability because it can’t write to the images directory, which is where the cache lives.
Last edited by Bloke (2025-12-05 10:29:06)
The smd plugin menagerie — for when you need one more gribble of power from Textpattern. Bleeding-edge code available on GitHub.
Txp Builders – finely-crafted code, design and Txp
Offline
Re: Automatic thumbnails for Textpattern
First set of testing on a basic install without having seen smd_thumbnail. I copied the prefs.json from the Hive theme into Sandspace for ease of testing.
I was a little confused by the use of the character “x” (Latin small letter x) as separator. In modifying the prefs in the Admin, I first used “X” (capital x), which caused nothing to work … After taking a closer look (that onscreen magnifier is so useful), I understood my error. Then all (a very basic test, inserting a <txp:thumbnail id=xxx alt=abcd width=800 height=450 />) started to work.
Q: how do you see a workflow where on the admin side (the default list table) images are displayed at “full view” – that is: small thumb size but no cropping (see the sample images list panel for Sandspace: dev.l-c-n.com/txp-4.9/txp-content-image.html)? That is kinda important for us, my partner’s website has many “graph”-type images, pie chart, bar charts, line charts etc. That full view makes them kinda a little easier to recognise… ‘kinda’ does some work there though. Or see Apple’s Photos.app, the grid allows either square thumbs or full view (⌥T or option-T).
Q. How does that work if a visitor wants to view the image that is displayed on the webpage? The age old right-click on image > view image or other items in that context menu.
Now I need to think of workflows to transition from the use of smd_thumbnails – and the use of its tags in my shortcode blocks, or sometimes a direct <txp:images> <txp:smd_thumbnail type='foo'> </txp:images>. Tips welcome. I suspect smd_where_used will come in handy.
I am sure more question will come up. I do think it is a useful addition.
Where is that emoji for a solar powered submarine when you need it ?
Sand space – admin theme for Textpattern
phiw13 on Codeberg
Offline
Re: Automatic thumbnails for Textpattern
phiw13 wrote #341474:
I was a little confused by the use of the character “x”
What character would you prefer? SLIR uses that verbatim as they expect 9×16 or something. But if you think something else would be better I can convert it from whatever characters are there.
how do you see a workflow where on the admin side (the default list table) images are displayed at “full view” – that is: small thumb size but no cropping
Empty the crop box and they’ll be shown fully at the width you specify.
How does that work if a visitor wants to view the image that is displayed on the webpage?
I wouldn’t envisage most people wanting to right click a thumbnail for a bigger view. Normally it acts as content for an anchor to the full-size images doesn’t it? Or am I missing something?
The smd plugin menagerie — for when you need one more gribble of power from Textpattern. Bleeding-edge code available on GitHub.
Txp Builders – finely-crafted code, design and Txp
Offline
Re: Automatic thumbnails for Textpattern
Bloke wrote #341475:
Empty the crop box and they’ll be shown fully at the width you specify.
Aha, that might work yes.
I wouldn’t envisage most people wanting to right click a thumbnail for a bigger view. Normally it acts as content for an anchor to the full-size images doesn’t it? Or am I missing something?
Image is displayed on a public webpage (e.g fills the article text column). Visitor want to see in more details, copy the image for some type of use,… (this view: dev.l-c-n.com/_b/txp-test.png, I try right-click on the image, “Open image in new tab” in Firefox, result is a blank page).
Where is that emoji for a solar powered submarine when you need it ?
Sand space – admin theme for Textpattern
phiw13 on Codeberg
Offline
Re: Automatic thumbnails for Textpattern
phiw13 wrote #341476:
Aha, that might work yes.
Note to self: mark the crop input as optional.
Image is displayed on a public webpage (e.g fills the article text column). Visitor want to see in more details, copy the image for some type of use
Yes, that’s fine. But if you think people might want to see more detail, why not just use <txp:thumbnail width="400" link /> so they tap to open the full-size pic? Then they can save that instead.
That said, I might see if it’s possible to override the security at the tag level. Maybe secure="0" or something? That way, you can temporarily shut the security off just for that tag without compromising the security of the system overall.
I’ll have a play. Thank you for testing so far.
The smd plugin menagerie — for when you need one more gribble of power from Textpattern. Bleeding-edge code available on GitHub.
Txp Builders – finely-crafted code, design and Txp
Offline
Re: Automatic thumbnails for Textpattern
You did it!! Sorry about those hairs!
But… at the risk of doing them more damage, I do get a problem with the token expiring with that example I sent you of srcsets:
If you supply a srcset and load up your site at a narrow browser width. All is fine so far. Wait a while (e.g. the 30 seconds), then widen the window so that another image in the srcset kicks in. The images no longer load… While my experiment is a bit contrived, it is feasible that people change their browser width or that a layout change on the page caused by a width change causes a different image in a srcset to be loaded. That won’t – unfortunately – have any specific time horizon.
EDIT: the original small sizes also no longer show when sizing back down to the previously loaded size.
What I’ve not tried, but might also be affected, is how it responds to lazy loading when you, say, load a page, then get called away, come back to the screen and scroll down a long list of images that gets loaded lazily. I’m guessing the token may then also be invalid.
Thinking aloud: is the time-limited aspect of it necessary? Would a token per image be sufficient for preventing spamming the url? Each image has its own token, rather than one per page, so post-generating new images from a token scraped from the page shouldn’t work, right?
TXP Builders – finely-crafted code, design and txp
Offline
Re: Automatic thumbnails for Textpattern
Yes, the expiry probably isn’t necessary, but without it, the token table will fill up pretty fast.
That’s a good shout about the srcset situation. I’ve got no problem increasing the default timeout to maybe an hour or two if that makes things better. What sort of time frame do you think makes sense?
[Edit: or even getting rid of the expiry altogether and just allowing the garbage collector to blat entries older than a day next time someone interacts with the site.]
Even if someone views source and steals the token it’s only good for that image at that size on that page load so replays are only possible on the current image, which will just return the cached image.
I also think it’d be trivial to let you specify, say, thumbnail="3" which behaves in exactly the same way as “2” except it doesn’t render or check the token. I don’t think that’s a security hole per se, because (as you say) the fact the thumb_dir is protected by default means only tags can get through anyway.
Should be a cinch to change – about two lines of code – so I’ll give it a whirl later this afternoon. Watch GitHub.
Last edited by Bloke (2025-12-04 13:15:01)
The smd plugin menagerie — for when you need one more gribble of power from Textpattern. Bleeding-edge code available on GitHub.
Txp Builders – finely-crafted code, design and Txp
Offline
Re: Automatic thumbnails for Textpattern
Bloke wrote #341484:
Yes, the expiry probably isn’t necessary, but without it, the token table will fill up pretty fast.
That’s a good shout about the srcset situation. I’ve got no problem increasing the default timeout to maybe an hour or two if that makes things better. What sort of time frame do you think makes sense?
[Edit: or even getting rid of the expiry altogether and just allowing the garbage collector to blat entries older than a day next time someone interacts with the site.]
It’s hard to put a time on it, as it depends on user surfing habits, whether they pause for a lunch break, come back to it tomorrow … and so on. I think the clean-up a day later would be better (effectively a day’s expiry time, then?). Must test that with lazy loading scenario, though. Not sure if that would still mean people coming back to their computer the next day don’t get lazy-load images when they scroll down on an already open page. I haven’t tested properly: I couldn’t provoke it on my local test setup, so maybe I need to set up a proper, more extensive test on a live server.
Even if someone views source and steals the token it’s only good for that image at that size on that page load so replays are only possible on the current image, which will just return the cached image.
Yeah, that is how I understand the security principle.
I also think it’d be trivial to let you specify, say, thumbnail="3" which behaves in exactly the same way as “2” except it doesn’t render or check the token. I don’t think that’s a security hole per se, because (as you say) the fact the thumb_dir is protected by default means only tags can get through anyway.
Not sure I understood that. Why then have the token at all?
But thanks! I like it a lot overall.
TXP Builders – finely-crafted code, design and txp
Offline
Re: Automatic thumbnails for Textpattern
Further to my earlier post: while this doesn’t strictly have to do with the functionality, when an image doesn’t load, my browser doesn’t seem to respect its height and width values, even if explicitly supplied in the markup. When the image doesn’t load, the layout then collapses because the space the image uses is then only as high as the space it needs to show the alt-text.
For anyone trying to follow, I grabbed a bunch of images off unsplash to test with, then under Presentation › Forms made a misc form called gallery with the following code:
<txp:images limit="50" wraptag="div" class="gallery" break="">
<figure>
<img srcset="<txp:image_url thumbnail crop="2x3" width="1200" /> 1200w,
<txp:image_url thumbnail crop="3x3" width="800" /> 800w,
<txp:image_url thumbnail crop="4x3" width="400" /> 400w"
sizes="33vw"
src="<txp:image_url />"
width="<txp:image_info type="w" />"
height="<txp:image_info type="h" />"
loading="lazy"
alt="<txp:image_info type="alt" />">
<txp:image_info type="caption" wraptag="caption" />
</figure>
</txp:images>
and then a stylesheet called gallery under Presentation › Styles with the following:
.gallery {
display: grid;
grid-template-columns: repeat(3, 1fr);
grid-gap: 1.25rem;
font-family: arial;
}
.gallery img {
border-radius: .25rem;
}
.gallery figcaption {
font-style: normal;
font-weight: 600;
color: darkslategrey;
margin-block-start: .75rem;
word-break: break-word;
}
In your page’s head block, insert <txp:css name="gallery" format="link" /> alongside your other styles to load the css.
Finally create an article and place <txp::gallery /> somewhere in your article. Now call up the article in the browser.
The test is simple if a bit contrived in that I make it create thumbnails with different aspect ratios, so you can see when the different srcset images kick in. Call up the page with a narrow browser width, then gradually expand, and the images go from landscape, through square to tall.
TXP Builders – finely-crafted code, design and txp
Offline
Re: Automatic thumbnails for Textpattern
We could ditch the expiry check and just let the table flush itself after a day. If someone leaves their browser open on a page overnight and comes back the next day, well, they may need to refresh the page to generate new tokens. A week seems a bit long, but we could set the garbage collector to kick in and keep a rolling weeks’ worth of tokens if it helps.
As for the tokens themselves, without them, there’s potential for spamming links to generate thumbnails. The check is a two-phase system. First is placing the tag, generating the token and adding it to the URL. The second phase is fetching the image from the URL and resizing it. The presence of a matching token at this stage allows the image delivery to be confident the image came from a trusted source.
But the occasional image that you deliberately let through and don’t check its token is probably okay.
I’ll extend the timeout later. In the meantime, try it out with a longer expiry by overriding THUMB_VALIDITY_SECONDS in config.php and see if things improve.
Last edited by Bloke (2025-12-04 14:09:31)
The smd plugin menagerie — for when you need one more gribble of power from Textpattern. Bleeding-edge code available on GitHub.
Txp Builders – finely-crafted code, design and Txp
Offline
Re: Automatic thumbnails for Textpattern
Bloke wrote #341487:
We could ditch the expiry check and just let the table flush itself after a day. If someone leaves their browser open on a page overnight and comes back the next day, well, they may need to refresh the page to generate new tokens. A week seems a bit long, but we could set the garbage collector to kick in and keep a rolling weeks’ worth of tokens if it helps.
Maybe a couple of days, then? (that was me in full bartering mode 😅) Is there a point where the number of tokens in the table starts to become problematic? Sites with many images or many interim thumbnails will ramp up tokens more quickly than a conventional site with a few images per page and a few srcset sizes.
As for the tokens themselves, without them, there’s potential for spamming links to generate thumbnails. But the odd image that you deliberately let through and don’t check its token is probably okay.
Ah right. That’s what you meant. Not in general but just when needed.
Thanks!
TXP Builders – finely-crafted code, design and txp
Offline
Re: Automatic thumbnails for Textpattern
I doubt the table will fill up. It’s just nice to keep on top of it. I’ll try a few days for the garbage collector, and comment out the expiry checks on the individual image requests. That means your srcset issues go away, and phiw13 can right click and save images for up to 2 days after the page has loaded 😁
I was just being overly cautious, since the token is useless after it’s been validated. But I see the benefit of keeping it around a bit longer.
Last edited by Bloke (2025-12-04 14:18:43)
The smd plugin menagerie — for when you need one more gribble of power from Textpattern. Bleeding-edge code available on GitHub.
Txp Builders – finely-crafted code, design and Txp
Offline