Reptorian G'MIC Filters

Yes, {s} should not work; e.g.,

gmic sp tiger sh {s}

unless you are grabbing s from the wrong image.

Ok, going to post a bug report with this current WIP sample.

#color_space,keep_original={ 0 = remove_original | 1 = keep_original },_duplicates_count>=2,_distance>0,0<=_angle<=360,0<=_boundary_conditions<=3,_interpolation={ 0=nearest_neighbor | 1=linear }#
initial_angle=270
distance=0.025
duplicates=10
incremental_angle={360/$duplicates}
impose={0?1}
duplicates+=$impose
max_alpha=255
adiv={$max_alpha*$duplicates}
nn=0
repeat $! l[$>]
    dist_hypo={$distance*sqrt(w^2+h^2)}
    if {s==1||s==3} 
        {w},{h},100%,100%,1/$duplicates a c
    else
        sh {s-1}
        /. $adiv
        rm.
    fi
    +store[0] fragment
    rep_sdaxy $dist_hypo,$initial_angle,2,1
    nn+=1
    do
        restore fragment
        rep_sdaxy. $dist_hypo,{$initial_angle+$nn*$incremental_angle},1,1
        sh[-2,-1] 0,{s-2}
        sh[-4,-3] {s}
        f[-4] "srcC=i#-4;srcA=i0#-2;dstC=i#-3;dstA=i0#-1;outA=srcA+dstA*(1-srcA);(!outA==0)?(srcC*srcA+dstC*dstA*(1-srcA))/outA:0"
        f[-2] "i+i#-1"
        rm[-5--1]
        nn+=1
    while $nn<$duplicates-$impose
    if $impose
        restore fragment
        sh[-2,-1] 0,{s-2}
        sh[-4,-3] {s}
        f[-4] "srcC=i#-4;srcA=i0#-2;dstC=i#-3;dstA=i0#-1;outA=srcA+dstA*(1-srcA);(!outA==0)?(srcC*srcA+dstC*dstA*(1-srcA))/outA:0"
        f[-2] "i+i#-1"
        rm[-5--1]
    fi
    sh {s-1} *. $max_alpha rm.
endl done

There is something to be explained here :

sh[-4,-3] {s}

here: the {s} is equivalent to {-1,s}, so substituted by the number of channel of the last image.
Maybe you expected {s} is replaced by s#-3 or s#-4, but if so, this is a misunderstanding of the language syntax.

Oh, now I get it. Thanks. I’ll close the bug report myself. G’MIC can be confusing at times.

Yep, that was what I was trying to say but I am not Mr G’MIC. ha ha

Not sure I agree with this :slight_smile:
Just remember that the arguments are always substituted (if needed) before the command execution. Use the debug flag to actually look at what is done during the interpretation:

$ gmic debug sample lena +luminance sh[-2] {s}

......>8..... skip some things here ....

<gmic>-1./luminance/#8509 Exit scope 'luminance/'.

<gmic>-2./ Item 'sh[-2]', selection [0].
<gmic>-2./ Command 'shared': arguments = '{s}' -> '1'.  # <- THIS!
[gmic]-2./ Insert shared buffer from channel 1 of image [0].
[gmic]-3./ Display images [0,1,2] = 'lena, lena_c1, lena_c1'.
[0] = 'lena':
  size = (512,512,1,3) [3072 Kio of floats].
  data = 0x55bc7b10b140 = (225,225,223,223,225,225,225,223,225,223,223,223,(...),78,78,78,77,91,80,79,89,77,79,79,82).
  min = 8, max = 251, mean = 128.241, std = 58.9512, coords_min = (457,60,0,1), coords_max = (425,20,0,0).
[1] = 'lena_c1':
  size = (512,512,1,1) [1024 Kio of floats].
  data = 0x55bc7af05e20 = (163.848,163.848,158.777,158.777,163.848,153.841,163.848,157.234,163.848,157.234,158.777,157.234,(...),72.2288,72.2288,72.2288,80.5533,97.1754,92.5469,96.6303,106.92,105.039,108.518,108.518,112.474).
  min = 36.324, max = 224.562, mean = 125.345, std = 46.617, coords_min = (457,60,0,0), coords_max = (289,76,0,0).
[2] = 'lena_c1':
  size = (512,512,1,1) [1024 Kio of shared floats].
  data = 0x55bc7b20b140 = (141,141,133,133,141,124,141,131,141,131,133,131,(...),45,45,45,53,73,63,63,73,66,72,72,75) [shared].
  min = 8, max = 221, mean = 98.9929, std = 52.7959, coords_min = (457,60,0,0), coords_max = (289,76,0,0).

Does debug work on gui filter? I should test that.

Here’s my next idea - Introducing "Mosaic Maniac Collage Paint" plugin - Plugins - Publishing ONLY! - paint.net Forum

