G'MIC exercises

Like one of these? https://www.imagemagick.org/Usage/resize/#resize

More like something like this.

Image #0 = Big Image
Image #1 = Target Small Image

You set points from the big image and then go into the small image to set point again. Then, it’ll automatically rescale and fit based on the info found on those point. Kind of an automated way to rescale to fit features from one image to another image.

Did you say features as in objects and then overlay images? In any case, I would need an example instead of just text because right now I am just guessing…

Yes. By features, I think the best approach would be manual edge detection.

Here’s two picture to show what I think would be best.

  1. The picture to use for scaling and placement
    image
  2. The target image to scale and move to fit features.
    image

Ideally, I would draw line to place reference as feature, and then the image would scale and move to fit that placement.

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.