Go to main content

Textpattern CMS support forum

You are not logged in. Register | Login | Help

#1 Today 03:42:22

Bloke
Developer
From: Leeds, UK
Registered: 2006-01-29
Posts: 12,110
Website GitHub

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:

  1. Uninstall smd_thumbnail if you’re using it.
  2. 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).
  3. 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.
  4. 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_dir with 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.
  • 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. So if you render a webpage, it’ll show fine but if you subsequently right click a thumbnail image after 30 seconds or so, and 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.


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

Board footer

Powered by FluxBB