How to create a custom thumb driver for additional image transformations

Hi there,
i would like to be able to create additional tumbnails with image magick, that transform the images to halftone images, as described here:
http://www.imagemagick.org/Usage/quantize/#halftone

As far as i understood here: https://getkirby.com/docs/reference/plugins/components/thumb
i can extend the thumb drivers functionality.

However, i have not the slightest idea, how i would start from there. How could i implement the option to extend the image filters from grayscale and such to this:
convert source-image.jpg -colorspace Gray -ordered-dither result-image.jpg
?

Any help would be much appreciated.

Also, please note that i would like to keep the original thumb drivers functionality and just simply add the halftone option…

Take a look at the excellent focus crop plugin. It contains a thumbs driver that extends the built in driver to add new functionality. It should give you a big hint…

Thanks James, i’ll try to figure out how this works…

i created one as well but its a bit complex under the hood. you might still get some inspiration from it: https://github.com/bnomei/kirby3-thumb-imageoptim

Hey, I’m trying to solve something like that as well. Did you do it, any hints?

hey jakob, so far, this is out of my league, so i will tackle this hopefully in the future, but right now i wouldn’t even know how to start… have you been making progress with this?

I need it for a side project and did not get back to it yet. I’m more into simple frontend stuff so it’s kind of hard for me to dive in as well. But I’ll give it a try and gonna inform you!

Ok, so we meet on the same level here. Lets just agree on this: the first to tackle this has to post it here, ok? :slight_smile:

Deal!

I made a proof-of-concept plugin, available here:

In principle, it is not that complex. As was mentioned above, we extend the built-in ImageMagick driver with an additional function, we then also need to overwrite the original’s process() function and that’s basically it.

However, my code doesn’t play nice with all of the “thumb” component yet, so maybe there are Kirby wizards who can point me in the right direction.

When I call the plugin’s file method on an image, everything works as expected:

$image->halftone()
$image->dither()

However, for example when I try to define a srcset preset in the config.php, the new dither or halftone option is ignored unless I also set, e.g. 'grayscale' => true or 'quality' => 99:

// doesn't work
'thumbs' => [
  'srcsets' => [
    'test' => [
        '300w' => ['width' => 300, 'dither' => true],
      	'500w' => ['width' => 500, 'dither' => true ],
      ]
  ]
]

// works
'thumbs' => [
  'srcsets' => [
    'test' => [
        '300w' => ['width' => 300, 'quality' => 99, 'dither' => true],
      	'500w' => ['width' => 500, 'grayscale' => true, 'dither' => true ],
      ]
  ]
]

I welcome contributions to the repo or help here if someone has got a spontaneous idea. I am planning to turn this into a more full-featured plugin once these basic issues are sorted out. Thx!

Just a guess. But it seems like the filename for dithered images would be the same as for not dithered versions.
This would make testing your extension very tedious, maybe the dither isn’t applied sometimes because a normal version already exists and Kirby can’t tell them apart?

The filename stuff seems to be buried deep down here: kirby/Filename.php at 3e5899b628a2b59c1833a8d79eda292a7fe06843 · getkirby/kirby · GitHub
Don’t know if you can change that. Maybe with the “file url” or “file version” components? I’ve never understood those parts.

Thanks for your reply!

In my testing, I made sure to always clear out the media folder completely, caching and uuids are disabled.

Now, let’s say I definded this srcset:

'srcsets' => [
  'test' => [
    '300w' => ['width' => 300, 'dither' => true],
    '500w' => ['width' => 500, 'dither' => true ],
  ]
]

I then trigger a force render of all thumbs and can see two thumbnails being created. They have the correct widths, and they are correctly read by the frontend.

It is just that the dither option somehow isn’t passed through (I logged the $options array in the function that executes the actual convert command. dither is missing from the array.)

Now I create this srcset. The only difference is, that I set qualityto 99:

'srcsets' => [
  'test' => [
    '300w' => ['width' => 300, 'dither' => true, 'quality' => 99], 
    '500w' => ['width' => 500, 'dither' => true, 'quality' => 99],
  ]
]

In this scenario, the dither option is passed, ImageMagick gets the right command, and the thumb is correctly written to /media. It’s also consumed by the frontend correctly. This also works when I pass 'grayscale' => true.

So tl;dr: I’m not sure it has something to do with the filename, since even on an empty media folder, and only in some scenarios, the ditheroption is not passed.