G'MIC exercises

Now that the earlier problem was solved [See earlier thread to see that I have solved the transformation problem] -
I’m having trouble making something work.

rep_test_val:
rm
repeat $#-3
    val={4+$>}
    orientation=${i=$val}
    1,1,1,1,$orientation
done
a x

See what I’m doing there? The output should be only numbers within argument 4 and above. I know I could do ($4–1), but however, I need to make the above work for a command I am working on. A snip of the command I’m working on is here.

        val={4+$>}
        orientation=${i=$val}
        if $orientation
            width={min($length_1,$length_2)}
            height={max($length_1,$length_2)}
        else
            width={max($length_1,$length_2)}
            height={min($length_1,$length_2)}
        fi

The closest I got to it was this which gives me error that includes $4 in it when there is 4 argument.

rep_test_val:
repeat $#-3
    val={4+$>}
    orientation="$"$val
    1,1,1,1,$orientation
done

The answer wasn’t easy to find, but here it is.

rep_test_val:
repeat $#-3
    $=val
    1,1,1,1,${val{$>+4}}
done

EDIT:
Now, what I would like to do is to be able to access original ratio of image within command, just before the commands.

#@cli rep_ratio_orientation:
rep_ratio_orientation:
ti=$!
u {"
if(w#0>h#0,ro=[0],ro=[1]);
for (k = 0, k<"$ti", ++k,
    if (w#k>h#k,tr=[0],tr=[1]);
    ro=[ro,tr];
);
(ro)"}

The above is my shoddy attempt at doing it. The reason why is that I would like to be able to do this with my rectangular polar transformation cli filter.

or={$-rep_ratio_orientation} rep_polrectrans 0,0,1,$or

The above command should work. I believe that this would be very useful for future filter. @David_Tschumperle

EDIT: Better attempt at $rep_ratio_orientation

Curious what the application of this would be.

@David_Tschumperle

@afre and I were having a PM conversation pertaining to getting pass to work in context of fill function. Right now, I would like to edit my modf command to allow for 2 different set of arguments, and eliminate the need for the 4th argument. The 2 arguments for $3 should be either images or number. He suggested to use pass, but I didn’t get it to work correctly, and he mentioned he didn’t get it to work in form of *[0] [1].

#@cli modf:
#@cli : (eq. to '_modular_formula').
#@cli : $ modf 3,255,{128/255},0 ,
modf : _modular_formula $*
#@cli _modular_formula : 0<=operation<=5,chan_v>0, 0<value[%]<=1,two_layers={0=Do not use layer as blending mode | two_layers=Use Layers as blending mode}
#@cli : Default value : 'two_layers=0'
_modular_formula :
skip ${4=0}
if {$1==0} f "eps=10^-8;img=i#0;vp=$4==1?i#1/$2:$3;mv=($2*vp)+eps;f=img-mv*floor(img/mv);f>$2*vp?$2*vp:f"
elif {$1==1} f "eps=10^-8;img=i#0;vp=$4==1?i#1/$2:$3;mv=($2*vp)+eps;nf=img-mv*floor(img/mv);minm=$2*vp;e=ceil((i#0/minm))%2>0?$2:0;cinv=i#0>0?e:$2;cinv>0?nf:mv-nf"
elif {$1==2} f "eps=10^-8;img=i#0;vp=$4==1?i#1/$2:$3;ivp=1/vp;simg=ivp*img;maxm=$2+eps;f=simg-maxm*floor(simg/maxm)"
elif {$1==3} f "eps=10^-8;img=i#0;vp=$4==1?i#1/$2:$3;ivp=1/vp;simg=ivp*img;maxm=$2+eps;f=simg-maxm*floor(simg/maxm);minm=$2*vp;e=ceil((i#0/minm))%2>0?$2:0;cinv=i#0>0?e:$2;cinv>0?f:$2-f"
elif {$1==4} f "eps=10^-8;img=i#0;vp=$4==1?i#1/$2:$3;vpi=vp*$2;fimg=img+vpi;maxm=$2+eps;fimg-maxm*floor(fimg/maxm)"
elif {$1==5} f "eps=10^-8;img=i#0;vp=$4==1?i#1/$2:$3;vpi=vp*$2;fimg=img+vpi;maxm=$2+eps;f=fimg-maxm*floor(fimg/maxm);cinv=fimg>maxm?$2:0;cinv>0?maxm-f:f" fi

This works in cases of two layers, but however I would have to assign 4 arguments and only be restricted into one layer. This is due to the fill function.

How would I modify it, so that modf[-1] 3,255,[-3] becomes valid and thus only 3 arguments would be needed while the 3rd argument can also take a number?

I know how it works, just not in your case ATM. I am not in that headspace, sorry. I am sure David or the others can help. :slight_smile:

Oh… you mean, either an image or a value? We’ve already discussed this somewhere.

Yes, as an image or value. If it has been discussed somewhere, I would like to know where.

On your thread. Ha ha.

Wrap with

if ${is_image_arg\ $3} pass$3 0 ... else ... fi
2 Likes

How exactly do I return coordinates for all non-alpha values within a radius within x,y,z coordinates? The first 3 coordinates would be the 0,0,0 relative point.

For codes on found in my thread:

#@cli rep_n0_alp_coords: eq. to 'rep_nonzero_alpha_count'. : (+)
rep_n0_alp_coords: rep_nonzero_alpha_coordinates
#@cli rep_nonzero_alpha_coordinates:
#@cli : Return the number of non-zero alpha of selected images.
#@cli : (eq. to 'rep_n0_alp_coords').
rep_nonzero_alpha_coordinates:
imgs={$!}
tna=${-rep_n0_alp_c}
tna={"sum("$tna")"}
tna*=3
u {"coordinates=vector"$tna"(0);mult=0;
for(img=0,img<"$imgs",img++,
    last_channel=s#img-1;
    for(pz=0,pz<d#img,pz++,
        for(py=0,py<h#img,py++,
            for(px=0,px<w#img,px++,
                if(i(#img,px,py,pz,last_channel)!=0,coordinates[mult*3]=px;coordinates[mult*3+1]=py;coordinates[mult*3+2];mult++;);
            );
        );
    );
);
(coordinates)
"}
#@cli rep_n0_alp_c: eq. to 'rep_nonzero_alpha_count'. : (+)
rep_n0_alp_c: rep_nonzero_alpha_count
#@cli rep_nonzero_alpha_count:
#@cli : Return the number of non-zero alpha of selected images.
#@cli : (eq. to 'rep_n0_alp_c').
rep_nonzero_alpha_count:
imgs={$!}
u {"num_alpha=vector"$imgs"(0);
for(img=0,img<"$imgs",img++,
    alpha_count=0;
    last_channel=s#img-1;
    for(pz=0,pz<d#img,pz++,
        for(px=0,px<w#img,px++,
            for(py=0,py<h#img,py++,
                if(i(#img,px,py,pz,last_channel)!=0,alpha_count++;);
            );
        );
    );
    num_alpha[img]=alpha_count;
);
(num_alpha)
"}

And this is an ongoing solution to solve this thread - Anything to autoconnect points within G'MIC?

That is loopy. I don’t think you need that many. Many functions already loop themselves, just as fill does.

Could you also explain your question using an actual example? Keep it dead simple. I am not quite sure what you want to do.

I’ll try to explain better with images.

Input Image of 32x32

image

The search image

The placement of the search image

image

The output image

image

The process of what I want:

  1. Using a search radius on the input image and place at x,y,z coordinate (Note: x,y,z place is suppose to be where the center of the sphere or circle is.), find all the white pixels coordinates that resides within the search image placed at x,y,z. The white pixels are on the output image.
  2. Then output the coordinates of all white pixels that resides within the boundary of the search image.

Use the crop() function is retrieve your neighbourhood. Each parameter will loop if you use whds variables or not if you use values. N=crop(...); If you want another shape, you would need a set of conditions to rule out those regions.

@afre
Well, I haven’t figured out a way to avoid the for(z..for(y,...for(x...););); loop thing. I still need to find a way to extract all coordinates, and to do that , the easiest routes was to use the loop. But, I did managed to only need one loop to extract what I need.

imgs={$!}
1,1,1,1
eval ${-math_lib}"
for(img=0,img<"$imgs",img++,
    alpc=s#img-1;
    n0alpc=0;
    for(pz=0,pz<d#img,pz++,
        for(px=0,px<w#img,px++,
            for(py=0,py<h#img,py++,if(i(#img,px,py,pz,alpc),dar_insert(#-1,px);dar_insert(#-1,py);dar_insert(#-1,pz););
            );
        );
    );
);
"
size={iM#-1}
r. 1,{iM#-1},1,1,0,0,0,0
u {"coords=vector"$size"(0);
for(k=0,k<h#-1,k++,coords[k]=i(#-1,0,k););
(coords)
"}
rm.

Sorry for the incomplete answer above; my dad has been terribly sick again. Here is some more to go by on crop(...). Take this silly foo:

f N=crop(x,y,z,c,3*2+1,3*2+1,1,1);min(N)>=128?i/2:i

It takes a radius=3 neighbourhood for every pixel and, if the min(N)>=128, do i/2. If you figure out how to use crop(...) to your advantage, perhaps you could be able to crop a or many ROI and use each window to extract coordinates.

my dad has been terribly sick again.

In that case, I won’t bother you with questions for a while, but I’ll try to find out for myself like usually.


@KaRo You wouldn’t happen to know how to get value found in n placement of a variable assigned? What I’m trying to achieve is Gossamer filter for Paint.NET, but for g’mic. Hence, why I am extracting coordinates.

rep_sphere_search_coords 5,0 #0,-2,0,-1,-1.....#
test=${}
error {$test[4]} #Expected output == -1}#
#Actual Output == Item substitution.....#

I don’t want to recreate the image over and over per loop for efficiency reasons. Hence, my need to do this.

EDIT: Nothing works. I can’t access vectors without going into eval or u, and I wish to be able to access them outside of those. I guess I will settle with crop even though I don’t want to create a image to make the task easier.

Time to post again after what feels like a century.

First, after a long while of trying to figure out how to do this, giving up and then sorting it out using the GEGL implementation as a reference, the kaleidoscope layer cake script is ready to use.

#@gui Kaleidoscope Layer Cake : fx_jr_klc, fx_jr_klc_preview(1)
#@gui : sep = separator()
#@gui : Kaleidoscope Mirrors = int(6,1,64)
#@gui : Mirror Rotation = float(0,-360,360)
#@gui : Result Rotation = float(0,-360,360)
#@gui : Centre (%) = point(50,50,0,1)
#@gui : Mirror Offset (%) = point(50,50,0,1)
#@gui : Scale (%) = float(100,0,1000)
#@gui : Scale Bend (%) = float(0,-5,5)
#@gui : Broken Mirrors = choice("Off","On","Reverse")
#@gui : Layer Cake Density = float(30,0,100)
#@gui : Angle = float(0,-360,360)
#@gui : Angle Mode = choice("Normal","Divide by mirror quantity")
#@gui : Anti-Alias = choice("Off","2","3","4")
#@gui : Interpolation = choice(2,"None","Linear","Bicubic")
#@gui : Boundary = choice(3,"Transparent","Nearest","Periodic","Mirror")
fx_jr_klc:
aa=($14+1)
r2dx w*$aa
num=$1
mrot={$2/180*pi}
rrot={$3/180*pi}
cx=$4*w/100
cy=$5*h/100
ox=$6*w/100
oy=$7*h/100
scale=$8/100
sbend=$9
broken=$10
lcd=$11
lcang={$12/180*pi}
lcam=$13
inter=$15
bound=$16
f "begin(mrot="$mrot";rrot="$rrot";cx="$cx";cy="$cy";ox="$ox";oy="$oy";num="$num";scale="$scale";sbend="$sbend";broken="$broken";inter="$inter";bound="$bound";lcd="$lcd";lcang="$lcang";lcam="$lcam";aa="$aa";);
vx=x-cx+0.5*aa;vy=y-cy+0.5*aa;
maxr=sqrt((w+0.5*aa)^2+(h+0.5*aa)^2)/2;
rad=sqrt(vx^2+vy^2)/maxr;
radius=((rad)^(2^sbend));
ang=atan2(vy,vx)-mrot-rrot-((lcd==0?(radius*scale):(floor(radius*lcd*scale)/lcd))*lcang/(lcam?num:1));
awidth=pi/num;
mult = ceil(ang/awidth)-1;
ang -= mult*awidth;
broken==1?ang=ang:broken==2?ang=awidth-ang:(mult%2==1)?(ang = awidth - ang);
ang += mrot;
xwarp=radius*scale*maxr*cos(ang)+ox-0.5*aa;
ywarp=radius*scale*maxr*sin(ang)+oy-0.5*aa;
I=I(xwarp,ywarp,z,inter,bound)"
r2dx w/$aa
fx_jr_klc_preview:
fx_jr_klc $*

The only issue with this is that the I haven’t figured out a way to perform some kind of bilinear interpolation near the edges of the layers and strips as I was able to do with the layer cake script.

Meanwhile, I’ve been trying to figure out how to speed up the DCT and IDCT commands which would help with speeding up a far more configurable JFIF encoding and glitching filter. The current issue is that when an image is split into small tiles (say, 8x8) it’s painfully slow, and yet performing a DCT on the whole image is pretty fast. Today I’ve been looking for fast DCT algorithms to try and mitigate this but all the implementations I’ve found only work with powers of 2. I’m not sure how to generalise this.

While I was hunting for such generalisations I found an image scaling algorithm which might be useful: https://www.tau.ac.il/~bilevich/DCT_Scaling_Algorithm_SPIE_2013.pdf

1 Like

In that case, I would suggest to create a image, and utilize transformation within a filling of a image much in the same way that I did with rep_rectangular_polar_transform or rep_equi2cube.

Wouldn’t that make the transitions between kaleidoscope strips increase with distance from the centre though?

I thought that was the idea of the layer cake filter?

The layer cake script can blur the layers with respect to the radius. A modified kaleidoscope script could blur the strips only with respect to the angle - but then the degree of blurring would increase with distance from the centre.

I can’t seem to get GUI options to appear and disappear for my neon script.

#@gui Neon : fx_neon, fx_neon_preview
#@gui : note = note("Turns bright image outlines into bright, neon-like lines.")
#@gui : sep = separator(), note = note("Lines")
#@gui : 1. Norm Mode = choice("Gradient norm","Hessian","Laplacian","Rotation-invariant gradient","Afre's Edge algorithm")
#@gui : 2. Thinning  = int(1,1,10)
#@gui : 3. Recovery  = float(1,.5,4)
#@gui : 4. Brightness  = float(1,.5,4)
#@gui : 5. Details  = float(1,.5,4)
#@gui : 6. Smoothness = float(0,0,10)
#@gui : 7. Contrast = float(0.45,0,1.5)
#@gui : 8. Min Threshold = float(40,0,100)
#@gui : 9. Max Threshold = float(60,0,100)
#@gui : 10. Negative = bool(0)
#@gui : 11. Opacity Over Original = float(1,0,1)
#@gui : 12. Saturation = float(1.15,0,4)
#@gui : 13. Blur Colours = float(2,0,20)
#@gui : sep = separator(), note = note("Antialias")
#@gui : 14. Amplitude = float(3,0,100)
#@gui : 15. Edge Threshold (%) = float(0,0,100)
#@gui : 16. Smoothness = float(3,0,5)
#@gui : sep = separator(), note = note("Colour Glow 1")
#@gui : 17. Size = float(20,0,100)
#@gui : 18. Intensity = float(0.4,0,3)
#@gui : 19. Darken = float(0.1,0,1)
#@gui : 20. Saturation = float(1.5,0,4)
#@gui : sep = separator(), note = note("Colour Glow 2")
#@gui : 21. Size = float(5,0,100)
#@gui : 22. Intensity = float(0.2,0,3)
#@gui : 23. Darken = float(0.1,0,1)
#@gui : 24. Saturation = float(1,0,4)
#@gui : sep = separator(), note = note("Boost Glow")
#@gui : 25. Size = float(2,0,5)
#@gui : 26. Intensity = float(1,0,3)
#@gui : sep = separator()
#@gui : 27. Smooth Hues = float(0,0,20)
#@gui : sep = separator()
#@gui : 28. Alpha = bool(0)
#@gui : 29. Alpha Power = float(1,0,5)
#@gui : 30. Alpha Multiplier = float(1,0,5)
#@gui : sep = separator(), 31-33. Preview type = choice("Full","Forward horizontal","Forward vertical","Backward horizontal","Backward vertical","Duplicate top","Duplicate left","Duplicate bottom","Duplicate right","Duplicate horizontal","Duplicate vertical","Checkered","Checkered inverse"), Preview Split = point(50,50,0,0,200,200,200,0,10)_0
fx_neon :
repeat $! l[$>]
+fc 0,0,0 rv blend alpha
to_rgb rgb2hsl8 s c
*.. {$8^2.5} c 0,255
a[0-2] c hsl82rgb
if $11
[0] l[1]
b $6
if {$1==1}
+hessian xx sqr.
+hessian.. yy sqr. +[-2,-1]
hessian.. zz sqr.. +[-2,-1]
s={s} s. c +[-$s--1] sqrt.
elif {$1==2}
laplacian abs to_gray to_rgb
elif {$1==3}
gradient xyz abs blend add to_gray to_rgb
elif {$1==4}
afre_edge ${2-5}
else
gradient_norm replace_inf 1 replace_nan 0
fi
c 0,255
^ $7
c $8%,$9%
if $10 negate fi
n 0,255
if {$14!=0||$15!=100}
fx_smooth_antialias ${14-16}
fi
endl
if $13
b[0] {$6}%
fi
blend multiply,$11
fi
+b[0] {$17%*100},1 *[1] {$18*sqrt($17%)*10} -[1] {(($18*sqrt($17%)*128)-1)^(sqrt($19))}
+b[0] {$21%*100},1 *[2] {$22*sqrt($21%)*10} -[2] {(($22*sqrt($21%)*128)-1)^(sqrt($19))}
+b[0] $25,1 *[3] {($18+$22)*$25*($26^2.5)}
rgb2hsl[1-3] s[1-3] c
*[2] {$20^2.5}
*[5] {$24^2.5}
*[8] 0
a[1-3] c a[2-4] c a[3-5] c hsl2rgb[1-3]
replace_inf 1 replace_nan 0
blend add
if $27
rgb2ycbcr s c b[1,2] {$27%*100} a c ycbcr2rgb
fi
if $28
rgb2hsv8 100%,100%,1,1 f[1] "((j(#0,0,0,0,2)/255)^(1/$25))*255*$30" f[0] "[i0,i1,255]" hsv82rgb[0]  a c
fi

endl done
fx_neon_preview :
gui_split_preview "fx_neon ${1-30}",${-3--1}
u "{$1}"\
"{$2}"_{$1==4?2:0}\
"{$3}"_{$1==4?2:0}\
"{$4}"_{$1==4?2:0}\
"{$5}"_{$1==4?2:0}\
"{$6}"\
"{$7}"\
"{$8}"\
"{$9}"\
"{$10}"\
"{$11}"\
"{$12}"\
"{$13}"\
"{$14}"\
"{$15}"\
"{$16}"\
"{$17}"\
"{$18}"\
"{$19}"\
"{$20}"\
"{$21}"\
"{$22}"\
"{$23}"\
"{$24}"\
"{$25}"\
"{$26}"\
"{$27}"\
"{$28}"\
"{$29}"\
"{$30}"\
"{$31}"\
"{$32}"\
"{$33}"

I want options 2-5 to only appear when option 1 has a value of 4 but all of them display no matter what value option 1 has.

@Joan_Rake1 The _ is supposed to be inside the " marks otherwise known as quotation marks.