Release of G'MIC 3.0


Try repeating the command line several times in the same terminal.
You must never see the cursor of the mouse.
You can change the image with the spacing bar, the ENTER key without touching the mouse.

I see what you mean. Before your suggestion, I tried 3 times with the cursor present at the beginning. After several more tries I see your point on it being there and not being there at the beginning. It isn’t consistently correct or wrong. Maybe it is a Windows issue because the OS sometimes has focus problems depending on your configuration and the software in use.

I confirm this. I’ll investigate :slight_smile:

@garagecoder , good catch !!! Thanks !

This should fix the issue.

1 Like

La modification " Fix command ‘cursor’ when applied on other display than ‘w0’ " supprime l’erreur "sp lena,256 sp colorful,256 sp earth,256 w2[2] cursor[2] 0 … " sous Windows.
Merci :o)

Le ‘problème’ d’affichage du curseur en plein écran avec le terminal Windows est toujours présent.

I notice there is no da_pop(), and da_remove() does not return the removed value either. Must we do da_pop=(V=i[da_size()-1];da_remove();V) or did I miss something?

1 Like

I was struck by such asymmetry as well.


# First in, first out queue...

foopush : -skip ${1=0}
      -eval "da_push(#0,$1)"

barpop :
      -status {"if(da_size(#0)>0,pop=I;da_remove(#0,0,0));_(Do things with pop.);pop"}

where one custom command, foopush pushes state subsequently accessed by another custom command barpop:

$ gmic gstatedemo.gmic 0 name. stack foopush 1234 barpop echo "From the stack: "'${}'
[gmic]-0./ Start G'MIC interpreter.
[gmic]-0./ Input custom command file 'gstatedemo.gmic' (4 new, total: 4468).
[gmic]-0./ Input empty image at position 0 (1 image 0x0x0x0).
[gmic]-1./ Set name of image [0] to 'stack'.
[gmic]-1./ From the stack: 1234
[gmic]-1./ Display image [0] = 'stack'.
[0] = 'stack':
  size = (1,2,1,1) [8 b of floats].
  data = (1234;0).
  min = 0, max = 1234, mean = 617, std = 872.57, coords_min = (0,1,0,0), coords_max = (0,0,0,0).
[gmic]-1./ End G'MIC interpreter

Note the local blocks in each custom, for there may be many such images serving as backing storage, and custom commands coordinating their state around one such store probably should address such by name.

Some further remarks along these lines may appear later in G’MIC Tutorial Fragments in the sweet by-and-by.

1 Like

Getting to the point of too many questions now, I do apologise!

Update: I did some testing, it seems arg2var handles the below properly. That should give me enough to work with - this question can now be ignored :slight_smile:

The next one: is there a good way to handle the use of files where some of the returned file/directory names contain commas and/or spaces?

So far I’ve worked around spaces in my own way, but commas give me trouble when trying to get the individual file names…

Edit: don’t shoot me, I would never use commas in filenames by choice!

This must explain why my changes to random rectangle division has failed. I ended up sticking with old math_lib.

  • da_remove() does not return the removed value (or vector) indeed. The main reason is that I don’t like the idea of having da_remove() systematically return a new object that wil take memory space (and that will require initialization with copy), if, after all, the user does not want to do anything useful with the removed value.

  • If necessary, I could add a da_back() function that would return the latest element of a dynamic array. Eventually, a da_pop() that does as da_back() but also remove it from the array.

Now I remember why I haven’t implemented it already… :slight_smile:
Basically, what kind of object should da_back() and da_pop() return ?

  • If the dynamic array is vector-valued, that would be probably a vector. In that case, it means the #index specified should be a const value (otherwise, the compiler cannot determine what the size of the output vector at compile time).
  • If the dynamic array is scalar-valued, that would be a scalar.

But it would be definitely not clear in the code whether the returned object is a scalar or a vector, while using i[da_size()-1] and I[da_size()-1] makes it explicit in the code.

Why can’t there be a identifier for if it is a scalar array or not, and make it compile based on that?

Hah yes, that very problem occurred to me later as well - a consequence of being a scripting language without strong typing I suppose. It’s not at all difficult to work around anyway!

There is a saying in France that goes, “Only fools don’t change their minds!”


After thinking a lot about this proposal, I don’t think I’ll let G’MIC support this syntax.
Let me detail a few reasons for that:

1 - The advantage of conciseness

Considering that a syntax as

add[0] $img

would be actually valid. What could be an equivalent syntax with the current version of the language? Well, it would be equivalent to:

