G'MIC exercises

You might find some ideas here: http://www.ipol.im/.

I’ll just let you know I bookmarked that post. Speaking of which, I should bookmark the recent imblend.m primary source thread I made earlier.

Yeah, I always forget to bookmark stuff. Then for the life of me, I cannot find the resource again… Speaking of imblend.m, I have only really used soft light eb. Sometimes with FG negated; e.g., for my latest Play Raw entry.

Why would negate FG for softlight EB?

Soft light increases contrast, so negation would decrease it. At least that is the idea. Actually, that filter would be easier to prepare for afre.gmic. Should probably get on it first… Still figuring out echoing and error output for my guided filter. :sweat_smile:

@David_Tschumperle

Thanks for the full example. I sort of had it but mostly didn’t. The thing about indexing is that there are multiple ways to reference an image including, for my example, . , [-1] , or [0--1] . I will stick with the image name for now. This is what I have.

foo_pass0_:
  v - pass$1 1 s_name={`"s = ['"{b}"']; s[find(s,'_c1')] = 0; s[find(s,'2')] = 49; s[find(s,'3')] = 50; s[find(s,'4')] = 51; s"`} rm.
  v + e[^-1] "Process image$? with image '"$s_name"'."

Ideally, I would want to find all _c2, _c3, _c4,… strings and then de-increment the number. At the moment, I am only finding the numbers 2, 3, 4 and replacing them individually, which will leave out _c5,… and replace numbers that could be a legitimate part of the name.

f "
c=0;
sd=w/h;
ang=pi*(45/180);
xx=(x+w/2*0)/w-.5/(h>w?1/sd:1);
yy=(y+h/2*0)/h-.5/(w>h?sd:1);
XX=xx*cos(ang)-yy*sin(ang);
YY=xx*sin(ang)+yy*cos(ang);
xx=XX;
yy=YY;
xx+=.5/(h>w?1/sd:1);
yy+=.5/(w>h?sd:1);
xx*=w;
yy*=h;
zx=("$xmin"+xx*("$xmax"-"$xmin")/w)/(h>w?1:1/sd);
zy=("$ymin"+yy*("$ymax"-"$ymin")/h)/(h>w?sd:1);
vx=zx;
vy=zy;
for(v=0,v<"$iterations",v++,
    a=vx;
    b=vy;
    if(c==0,
        vx=a/cos(b)+"$cx";
        vy=b/sin(a)+"$cy";
    elseif(c==1),
        vx=a/sin(b)+"$cx";
        vy=b/cos(a)+"$cy";
    elseif(c==2),
        vx=a/tan(b)+"$cx";
        vy=b/tan(a)+"$cy";
    elseif(c==3),
        vx=(a/cos(b))*sin(a)+"$cx";
        vy=(b/sin(a))*cos(b)+"$cy";
    )
    if((vy*vy+vx*vx)>"$escape",break())
);
abs(zx)+abs(zy)?v;
"

How to use else if in content of if block within fill? The only workaround is to use a ?:?:?: series, and that’s much harder to read and understand. It seem like I have to create two function block with ? : to do something similar, and that’s not something I would want to do as I would rather have two formula close to each other, and it’s easier to tell if something is up. I could do if within if, but would that slow thing down?

EDIT:

My solution was to replace the if else if block with this, but it doesn’t look nice.

    if(c==0,
        vx=a/cos(b)+"$cx";
        vy=b/sin(a)+"$cy";
            ,
            if(c==1,
                vx=a/sin(b)+"$cx";
                vy=b/cos(a)+"$cy";
                ,
                if(c==2,
                    vx=a/tan(b)+"$cx";
                    vy=b/tan(a)+"$cy";
                    ,
                    if(c==3,
                        vx=vx=(a/cos(b))*sin(a)+"$cx";
                        vy=vy=(b/sin(a))*cos(b)+"$cy";
                        );
                    );
                );
        );

Why not just

if(...);
if(...);
if(...);
1 Like

That looks a lot better than my proposed method. Thanks!

I have been asking @David_Tschumperle in private a series of questions, using foo_* commands to help facilitate my learning. The last one might be of interest to you all. Perhaps you already have some idea or already solved this and can help me right away.

I am trying to learn how to apply : (no arg) to my commands. It isn’t so easy. I took some cues from stdlib.gmic to create this foo.

foo_noarg_:
  l[]
    if isnum("$1")
      e[] "good"
      skip ${1=0},${2=1},${3=0}
      a=$1 b=$2 c=$3
    else
      e[] "bad"
      if ["'$1'"]!=',' noarg fi
      a=0 b=1 c=0
    fi
    onfail e[] "ugly" noarg a=0 b=1 c=0
  endl
  sp $a sp $b sp $c