Meanwhile my upgrade to modulo texture and fragment blur has to be done.

There is Debug (console) but it does nothing at least for my installation (Partha).

image

Ok, made the fractal generator.

ww={w}
hh={h}
xmax={pi}
xmin={pi*-1}
ymax={pi}
ymin={pi*-1}
escape=50000
iterations=255
cr={u(-10,10)}
ci={u(-10,10)}
7500,7500,1,1 k.
nww={w%2==0?w+1:w}
nhh={h%2==0?h+1:h}
r $nww,$nhh,1,1,0
f "
zr="$xmin"+x*("$xmax"-"$xmin")/w;
zi="$ymin"+y*("$ymax"-"$ymin")/h;
ir=zr;
ii=zi;
for(k=0,k<"$iterations",k++,a=ir;b=ii;ir=a/cos(b)+"$cr";ii=b/sin(a)+"$ci";if((ii*ii+ir*ir)>"$escape",break()));
k;
"
r {$ww},{$hh},1,1,3 n 0,255

Result:

Working with this code via code[local], I’m interested into finding more formulas for the filter. Starting with 6. During the meantime, I’m experimenting.
EDIT: Now I have 25 formulas. I still want more.

ww={w}
hh={h}

depth=7
r {$depth*100}%,{$depth*100}%,1,1,0

scale_dimensions_pi=1
M_pi={pi}
r_xy=.5
r_x=1
r_y=1
r_x*=$r_xy
r_y*=$r_xy
xmax={$r_x}
xmin={-1*$r_x}
ymax={$r_y}
ymin={-1*$r_y}
if $scale_dimensions_pi
    xmax*=$M_pi
    xmin*=$M_pi
    ymax*=$M_pi
    ymin*=$M_pi
fi

escape=450000
iterations=255
cx=-4.999112
cy=.14885

text="cx="{$cx}"\ncy="{$cy}""
f "
c=7;
sd=w/h;
ang=pi*(90/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);
        vy=b/sin(a);
        );
    if(c==1,
        vx=a/sin(b);
        vy=b/cos(a);
        );
    if(c==2,
        vx=a/tan(b);
        vy=b/tan(a);
        );
    if(c==3,
        vx=(a/cos(b))*sin(a);
        vy=(b/sin(a))*cos(b);
        );
    if(c==4,
        vx=(a/cos(b))*sin(b);
        vy=(b/sin(a))*cos(a);
        );
    if(c==5,
        vx=a/(cos(b)*sin(b));
        vy=b/(sin(a)*cos(a));
        );
    if(c==6,
        vx=a/tan(cos(b)*sin(b));
        vy=b/tan(cos(a)*sin(a));
        );
    if(c==7,
        vx=(tan(a+b)*b)/cos(b);
        vy=(tan(a-b)*a)/sin(a);
        );
    if(c==8,
        vx=a/(tan(b)*cos(b)*sin(b));
        vy=b/(tan(a)*cos(a)*sin(a));
        );
    if(c==9,
        vx=(a/(cos(b)))*(a/(sin(b)));
        vy=(b/(cos(b)))*(b/(sin(b)));
        );
    if(c==10,
        vx=(a/(cos(b)))+(a/(sin(b)));
        vy=(b/(cos(a)))+(b/(sin(a)));
        );
    if(c==11,
        vx=b+tan(a)/(a/(cos(b)))+(a/(sin(b)));
        vy=a+tan(b)/(b/(cos(a)))+(b/(sin(a)));
        );
    if(c==12,
        vx=(a+tan(a*b))/sin(b);
        vy=(b+tan(a*b))/cos(a);
        );
    if(c==13,
        vx=(a-tan(a*b))/sin(b);
        vy=(b-tan(a*b))/cos(a);
        );
    if(c==14,
        vx=(a*tan(a*b))/sin(b);
        vy=(b*tan(a*b))/cos(a);
        );
    if(c==15,
        vx=(a*tan(a*b))/sin(b);
        vy=(b*tan(a*b))/cos(a);
        );
    if(c==16,
        vx=a+tanh(a+b)/cos(b);
        vy=b+tanh(a+b)/sin(a);
        );
    if(c==17,
        vx=b+tan(a)/(a/(cos(b)))+(a/(sin(b)));
        vy=a+tan(b)/(b/(cos(a)))+(b/(sin(a)));
        );
    if(c==18,
        vx=(a+tan(a)+tan(b))/cos(a);
        vy=(b+tan(a)+tan(b))/sin(a);
        );
    if(c==19,
        vx=(a+tan(a)+tan(b))/sin(b);
        vy=(b+tan(a)+tan(b))/cos(a);
        );
    if(c==20,
        vx=a/(cos(tan(b))*sin(tan(b)));
        vy=b/(sin(tan(a))*cos(tan(a)));
        );
    if(c==21,
        vx=(tan(a)+b)/(cos(tan(b))*sin(tan(b)));
        vy=(tan(b)+a)/(sin(tan(a))*cos(tan(a)));
        );
    if(c==22,
        vx=(a+tanh(a+b))/cos(b);
        vy=(b+tanh(a+b))/sin(a);
        );
    if(c==23,
        vx=(a+tanh(a*b))/cos(b);
        vy=(b+tanh(a*b))/sin(a);
        );
    if(c==24,
        vx=(a+tanh(a*b))/(cos(b)*sin(a));
        vy=(b+tanh(a*b))/(sin(b)*cos(a));
        );
    vx+="$cx";
    vy+="$cy";
    if((vx^2+vy^2)>"$escape",break())
);
abs(zx)+abs(zy)?v;
"
r {$ww},{$hh},1,1,5 n 0,255
#to $text,3,3,5%#

