Reptorian G'MIC Filters

Outside of my wheelhouse of course. I doubt G’MIC or apps in general have that level of control…

So, in other words, this is the best it’s going to get. It’s fast in most use-case, but if I open a existing image with less than 1000000 colors and use existing colors option when applying color existence distribution filter, then run this, it takes over 30 mins just to finish. By the way, I have even more idea on top of this.

There should be more efficient ways or ways to approximate the process. But in terms of what you are asking (controlling which operations happen on specified threads and in specified orders), seems like sophisticated stuff (I am not a programmer) and more work than the command would warrant.

The problem here is that I don’t see a faster way of doing this. The code is basically compressing pixels ignoring pixels with alpha value of zero. One sentence, pretty complicated problem.

Right now, I suspect many of your commands are brute force, which is okay if the goal is to determine whether your ideas actually work but the challenge is to do things smarter. Easier said than done. But if it takes 30 mins on your machine, mine would explode in 10 secs.

I’m thinking apply_tiles will do the job.
@David_Tschumperle
Does this do what I want?
I’m thinking that there should be way to run the command on each thread with row number or column number corresponding with the thread number as in if the row number or column number modulus thread number is equal to 0.

If you ask me I think that using apply_tiles won’t do what you want since that divides up the image into tiles and only applies things within those tiles before stitching them back together. One thing that you could do instead is take inspiration from powder simulation games. They have physics engines which after a few hundred iterations manage to do almost exactly what you’re thinking of.

@afre @David_Tschumperle @Joan_Rake1

I discovered a insanely fast algorithm. Instead of the result being 30 mins in the odd case of color existence distribution table containing 100000 colors, this takes 2 seconds!

