Release of G'MIC 3.2

OK, I’ve fixed a few minor errors today in the different G’MIC scripts.
If everything is OK with the current version, I think I’ll make the release on Monday
(I will stop by the lab quickly to start the compilations in the morning…)

break() works, (didn’t try it, tnx)

but i’m thinking about exit from this list:

sp dog
f. "
echo(x,‘/’,y);
break();
"

I actually like the idea of outright stopping execution, and not making any further change to image. But, there are very few cases where you would want this. Usually, I write something like that like:

fill " # Insert a bunch of code here
 if(condition_exec,
   # Insert code here. If condition does not met, condition_exec=0 and 0 is treated as False.
 ,I);
 "

Also, you can do set('variable_name',output) to debug too or print().

You can also raises an abort signal to tell the entire G’MIC interpreter to stop, by adding run('q').
This will stop the interpreter as soon as the abort signal is tested.
By default, it is not tested for each image pixel, to keep things optimized, but you can also force it with function breakpoint().
So at the end, adding run('q'); breakpoint(); in your expression is a quite certain way to end your expression (and the whole interpreter as well).

Saying that also suggest that I should add a function abort() that does this. I’ll probably do it.

Done, with

and

exiting whole interpreter works with run(‘q’);brp();,
but i want to stay in, to investigate what i did wrong in the meantime
(if abort() does so, its OK)

I’m guessing what you mean is displaying the image, right?

Something like this?

