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 correspondingcommand
, 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
orcommand
. - It is obviously not recommended to implement a
+command
specialization that is not consistent with the correspondingcommand
implementation (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.