G'MIC 2.9.9: Specialization of `+custom_command`

A few words about a new feature I’ve implemented for G’MIC 2.9.9 :
It will be possible to write a +-specialization of a custom command, in case it is invoked with the +command syntax (preprended +).

In which case it is useful ? Not so often to be honest, but in certain occasions it may be more efficient, by saving memory usage and avoiding unnecessary image copies.
Here is one example to illustrate this fact.

Suppose we want to rewrite the mse command as a custom command. The mse command computes the mean-squared error between several images, and replaces the N input images as a NxN (symetric) matrix containing the MSE between all possible pairs of images.

One way to write it would be:

my_mse : 
  $!,$!,1,1,">x==y?0:x>y?(i(y,x) = run('+-[',x,',',y,'] sqr. u {ia} rm.')):i" k.

And then, you would use it as:

$ gmic sp portrait1,portrait2,portrait3 my_mse

But in fact, that’s not how this would be used the most, because most of the time you probably want to keep your 3 images after the MSE is computed, so, you’d rather use it like this:

$ gmic sp portrait1,portrait2,portrait3 +my_mse

Here, the +my_mse works as expected, but is not efficient : indeed, when a custom command is invoked with a +command syntax, the interpreter first duplicates the input selection of images (here all images) and run my_mse on this new (temporary) set of images. In our case, the three input images are then duplicated in memory, just to be able to compute the MSE on them.
This is not optimal : you know you won’t modify the input images, so there is no need to duplicate them before invoking my_mse.
Of course, you could write a version of the my_mse command that just inserts the MSE matrix at the end of the image list (simply by removing the last k. in the my_mse code). But this would go a bit against the G’MIC philosophy that says a command[selection] acts in place (so modify the selection) and that +command[selection] returns its result as a new image in the list (so keep the selection unmodified).

That is where the +command specialization is useful.

In G’MIC 2.99, you’ll be able to define the custom command my_mse as:

+my_mse : # Specialization for the '+my_mse' invokation.
  $!,$!,1,1,">x==y?0:x>y?(i(y,x) = run('+-[',x,',',y,'] sqr. u {ia} rm.')):i"

my_mse:
  +my_mse k.

Here, when the interpreter encounters a call to +my_mse, it recognizes it as a +command specialization and executes the specialized command just as a regular command (so, without the + sign). Consequence: no image copies done and the command is 2x faster to execute here (with 3 input images).

Here, we also defined a regular my_mse command to get a consistent behavior when my_mse is invoked without the + preprended.

Also, note that:

  • Custom commands that have no +-specializations defined (most of the commands basically) just works as before when they are invoked with the +command syntax.
  • If you define a +command specialization without defining the corresponding command, then only the +command invokation will be recognized. In practice, this means you can decide to allow of forbid the execution of a command when it is invoked with +command or command.
  • It is obviously not recommended to implement a +command specialization that is not consistent with the corresponding command implementation :slight_smile: (but it becomes possible anyway).

It’s not a big thing, but this will further optimize the calling of some custom commands by avoiding unnecessary copies of images.
I’m actually planning to use this mechanism to have non-builting implementations of mse and psnr in next G’MIC version.

3 Likes

Good addition. Frequent user of mse / psnr. Generally store them in variables.

Hmm, looks like I would have to revise my scripts and see how I can use this to good use when 2.9.9 arrives.

What’s cool with it is that it is just an extension of the existing system, so everything is backward-compatible without changing anything.
The only difference is that you can now define functions such as

+func : 
  echo "do something for specializing +func"

I’ve started using this feature in stdlib 2.9.9 (so far for mse and psnr).
I’ll try to find other places where it is useful.

Will try it once the Windows version comes out.

In a few minutes hopefully :slight_smile:

I thought you were on vacation. :slight_smile:

1 Like

Not anymore!

1 Like

News about this:

  • It’s not possible to define a +command specialization without the corresponding command and still be able to invoke command (without the +). In that case, it is just equivalent to invoking +command.

This solves a problem we had in previous versions of G’MIC for custom commands that were designed to insert a new image in the image list (e.g. clut or palette).
The problem was the following:

$ gmic sp lena +clut summer

duplicated the image lena, while

$ gmic sp lena clut summer

did not, but was not really in line with the G’MIC command philosophy that said +command inserts a new image while command just acts in place.

Now, defining the command clut as:

+clut : 
   # Code of command 'clut' here.

solves this problem, and

$ gmic sp lena +clut summer

just inserts the new clut image at the end of the list, without duplicating ‘lena’.

I’ve posted new pre-release binaries for Ubuntu 20.04 and Windows, this morning.

I got around using this at this time.

++command is not possible if one wants to add another image. Would another symbol work? I believe ~command would work instead of +command. Or is there something I’m missing?

Don’t bother about the “+command specialization”. Use +command!

I don’t understand what you try to do with your ++command.
Having a +command specialization does not mean you can invoke it with ++command.