Update - I ended up having 40 formulas, and it is close to being released into a pull request. ETA - 1-2 days.

A quick preview - This is the 45th formula used.

Suggestion: provide the ability for the user to input their own formulae. :wink:

Never mind, solved! It was the preview that was failing. Now, going to release it pretty soon!

I don’t know what you have solved because you keep on editing and / or deleting posts rapidly, which is very confusing. I could be reading your code and see it change in real time! Perhaps try using Gists and linking to them here. Won’t change anything but would be easier for me to follow you.

Ok, fair point, given my frequent coding, I might do it.

By the way, Thorn Fractal was released.

Got something here

r2dx 200%,3
+to_gray .
gradient_orientation. 2
*[-2,-1] {pi}
f.. (atan2(i,i#-1)+pi)*(360/(pi*2))
rm.
300,1,1,4
eval ${-math_lib}"
sp=0;
isx=wh#0/w#-1;
    for(p=0,p<wh#0,p++,
        if(sp<=w#-1,
            val=round(u(0,1)*isx+(isx*sp));
            i(#-1,sp,0,0,0)=val%w#0;
            i(#-1,sp,0,0,1)=floor(val/w#0);
            i(#-1,sp,0,0,2)=i(#1,i(#-1,sp,0,0,0),i(#-1,sp,0,0,1));
            i(#-1,sp,0,0,3)=i(#2,i(#-1,sp,0,0,0),i(#-1,sp,0,0,1));
            sp++;
        ,break();
        );
    );
"
sh. 2 pixelsort.. +,x,[-1] rm. rm..

{w#0},{h#0},1,{s#0}

repeat w#2
    x_pos={i(#2,$>,0,0,0)}
    y_pos={i(#2,$>,0,0,1)}
    luma_v={i(#1,$x_pos,$y_pos)}
    pos_ang={i(#2,$>,0,0,3)}
    colour={I(#0,$x_pos,$y_pos)}
    scs={($luma_v/iM#-2)*1024}
    dupang=6
    linethickness=2
    if floor($scs)>$linethickness
        if $linethickness%2==0
            if $scs%2==0
                $scs,$scs,1,{s}
            else
                {$scs+1},{$scs+1},1,{s}
            fi
        else
            if !$scs%2==0
                {$scs+1},{$scs+1},1,{s}
            else
                $scs,$scs,1,{s}
            fi
        fi
        repeat $dupang
            ang={($pos_ang+(360/$dupang)*$>+90)/180*pi}
            linethick. 50%,50%,{50-cos($ang)*50}%,{50-sin($ang)*50}%,$linethickness,1,$colour
        done
        sh. 0,{s-2}
        sh.. {s}
        j[-4] [-3],{-w#-1/2+$x_pos},{-h#-1/2+$y_pos},0,0,1,[-1],255
        rm[-3--1]
    fi
done
k[3]
r2dx 50%,2

It’s slow though because of the lack of way to do this without using polygon. Yes, it’s an attempt at a faster version of what @samj has made, but I’m planning to add variable opacity map to stars. I wanted the stars to be sorted by luminosity map. If G’MIC supported vectors directly, then this would have been made much faster.

I might utilize edge detection though.

I think I should do the above later.

I made rep_shape_brick. I think I’ll add diamond option here.

EDIT: Bevel style option been added.
EDIT: Beveling bugs fixed, now they all look like they’re of the same thickness.

#@cli rep_shape_brick: brick_width>0,brick_height>0,_mortar_width>0,_mortar_height>0,_bevel>=0,_outline>=0,_shift_direction= { 0=horizontal | 1=vertical },-1>=_shift_val>=1,_bevel_style= { 0=Round | 1=Inverse Round | 2=Diamond },_flip= { 0= Do Not Flip | 1= Flip }_sublevel>=0,_normal_01= { 0=Do Not Normalize | 1=Normalize to 0-1 Range }
rep_shape_brick:
skip ${3=10},${4=10},${5=0},${6=0},${7=0},${8=1},${9=0},${10=0},${11=0},${12=0}
sublevel={abs($11)}
sublevel+=1
brick_width={abs($1)*$sublevel}
brick_height={abs($2)*$sublevel}
mortar_width={abs($3)*$sublevel}
mortar_height={abs($4)*$sublevel}
bevel={abs($5)*$sublevel}
outline={abs($6)*$sublevel}
shift_direction=$7
shift_val=$8
bevel_style=$9
reverse_dir=$10
normal_01=$12

if !(($brick_width&&$brick_height)||$bevel) v + error "Brick Area must be greater than 0!" v - fi

if $bevel
    if $bevel_style==0||$bevel_style==1 shape_circle {$bevel*2} 
    else shape_diamond {$bevel*2} fi
    *. 2
    if $outline
        if $bevel_style==0 shape_circle {($bevel+$outline)*2}
        elif $bevel_style==1 shape_circle {($bevel+$outline+1)*2} shrink_xy. 1
        else shape_diamond {floor($bevel+($outline*(cos(45/180*pi)+sin(45/180*pi))))*2} r. {($bevel+$outline)*2},{($bevel+$outline)*2},100%,100%,0,0,.5,.5 fi 
        j[-1] [-2],.5~,.5~,0,0,.5,[-2]
        rm..
    fi
    s. x,2
    s[-2,-1] y,2
fi

{$brick_width<$bevel*2?$bevel*2:$brick_width},{$brick_height<$bevel*2?$bevel*2:$brick_height},1,1,1

if $outline
    expand_xy. $outline,0
    +. 1
else
    +. 1
fi

if $bevel if $bevel_style==1 negate[-5--2] fi fi

if $bevel
    j[-1] [-5],{$bevel_style!=1?0:1}~,{$bevel_style!=1?0:1}~
    j[-1] [-4],{$bevel_style!=1?0:1}~,{$bevel_style!=1?1:0}~
    j[-1] [-3],{$bevel_style!=1?1:0}~,{$bevel_style!=1?0:1}~ 
    j[-1] [-2],{$bevel_style!=1?1:0}~,{$bevel_style!=1?1:0}~ 
    rm[-5--2]
fi

mw={w}
mh={h}
mw/=2
mh/=2

r. {w+$mortar_width},{h+$mortar_height},100%,100%,0,0,1,1

if $shift_val
    if $shift_direction +shift. 0,{$shift_val*$mh+$mortar_height/2},0,0,2 a[-2,-1] x if $reverse_dir mirror. x fi
    else +shift. {$shift_val*$mw+$mortar_width/2},0,0,0,2 a[-2,-1] y if $reverse_dir mirror. y fi
    fi 
fi

if $sublevel-1 r2dx. {(1/$sublevel)*100}%,5 fi
if $normal_01 n. 0,1 fi

@afre I’m not sure if I’m feeling it because of lacking in confidence about parameter order.

See naming, formatting and order. Haven’t tried your filter, just basing it on what I see here.

Depending on what it does, you may want to change the name _sublevel.

I also removed normalization. CLI users should know how to normalize; if not, then set it to common sense range by default.

PS You could probably combine _shift_direction and _reverse_direction into one parameter, which would lower the parameter count to magic 10.

brick_width>0
brick_height>0
_mortar_width>0
_mortar_height>0
_sublevel>=0
_bevel>=0
_outline>=0
_style={ 0=Round | 1=Inverse Round | 2=Diamond }
-1>=_shift>=1
_shift_direction={ 0=Horizontal | 1=Vertical }
_reverse_direction={ 0=No | 1=Yes }
1 Like

I have news, I think I"m going to be back on Construction Material Texture. But, however, is there any buggy filter I should know about? I know I should fix some of the palettes in my reduced transfer filter. The OOBS filter is not something I care too much about for now, that’s very low on my priority. And yes, modulo filter needs a upgrade too.


Post as of 10/26/2019

Why is this not working at all for images with 4 channels?

@afre Can you confirm there’s a issue? It works for 3 and 2 channels. But not 4.

repeat $! l[$>]
    round
    ss={s}
    s c
    repeat $ss-1 <<[$>] {($ss-1)*8-$>*8} done
    +
    repeat $ss-1 [0] done
    repeat $ss >>[$>] {($ss-1)*8-$>*8} &[$>] 255 done
    a c
endl done

It depends on what you mean by doesn’t work. What is different about 2-3 channels vs 4? I typically don’t have 4 channel images handy.

The difference is that the result is the same as the initial image assuming 8I Images. When it comes to 4th channel, it doesn’t seem to work. The result is different there for some reason even though the output from RRRGGGBBBAAA is suppose to be exactly (RRR,GGG,BBB,AAA)