Out of the commands below, only gmic foo_noarg_ q works.

gmic foo_noarg_
gmic foo_noarg_ ,
gmic foo_noarg_ ,0
gmic foo_noarg_ q    # Works (^_^)
gmic foo_noarg_ , q
gmic foo_noarg_ ,0 q

I propose this shorter version:

foo_noarg_: skip ${1=0},${2=1},${3=0}
  l[]
    if "isnum($1) && isnum($2) && isnum($3)" a,b,c=$1,$2,$3
    else a,b,c=0,1,0 noarg
    fi
  onfail a,b,c=0,1,0 noarg
  endl
  sp $a,$b,$c

Your main mistake was that you were using if isnum("$1") before the skip command, where the default values of the arguments are set. skip or check should always be defined as the first instruction of a command. I don’t see any case where it could be useful to have them put elsewhere.

I admit that it was sloppy; I was bending over backwards getting it to work. What I learnt:

1 The conditional should check every parameter, not just the first one.

2 noarg should be the last element in the statement.

The problem I have with your example is that sp $a,$b,$c isn’t the same as sp $a sp $b sp $c.

There should be no difference in practice. Command sample may take multiple arguments.

You are right, if the arguments of sample are numbers (which is the case here), then you should use sp $a sp $b sp $c as you did.
Sorry about that.

Looks like we aren’t finished with our exercise yet. I have changed the variable values to see what happens with different parameters.

foo_noarg_: skip ${1=0},${2=1},${3=2}
  l[]
    if "isnum($1) && isnum($2) && isnum($3)" a,b,c=$1,$2,$3
    else a,b,c=3,4,5 noarg
    fi
    onfail a,b,c=6,7,8 noarg
  endl
  sp $a sp $b sp $c
gmic foo_noarg_      # apples, balloons, barbara
gmic foo_noarg_ ,    # apples, balloons, barbara
gmic foo_noarg_ ,0   # apples, apples, barbara
gmic foo_noarg_ q    # boats, bottles, butterfly
gmic foo_noarg_ , q  # apples, balloons, barbara
gmic foo_noarg_ ,0 q # apples, apples, barbara

gmic foo_noarg_ q is still the odd :duck:. It is the only case where the if condition fails. We never get to see an onfail either. Is onfail even necessary?


Let me skip ahead and tell you what my aim is with this enquiry. This is I want the command to do:

1 If (no arg) or ,, let $1,$2,$3 be random values.
2 If only some are omitted, only the omitted are random values.
3 If all values are specified, then all values are set.

onfail is necessary only in very rare cases. Like if what follow foo_no_arg_ would be something that destroys the math expression, but at the same time corresponds to some weird filename.
Like:

$ gmic foo_noarg_ ").jpeg"

it’s unlikely to happen in practice, but who knows ? :slight_smile:

And you your other request, I’d propose something like this:

foo : skip ${1=?},${2=?},${3=?}
  l[]
    a,b,c=?,?,?
    if ("(isnum($1) || ['$1']=='?') &&
         (isnum($2) || ['$2']=='?') &&
         (isnum($3) || ['$3']=='?')")
       a,b,c=${1-3}
    else noarg
    fi
  onfail noarg
  endl
  sp $a sp $b sp $c
1 Like

What does meshgrid() do in Octave? E.g.,

[cx, cy] = meshgrid(2*pi*[0:cols-1]/cols, 2*pi*[0:rows-1]/rows);

I suspect warp might be involved. Brain juice is lacking ATM. :dizzy_face:


Got it It generates 2 images, one filled along the x-axis and the other along the y. In the case above, the pattern is 2*pi*x/w and 2*pi*y/h.

Actually, I have no idea what you’re trying to do here. @Joan_Rake1 knows what meshgrid is, but I don’t.

Does G’MIC have a function like this?
foo( num,2,5 ) = num^2^2^2^2^2

For fill function - I used this “nexp(a,b,c)=(for(n=0,n<c,n++,a^b));”

Look everyone, my very first macro and use of eval~!

fooip_: skip ${1=2},${2=2},${3=5}
  eval fooip(x,y,z)=x^(y*z);fooip($1,$2,$3) e[] " "${}
gmic fooip_ 2,2,5
 1024

@afre @Iain How would you go by pixel sorting every pixel from top left pixel to bottom right pixel? I would like to pixel sort luminosity of every pixel in an arbitrary width and height in that order.

The only solution I can think of is to make a iterative algorithm which use bubble sorting.