The remaining ImageMagick-based commands
With release 1.8, most of the image commands in the bot have been ported over from ImageMagick/Magick++ to the libvips library. While this has already resulted in a significant performance increase with image processing (and the bot in general), not all commands have been ported, either due to confusion regarding how they would be implemented or because of bugs in libvips.
This issue is here to track those unported commands and the current status of porting them. The goal is to completely remove ImageMagick as a dependency from the bot, and as such none of the ports should use it in any way. Help with porting these over is greatly appreciated.
Commands
- [x] circle (radial/rotational blur effect, unsuccessful attempts have been made using mapim function)
- [x] explode (working prototype using static mapim image, would be better to generate it on-the-fly)
- [ ] magik (probably doable with liblqr [the same library that ImageMagick uses], though performance is a concern; maybe worth looking into porting https://github.com/li-plus/seam-carving)
- [x] scott (slightly working prototype using static mapim image, would be better to generate it on-the-fly, antialiasing issues)
- [x] spin (libvips has a rotate command, however it works much differently and I haven't figured out how to make it use the middle of the image as a center point/axle yet)
- [x] swirl (tried using mapim and various polar coordinate functions, unsuccessful so far)
- [x] tile (easy to port, attempted removal but kept due to popular demand)
- [x] wall (need to generate perspective transform and use mapim with it, attempted removal but kept due to popular demand)
Here is a (messy) tarball of what I have so far with explode, spin, and swirl: https://cdn.discordapp.com/attachments/523946539505156128/991436149694398474/vipsproto.tar.zst
Hello, I could have a stab at one of these if you could post sample before-after images of the desired effect, or point me at the imagemagick command line that you are trying to replicate.
what's wrong with the tile command? was it hard to maintain or just worked poorly? was it useless or deprecated?
Hello, I could have a stab at one of these if you could post sample before-after images of the desired effect, or point me at the imagemagick command line that you are trying to replicate.
@jcupitt Oh nice, thanks for stopping by! Spin, scott, and swirl (sources linked) seem to be the toughest ones at the moment. Here's an example input image:

Here are some example outputs for spin, scott, and swirl (images linked by command name). Feel free to pick which one to go after.
what's wrong with the tile command? was it hard to maintain or just worked poorly? was it useless or deprecated?
@BlueBlueTeam Mostly a mix between the slash command limit and lack of usage compared to the other commands. Might still consider keeping it.
I had a stab at swirl in python (should be easy to adapt to C++):
#!/usr/bin/python3
import math
import sys
import pyvips
original = pyvips.Image.new_from_file(sys.argv[1])
# stretch the image out so we have lots of spare edge pixels
image = original.gravity("centre",
original.width * 3,
original.height * 3,
extend="copy")
# this makes an image where pixel (0, 0) (at the top-left) has value [0, 0],
# and pixel (image.width, image.height) at the bottom-right has value
# [image.width, image.height]
index = pyvips.Image.xyz(image.width, image.height)
# move the origin to the centre, negative values up and left,
# positive down and right
centre = index - [image.width / 2, image.height / 2]
# to polar space, so each pixel is now distance and angle in degrees from the
# centre
polar = centre.polar()
# swap distance around so we have 1 in the centre and 0 at the edges of the
# original image size ... square, so we have a gentler twist at the edge
size = min(original.width, original.height) / 2
d = (1 - polar[0] / size) ** 2
# add to a so we swirl by 180 degrees in the centre and 0 at the edges
a = polar[1] + d * 180
# and back to rectangular coordinates again to make a set of vectors we can
# apply to the original image
distort = polar[0].bandjoin(a).rect() + [image.width / 2, image.height / 2]
# distort the image
interp = pyvips.Interpolate.new("bicubic")
distorted = image.mapim(distort, interpolate=interp)
# crop out the original again
image = distorted.crop(original.width,
original.height,
original.width,
original.height)
image.write_to_file(sys.argv[2])
With:
$ ./swirl2.py ~/pics/test.jpg x.jpg
I get:

Not an exact match for your sample output, but maybe close enough?
Apologies for the long wait, but yeah, that should work! I've finally went ahead and ported the Python code and committed it here: a2493bcc0ab6d9925ce7a104c29d98c5cbb8195c
Thank you so much once again for helping out, libvips is great! :D
The scott command has been ported over with a77dc5a, that's one more off the list.
The explode command is done! d236179
The tile command is done. 5c17eca