ss={s-1}
f "i(x,y,z,"$ss")>128?i:0"
{w},{h},1,1,i(#-1,x,y,0,$ss)?1
{w},1,1,1,sum(crop(#-1,x,0,0,0,1,h#-1,1,1))
{w#-2},{h#-2},1,{$ss+1}

eval ${-math_lib}"
for(xx=0,xx<w#-1,xx++,
    nyy=h#-1-1;
    if(i(#-2,xx,0),
        N=i(#-2,xx,0);
        tyy=h#-1-N;
        tyy*=1;
        for(yy=h#-1-1,yy>-1,yy--,
            if(N,
                if(i(#-3,xx,yy),
                    N--;
                    I(#-1,xx,nyy-tyy)=I(#-4,xx,yy);
                    nyy--;
                );
            ,break();
            );
        );
    );
);
"
k.
2 Likes

Nice! There are at least 2 less dos. The less loopy loops, the less labouring. :slight_smile:

I have pushed rep_primelist cli and rep_prime_surface (The algorithm is slow, but miles faster than the earlier one), better version of Grouped Pixels Shift filter, some undeveloped cli only pushed there for development purpose and backup.


2/10/2020

Object Size Filtering has been upgraded. It’s a bit harder to use now, but also far more flexible

Other details:

  1. I fixed descriptor for Nebulous

  2. I have added credits to @Asmageddon Prince in Logarithmic Distortion series.


2/22/2020

Rewrite of Object Size Filtering GUI again. I think there exists dynamic gui issue on the auto side of things because of alpha threshold. It’ll do for now.


2/25/2020

Small new feature added to Glass Vignette - Len Size (%)

All this does is change the size of len distortion. Now the extension of TechnoRobbo’s PDN Glass Vignette is completed. I wanted to do this for a while.


2/26/2020

3 New Filters

  1. Point Warp
  2. Prime Surface
  3. Pixel Push

2/27/2020

I am now working on the donut distortion filter again! Literally! I am a bit closer to doing it. I looked at cos graph to figure out the variety of modes in here by finding the relationship between y and x location using pi as base. - Donut distortion Effect Plugin - Plugins - Publishing ONLY! - paint.net Forum .

EDIT: New Code. This one actually supports relative coordinate. So, now you can place the distortion elsewhere by editing shift.

#$1=_torus_circu_min_dimension_percent_1#
#$2=_torus_circu_min_dimension_percent_2#
#$3=_mode_1#
#$4=_mode_2#
#$5=_mode_percent_comb#
#$6=_offset#
#$7=_offset_duplicates#
#$8=_interpolation#
#$9=_boundary#
#$10=_eff_mix#

{w*2},{h*2},1,1,"
    begin(
    ww=w-1;
    hh=h-1;
    sd=max(w,h)/min(w,h);
    sx=w>h?sd:1;
    sy=w>h?1:sd;
    torus_val_1=.85;
    torus_val_2=.05;
    new_min=min(torus_val_1,torus_val_2);
    new_max=max(torus_val_1,torus_val_2);
    old_max=max(1,0);
    old_min=min(1,0);
    nm(v)=((old_max-old_min)/(new_max-new_min))*(v-new_max)+new_max;
    oldcut(v)=v>old_max?old_max:(v<old_min?old_min:v);
    bndcut(v)=v>old_max||v<old_min?0:1;
);
xx=(x/ww-.5)*2*sx;
yy=(y/hh-.5)*2*sy;
radial_gradient=sqrt(xx^2+yy^2);
[oldcut(nm(radial_gradient)),bndcut(nm(radial_gradient))];
"

r2dx. 50%,3
r. 100%,100%,100%,2

f. "begin(
    dist=min(w,h)/2;
    sd=max(w,h)/min(w,h);
    sx=w>h?sd:1;
    sy=w>h?1:sd;
    ww=w-1;
    hh=h-1;
    max_ang=20;
    max_ang*=-1;
    ang2rad(v)=pi*(v/180);
    rot_x(a,b,c)=a*cos(ang2rad(c))-b*sin(ang2rad(c));
    rot_y(a,b,c)=a*sin(ang2rad(c))+b*cos(ang2rad(c));
    softmode(v)=(cos(v*(2*pi)-pi)+1)/2;
    midmode(v)=abs(cos(v*pi+pi/2));
    hardmode(v)=sqrt(1-(abs(v-.5)*2)^2);
    distroymode(v)=cos(v*pi)*i1;
    invdistroymode(v)=(cos(v*pi)*-1)*i1;
    quadextrudemode(v)=1-abs(v-.5)*2;
    hexextrudemode(v)=(r=(1-abs(v-.5)*2)*2;r>1?1:r);
);
z_depth=hexextrudemode(i0)*max_ang;
xx=(x/ww-.5)*2*sx;
yy=(y/hh-.5)*2*sy;
XX=rot_x(xx,yy,z_depth);
YY=rot_y(xx,yy,z_depth);
XX/=2*sx;
YY/=2*sy;
XX+=.5;
YY+=.5;
XX*=ww;
YY*=hh;
[x-XX,y-YY]
"

shift. 0%,0%,0,0,2,1

f[^-1] "i(x-i(#-1,x,y,z,0),y-i(#-1,x,y,z,1),z,c,1,3)"
rm.

2/29/2020

New filter released! Donut Distortion

EDIT: It’s now Rotate By Torus Map

2 Likes

@garagecoder I think I have discovered the secret of your warp filter.

channels 0
f "
xx=x/w-.5;
yy=y/h-.5;
xx*=2;yy*=2;
1-sqrt(xx^2+yy^2);
"
f "
vert_top=i+j(0,-1,z,c,0,1);
vert_bottom=i+j(0,1,z,c,0,1);
vert=vert_bottom-vert_top;
land_top=i+j(-1,0,z,c,0,1);
land_bottom=i+j(1,0,z,c,0,1);
land=land_top-land_bottom;
((atan2(land,-vert)+pi)/(2*pi))*255;
"

The result looks good too. I see the direction in which the slope is going. So, I think I can make my own warp filters. This is my own approach where I wanted the center pixel to be factored in.

The Rotate by Torus Top filter I have made on top of this finding did made me realize that I can make plugins such as Squirkle Warp for Paint.NET as well as clipboard warp filter.

Try making a Lensball Springrimw. :wink:

I’m working on a new filter - Based off TechnoRobbo’s Strange Attractor

image

Sadly, I don’t get results like these so often. So, I believe I would need to implement an auto redo system here.

srand 2353252
max_width=${-max_w}
max_height=${-max_h}
$max_width,$max_height,1,1
Algo=4

eval ${-math_lib}"
Density=5;
interpolate(a,b)=a*-b+(1-a)*b;

cenx="$max_width"/2;
ceny="$max_height"/2;

xc=0;
yc=0;
zc=0;

Amount=vector9(u(0,1),u(0,1),u(0,1),u(0,1),u(0,1),u(0,1),u(0,1),u(0,1),u(0,1));

ap="$Algo";

if(ap<=4,
    a=interpolate(Amount[0],3);
    b=interpolate(Amount[1],3);
    
    if(ap!=3&&ap<4,
        c=interpolate(Amount[2],3);
        d=interpolate(Amount[3],3);
    ,
        e=interpolate(Amount[4],3);
        f=interpolate(Amount[5],3);
    );
    
    if(ap<2,xc=.5;yc=.5;,
    if(ap==2,xc=-1;
    );
    );
,
    if(ap==5,
        a=interpolate(Amount[0],2);
        b=interpolate(Amount[1],2);
        c=interpolate(Amount[2],2);
        d=interpolate(Amount[3],2);
        e=interpolate(Amount[4],2);
        f=interpolate(Amount[5],2);
        g=interpolate(Amount[6],2);
        h=interpolate(Amount[7],2);
        i=interpolate(Amount[8],2);
        ,
        a=interpolate(Amount[0],3);
        b=interpolate(Amount[1],3);
        c=interpolate(Amount[2],3);
        d=interpolate(Amount[3],3);
        e=interpolate(Amount[4],3);
        f=interpolate(Amount[5],3);
    );
);

if(ap==0,
    xnf(coordx,coordy)=sin(coordy*b)+c*sin(b*coordx);
    ynf(coordx,coordy)=sin(a*coordx)+d*sin(a*coordy);,
if(ap==1,
    xnf(coordx,coordy)=sin(coordy*a)+cos(c*coordx);
    ynf(coordx,coordy)=sin(c*coordx)-cos(d*coordy);,
if(ap==2,
    xnf(coordx,coordy)=abs(sin(coordy*a)^3)+cos(c*coordx);
    ynf(coordx,coordy)=abs(sin(c*coordx)^2)-cos(d*coordy)^2;,
if(ap==3,
    xnf(coordx,coordy)=sin(coordy*a)+cos(a*coordx);
    ynf(coordx,coordy)=sin(b*coordx)-cos(b*coordy);,
if(ap==4,
    xnf(coordx,coordy,coordz)=coordz*sin(a*coordx)-cos(b*coordy);
    ynf(coordx,coordy,coordz)=coordx*cos(c*coordy)+sin(d*coordz);
    znf(coordx,coordy,coordz)=coordy*sin(e*coordz)-cos(f*coordy);,
if(ap==5,
    xnf(coordx,coordy,coordz)=coordy*sin(a*coordx)+cos(b*coordy)+sin(c*coordz);
    ynf(coordx,coordy,coordz)=coordz*sin(d*coordx)+cos(e*coordy)+sin(f*coordz);
    znf(coordx,coordy,coordz)=coordx*sin(g*coordx)+cos(h*coordy)+sin(i*coordz);
#if[ap==6#,
    xnf_3d(coordx,coordy,coordz)=coordz*sin(a*coordx)+cos(b*coordy);
    ynf_3d(coordx,coordy,coordz)=coordx*sin(c*coordy)+cos(d*coordz);
    znf_3d(coordx,coordy,coordz)=coordy*sin(e*coordz)+cos(f*coordx);
);
);
);
);
);
);

td=Density*10^6;
mnX=0;
MnX=0;
mnY=0;
MnY=0;

if(ap>3,
    for(n=0,n<td,n++,
        xn=xnf(xc,yc);
        yn=ynf(xc,yc);
        xc=xn;
        yc=yn;
        nX=xn*150+cenx;
        nY=yn*150+ceny;
        if(inrange(nX,0,"$max_width",1)&&inrange(nY,0,"$max_height",1),
            i(#-1,nX,nY,z,0)+=1;
        );
    );
,
    for(n=0,n<td,n++,
        xn=xnf(xc,yc,zc);
        yn=ynf(xc,yc,zc);
        zn=znf(xc,yc,zc);
        xc=xn;
        yc=yn;
        zc=zn;
        nX=xn*200;
        nY=yn*200;
        MnX=max(MnX,nX);
        mnX=min(mnX,nX);
        MnY=max(MnY,nY);
        mnY=min(mnY,nY);
        px=(MnX-mnX)/2;
        py=(MnY-mnY)/2;
        nX+=px;
        nY+=py;
        if(inrange(nX,0,"$max_width",1)&&inrange(nY,0,"$max_height",1),
            i(#-1,nX,nY,z,0)+=1;
        );
    );
);


"
k.
1 Like

Maybe the Wiki entry I linked to earlier (Newton Fractals - #14 by afre) has helpful info…

I’ll have a look at that. I think I will have to try to play around with the formula to see if I can get more consistent result and more of what I’m looking for.

Never mind. I solved it by changing - to +.


I am figuring out how to create color scheme for attractor filter. Might take a while to figure out exactly how to make it.

First create a grayscale gradient. Then, shift the midgray. That’s easy though with the formula provided by the Pixel Pusher filter, but also exponential formula will work just as well. I would also need random colors. The random colors will then have to be mapped to the midgray shifted gray gradient. Finally, assign the coloring to the attractor. I get something like this below.


It seems that I have a possible way to define coloring of attractor fractal.

to_gray

out1=4
out2=2
out3=0

if   $out1==0 col_formula_a="(sin(a*pi)+1)/2";
elif $out1==1 col_formula_a="(cos(a*pi)+1)/2";
elif $out1==2 col_formula_a="(sin(a*pi+pi)^3+1)/2";
elif $out1==3 col_formula_a="(cos(a*pi+pi)^3+1)/2";
elif $out1==4 col_formula_a="((cos(a*pi+pi/2)*sin(a*pi+pi/2))^3+.125)*4";
fi


if   $out2==0 col_formula_b="(sin(a*pi+pi/2)+1)/2";
elif $out2==1 col_formula_b="(cos(a*pi+pi/2)+1)/2";
elif $out2==2 col_formula_b="(sin(a*pi+pi/2)^3+1)/2";
elif $out2==3 col_formula_b="(cos(a*pi+pi/2)^3+1)/2";
elif $out2==4 col_formula_b="((cos(a*pi+pi/4)*sin(a*pi+pi/4))^3+.125)*4";
fi


if   $out3==0 col_formula_c="(sin(a*pi+pi)+1)/2";
elif $out3==1 col_formula_c="(cos(a*pi+pi)+1)/2";
elif $out3==2 col_formula_c="(sin(a*pi)^3+1)/2";
elif $out3==3 col_formula_c="(cos(a*pi)^3+1)/2";
elif $out3==4 col_formula_c="((cos(a*pi)*sin(a*pi))^3+.125)*4";
fi


256,1,1,3,"
begin(
ww=w-1;
hh=h-1;

ch0=100%; mch0=1; vsf0=0; mwl0=1; out1=1; end2col1=0;
ch1=100%; mch1=1; vsf1=0; mwl1=1; out2=2; end2col2=0;
ch2=100%; mch2=1; vsf2=0; mwl2=1; out3=0; end2col3=0;

col_formula_a(a)="$col_formula_a";
col_formula_b(a)="$col_formula_b";
col_formula_c(a)="$col_formula_c";

);
slope=x/ww;

col_chan_zero = col_formula_a( mch0 * (slope^lerp(ch0*(1-slope),1,ch0)+vsf0));
col_chan_one  = col_formula_b( mch1 * (slope^lerp(ch1*(1-slope),1,ch1)+vsf1));
col_chan_two  = col_formula_c( mch2 * (slope^lerp(ch2*(1-slope),1,ch2)+vsf2));

mul_chan_zero = lerp( col_chan_zero , slope * col_chan_zero , mwl0 );
mul_chan_one  = lerp( col_chan_one  , slope * col_chan_one  , mwl1 );
mul_chan_two  = lerp( col_chan_two  , slope * col_chan_two  , mwl1 );

gray2col_zero = lerp( slope , mul_chan_zero , end2col1 );
gray2col_one  = lerp( slope , mul_chan_one  , end2col2 );
gray2col_two  = lerp( slope , mul_chan_two  , end2col3 );
[mul_chan_zero,mul_chan_one,mul_chan_two]

"
map.. . rm.
1 Like

@hover

I have released the Attractor filter. However, I decided to keep it grayscale as coloring is easily doable with 3 main programs that use it (GIMP, Krita, and Paint.NET) while not having much luck with trigonometric mapping.

Here’s a png result of the filter with some bit of trigonometric mapping

strange attractor


@David_Tschumperle I figured it out! This is what I did to make trigonometry filter has sync’d options.

fx_rep_tg3_preview:
cc1,cc2,cc3,cc4,cc5,cc6=$4,$5,$6,$7,$8,$9
cc=[$cc1,$cc2,$cc3,$cc4,$cc5,$cc6]
cc={($cc)[$3]}
cc1,cc2,cc3,cc4,cc5,cc6={[$cc,$cc,$cc,$cc,$cc,$cc]}
gui_split_preview "fx_rep_tg3 ${1-30}",${-3--1}
u "{$1}"\
"{$2}"\
"{$3}"\
"{"$cc1"}_"{$3==0?2:0}\
"{"$cc2"}_"{$3==1?2:0}\
"{"$cc3"}_"{$3==2?2:0}\
"{"$cc4"}_"{$3==3?2:0}\
"{"$cc5"}_"{$3==4?2:0}\
"{"$cc6"}_"{$3==5?2:0}
2 Likes

2 Likes

That’s just beautiful.


RPG Tiler filter V3 has been finished. I have added constants to some of my filters, so hopefully, I didn’t screw anything up.


I am about to fix two of my filters. Picture Mosaic and Stitch. Stitch works, however, I feel that it is not perfect. There is going to be a new posterize filter, but it’s just a fun filter. Picture Mosaic will have better cli support. By the end of this month, I will take a break as tiler filter was pretty long.


I have committed a new upgrade to my own picture mosaic filter.

New Filter - Grouped Pixels Shift By Rectangular Polar Transformation

Note: It’s kinda very buggy right now. Not that it’s hard to get around. :confused:

3 Likes