$img add[0,-1]

which is really not that longer to write. The worst case would be to pass $img to a command different from add, that is not able to ‘merge’ the specified selection as a single image for the result. But even with that, it would only require:

$img command[0] . rm.

rather than command[0] $img. It is indeed longer, but not to the point where it becomes problematic. So for me, the argument of conciseness do not hold here.

2 - Required changes in the interpreter

On the other hand, from a technical point of view, supporting this syntax would require a quite large amount of changes in the current interpreter code, leading probably to a slight decrease of the interpreter performance concerning the parsing. Probably not enough to make it visible though. Anyway, something that requires a lot of work with only the benefit of begin slightly more concise than the existing syntax sounds not good to me.
You’re going to tell me that this is my problem, not the users’, so it’s not a valid point.
But as I am alone to develop this interpreter, and there is no lack of things to do… :wink:

3- Toward bad habits

Another problem I see with that new syntax : Why the user would have to deal with the list of images anymore ? It would be actually tempting to store each new image into a variable, with command store, then use those variables as arguments each time a command requires it.

That sounds good said like this, but I see several problems with this approach:

  • First, you have to know that command store basically acts like serialize: it transforms the image data into a form storable as a variable (basically a set of uchar8, stored as a string). This transformation has a real cost in terms of CPU cycles and memory usage, particularly if the image resolution is high. The reverse transform too (i.e. getting back a CImg<T> image from a string). So, generalizing this approach would lead to performance loss, because a lot of conversions from CImg<T> to *uchar8 could happen in practice (transparent to the user, but not for the CPU and for the memory!).
  • Second, I don’t really see the advantages of this new approach compared to the existing possibility to name your images in the stack and to use these names as variable names. This is actually a good coding practice when you have lot of different images to manage in a G’MIC command. It makes the code more clear and generally you don’t have to worry about the position of each image into the list.
foo : 
  nm[-3--1] lena,earth,colorful  # Set variable names to images in the stack

  r[lena,earth,colorful] 256,256,1,3
  +matchpatch[colorful] [lena],5 nm. displacement
  warp_patch[lena] [displacement],5
  blend[lena] [earth],softlight

In the above example, you can permute the order of the three input images in the list, and you won’t be in trouble. Just name the images correctly and everything becomes simple, no more [-4] to deal with :slight_smile: I’d actually suggest to do this as quickly as possible when you have more than 4 or 5 images to manage at the same time in your filters.
shame on me, it’s not something I do very often!

So, all these reasons make me think that there is already what is needed in G’MIC to not need this new syntax, syntax that could also make things slower in practice

1 Like

Apart from anything else, nice presentation on G’MIC internals, in particular, the internal workings of -store.

1 Like

@grosgood @David_Tschumperle
General consensus is it would be a bad move then, but thank you both for taking the time to consider it carefully!

I’ve already got some script which replicates the behaviour using the above alternatives, but I’m considering switching to named images instead. I had problems with those in the past when using implicit combination commands, such as add[firstname,secondname], but perhaps it’s time to give it another try…

Interestingly, I did actually test performance of store beforehand and discovered for the smaller meta-images I intend to use it with the overhead is insignificant. It’s quite slow with an entire usual image, but I wouldn’t be contemplating that.

Now I’m probably pushing my luck with one more question, but I can’t find a way to get the output of files (i.e. status) directly into an image with quoting intact, without first going via arg2var (or at least “converting” them individually to variables with $=var). Is that correct? The goal being to preserve filenames which contain spaces and/or commas.

Interesting question! It’s definitely not easy, as space and comma characters have a special meaning in the G’MIC language, and string substitution may occur here and there.
After experimenting a bit, I found this ‘minimal’ way (so far) to handle this case. Beware, it’s very tricky!!

# Tricky way of getting list of filenames containing spaces or commas!
foo :
  files *

  # Convert status into an image where each row = one filename.
  m "$0_f2i: $""=arg repeat $""# ({'${arg{1+$>}}'}) done a y" $0_f2i[] ${} um $0_f2i

  # Print filenames.
  repeat h e {`crop(0,$>,w,1)`} done

EDIT: Fix code snippet.

Multiple labels in selection is now handled correctly (was not the case before I guess).
Anyway, in that particular case of add[first,second] (without arguments), you need to know how the indices of first and last are sorted, to guess in which of the two image the result is merged.
In that case, I’d rather suggest to add the version of add that takes one argument:

add[first] [second] rm[second]

so this works whatever the relative order of [first] and [second] is.