5 f. if(x==3,display(#-1););x;

AFAIS it’s ok with the new release.

1 Like

If I want to put a kind of “breakpoint” during the expression evaluation, then I do as @Reptorian suggested :

foo : 
  sp colorful
  f "A = x + y;

    x==20 && y==20?( # Force "breakpoint" at pixel (20,20)
      print(A);
      display(#0);
   );

    A;
  "

yes, almost.
I can do

5 f. "echo(x);if(x>2,display(#-1));2*x;"

but I prefer

5 f. "echo(x);if(x>2,exit_math());2*x;" 
*possibly* d.
next_test_step
display

(condition is > not == and image is rather big)

there is method

next_proc:
 v 1 e ==$!== d q

main:
5 f. "echo(x);if(x>1,run('next_proc'));2*x;"

(yesterday this didn’t work for my error…)

Here’s another idea, and I believe it’s a brilliant idea.

I would like a generic command that does this:

#@cli rep_new_idea: input,list_of_variables
#@cli : Allow for users to choose between number and variable initials for parameters. All variables are set to 0 except chosen variable and return 1 into status. Return '0,input_argument' if input argument is not found.
rep_new_idea:
list_of_args=${2--1}
number_of_args={narg($list_of_args)}

if isnum($1)
 arg_choice={$1>=0?int($1)%$number_of_args:-1}
 if $arg_choice==-1
  status -1
  return
 fi
else
 $list_of_args={expr('x',$number_of_args)}
 arg_choice=$$1
 if !narg($arg_choice) 
  status $1,-1
  return
 fi
fi

$list_of_args={v=vector$number_of_args(0);v[$arg_choice]=1;v;}

Why would something like this be useful. For one thing, it’s very maintainable. Assuming you set up the variable, you can do a construct like this.

if $no_variable_is_found # Case of when input is not found in the list of variables
elif $variable_0
elif $variable_1
elif $variable_2
...
else
fi

So, this means you can look at corresponding initials. You don’t even need to worry about the number of arguments or setting ==0 and so. You can add argument initials, then add elif $variable and add in your argument there.

Here’s a real world use case where I use the above idea:

Example
#@cli rep_satellite: color_mapping,_gray_mode={ 0=luminosity | 1=luminosity_alternative | 2=lightness | 3=minimum_channel | 4=maximum_channel | 5=average },-1>=_midpoint_shift>=1,_sigmoid_level>=0,_normalize,color_position_a,....color_position_b,{ [palette] | hex_color_a },....,hex_color_z,....
#@cli : Apply Satellite mapping onto images.
#@cli : Default values: '_gray_mode=0'
rep_satellite:
skip ${2=0},${3=0},${4=0},${5=0}

  # Code Block

custom,pal,palette=-1
use_custom_palette,utilize_sig_adj,normalize_image=0,{[$3!=0||$4!=0,$5]}

list_of_palettes_with_single_initials=avn,bd,ft,jsl,ir2,ir2f,ir2h,ir2w,ir3,ir3b,rb,rbtop
number_of_pal_args={narg($list_of_palettes_with_single_initials)}

if isnum($1)
 pal_choice={$1>=0?int($1)%$number_of_pal_args:-1}
else
 $list_of_palettes_with_single_initials={expr('x',narg($list_of_palettes_with_single_initials))}
 pal_choice=$$1
 if !narg($pal_choice) error inv_inp_\$1 fi
fi

if $pal_choice==-1
 use_custom_palette=1
else
 $list_of_palettes_with_single_initials={v=vector$number_of_pal_args(0);v[$pal_choice]=1;v;}
fi

if isnum($2)
 c2g_mode={int($2)%6}
else
 m_luminosity,m_luminosity_alt,m_lightness,m_min,m_minimum,m_max,m_maximum,m_avg,m_average=0,1,2,{expr('x>>1',6)+3}
 c2g_mode=${m_$2}
 if !narg($c2g_mode) error inv_inp_\$2 fi
fi

append_back=0
foreach {

  # Code Block
 
 100%,100%,100%,1,"begin(
   const c2g_mode=$c2g_mode;
   c2g_mode==0?graymode(color)=color[0]*0.22248840+color[1]*0.71690369+color[2]*0.06060791:
   c2g_mode==1?graymode(color)=color[0]*0.2990+color[1]*0.5870+color[2]*0.1140:
   c2g_mode==2?graymode(color)=(max(color)+min(color))/2:
   c2g_mode==3?graymode(color)=min(color):
   c2g_mode==4?graymode(color)=max(color):
               graymode(color)=avg(color);  
  );
  graymode(I#0);"
 
  # Code Block
}

if $use_custom_palette
  # Code Block
else
 if $avn
  rep_satellite_create_reference_palette 48,52,56,60,64,68,72,76,80,84,88,92,96,100,104,108,112,116,120,124,128,132,136,140,144,148,152,156,160,164,168,172,176,180,184,188,192,196,200,204,208,212,216,220,224,250
  
  # Code Block

 elif $bd
  rep_satellite_create_reference_palette 59,68,97,175,188,199,209,215,221,226
  
  # Code Block

 elif $ft
  rep_satellite_create_reference_palette 44,152,184,204,216,224,237,253
  
  # Code Block

 elif $jsl
  rep_satellite_create_reference_palette 4,8,12,16,20,24,28,32,36,40,44,48,52,56,60,64,68,72,76,80,84,88,92,96,100,104,108,112,116,132,144,156,168,180,184,188,192,196,200,202,215,226,246
  
  # Code Block

 elif $ir2
  rep_satellite_create_reference_palette 2,26,51,62,68,69,81,111,131,171
  
  # Code Block

 elif $ir2f
  rep_satellite_create_reference_palette 151
  
  # Code Block
  
 elif $ir2h
  rep_satellite_create_reference_palette 13,126

  # Code Block
  
 elif $ir2w
  rep_satellite_create_reference_palette 42,191
  
  # Code Block
         
 elif $rb
  rep_satellite_create_reference_palette 4,8,12,16,20,24,28,32,36,40,44,48,52,56,60,64,68,72,76,80,84,88,92,96,100,104,108,112,116,120,124,128,132,136,140,144,148,152,156,160,164,168,172,176,180,184,188,192,196,200,204,208,212,216,220,224,228,232,236
  
  # Code Block

 elif $rbtop
  rep_satellite_create_reference_palette 61,91,101,145,155,171,191,201,211,221,246
  
  # Code Block
    
 elif $ir3
  rep_satellite_create_reference_palette 130,165,183,198,206,214,222,230
  
  # Code Block
    
 elif $ir3b
  rep_satellite_create_reference_palette 110,142,172,192,219
  
  # Code Block
  
 else error pal_id_no_info
 fi

 permute. yzcx
fi

contain_alpha=0

# Code Block

If you study the code, you’ll note that $1 can be a number or any of the following: avn,bd,ft,jsl,ir2,ir2f,ir2h,ir2w,ir3,ir3b,rb,rbtop. $2 case is a different version, but still showcases the benefit of said technique as $2 can be typed as min,max,lightness and it’ll work. This is easier to maintain, and the end user reap the benefits of not having to use numbers as argument.

On second thought, there might not be too much changes in context of line of codes. Maybe not that much benefit, but I’ll leave it to others to decide if this is worth it. There’s only benefit in context of complexity reduction of coding structure, but equally just as maintainable, but more so than the usual approach of having only $n as numbers.

Not sure I understood completely what you want to do here, but I’m here to remind that as long as the parameters of a command are defined as a unique item (so without space separators), then you are free to parse this list of argument as you wish.
For instance, if you think of a Python-style list of named arguments like:

my_function y=2,x=3,z=4

then, it’s obviously doable in G’MIC (you may have to introduce some specific commands to manage that syntax, but it’s 100% doable). If you don’t like the , argument separator and you prefer ; or anything else, it’s also possible. It’s just a matter of writing your own commands to manage your way of writing command arguments.

→ Anyway, I wouldn’t recommend to do it, as you’ll probably end up with commands that do not follow the same syntax and rules as all other commands, so the user of your command might feel a bit lost.


It’s true that In G’MIC, arguments to commands are not named by default, and just called $1, $2, and so on. This was made like (as well as other parts of the language) because of simplicity and compactness.
But as I said before, it’s usually good, when you write a complex command with many arguments to do something like:

#@cli foo : x,y,z,lambda1>0,lambda2>0,lambda3>0
#@cli : Do some fancy stuffs from its parameters.
foo : 
  x,y,z,lambda1,lambda2,lambda3=${1--6}
  check "$lambda1>0 && $lambda2>0 && $lambda3>0"

  # Use the named arguments in the command code, rather than $1,$2,...
  blur $lambda1

At this point, I don’t see a need for a new feature to be implemented specifically to manage command arguments. Everything is already there , I think.

I’m looking for a better way to allow users to use arguments like string_a,string_b or number_a,number_b as parameter which is basically what my code example did. So, if I were to type in ir2 as parameters, the resulting code utilize if $ir2 case upon execution. The same thing would happen if I type in 4. The way I written it is very maintainable though it’s not understandable.

See here:

list_of_palettes_with_single_initials=avn,bd,ft,jsl,ir2,ir2f,ir2h,ir2w,ir3,ir3b,rb,rbtop
number_of_pal_args={narg($list_of_palettes_with_single_initials)}
$list_of_palettes_with_single_initials={expr('x',narg($list_of_palettes_with_single_initials))}
$list_of_palettes_with_single_initials={v=vector$number_of_pal_args(0);v[$pal_choice]=1;v;}

With the above syntax, all I gotta do is to add in initials if I want to add a configuration, and then the user of said command can use the new initials as parameter argument or the integer representation of said parameter. In this case, there’s no need for me to add in if $1==‘avn’||$1==0 and so forth, and there’s no need for me to assign number as it’s done in the background.

But, like you said, everything in there even if this seem a little tricky to add in.

  • 2023/01/16: Release of G’MIC 3.2.0 (binary packages on their ways). Thanks to everyone who made it possible, especially all pixls.us folks :beers:
2 Likes

@David_Tschumperle

Bonjour,

Merci pour cette nouvelle version :smiley:


G’MIC CLI Win 32 bit + G’MIC GIMP QT 2.10 Win 32 bit + G’MIC GIMP QT 2.99.15 Portable Win 64 bit :

:o)

Kubuntu 20.04 / Gimp 2.10.32 / gmic_qt 3.2.0

Errors in Testing → Joan Rake → Deformations

Fake JFIF (JPEG) Encoder
*** Error in ./fx_jfif_fake/ *** Command ‘i’: Invalid selection [Q] (undefined label ‘Q’).

JFIF Effects
*** Error in ./fx_jfif/ *** Command ‘i’: Invalid selection [Q] (undefined label ‘Q’).

It’s my guess that it has to do with lines that has I[Q] (…).

Also, seem the code base needs restructuring. Something I plan to do at some point.