Reptorian G'MIC Filters

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

When you finish this would there be a way to add custom functions and/or maps for the gravity to follow?

Well, I consider it finished right now despite the bugs as I can’t solve them, but it works for the most part.

But, theoretically, it is doable. The way the current version of the filter works is using rectangular-polar transformation, and g’mic supports curves. So, if you figure out how to create a curve and make a shape out of it, and then find the point perpendicular to each end. But, that’s a bit complicated.

The other solution is to use a layer as a aid, and then erase based on the information found from the reference layer. Kind of a guide layer. If you can find the weighted center based on the reference layer. You can have the filter automatically find the point. I supposed I can use a pass argument to do this.

@Joan_Rake1 is getting restless. :slight_smile:
Me awaiting for the next creation. :crossed_fingers:

There will be only bug fixes for now and code refactoring. I think you noticed I have added const recently. I decided to focus back on Krita development.

At most, I will add neumann shifting to the tiler tool and grid option to tileset window.

If I feel like it, I’ll make a way to generate isometric tiles from image(s).

Why is this error showing up? Debug tells me zilch.

Operator '=': Invalid name specified for argument 1 when defining macro 'orddith()', in expression '... ); orddith(8ipx,cc,coefcount,ditherpattern)=int((((cc-1)*c(...)...'.```
#@cli rep_lpasc_ordith: 'eq to. rep_loupasc_ordered_dithered' : (+)
rep_lpasc_ordith: rep_loupasc_ordered_dithered $*
#@cli rep_loupasc_ordered_dithered : _dither_method={ 0=checkerboard | 1=dispersed | 2=arcade | 3=ordered | 4=lines | 5=custom | 6=rand }, _palette={ 0=Binary | 1= EGA | 2= Web-safe | 3=12-bit }
#@cli: Color reduction with dithering using algorithm provided by Pascal Ollive.
rep_loupasc_ordered_dithered:
f "begin(
    color_count=[2,4,6,16];
    custom_matrix=[34,14,3,22,6,27,21,8,26,13,30,1,29,18,33,5,20,12,9,0,19,28,10,32,16,31,7,17,2,25,4,24,15,35,23,11];
    line_matrix=[8,9,6,7,1,0,3,2,4,5,9,8,2,3,0,1,4,5,7,6,1,0,3,2,4,5,8,9,6,7,0,1,4,5,7,6,9,8,2,3,4,5,8,9,6,7,1,0,3,2,7,6,9,8,2,3,0,1,4,5,6,7,1,0,3,2,4,5,8,9,2,3,0,1,4,5,7,6,9,8,3,2,4,5,8,9,6,7,1,0,4,5,7,6,9,8,2,3,0,1];
    mat_rev(n)=(
        n = int(n);
        n = (n & 0x55555555) << 1 | (n >> 1) & 0x55555555;
        n = (n & 0x33333333) << 2 | (n >> 2) & 0x33333333;
        n = (n & 0x0f0f0f0f) << 4 | (n >> 4) & 0x0f0f0f0f;
        n = (n << 24) | ((n & 0xff00) << 8) | ((n >> 8) & 0xff00) | (n >> 24);
    );
    orddith(8ipx,cc,coefcount,ditherpattern)=int((((cc-1)*coefcount+1)*8ipx+255*ditherpattern-1)/(255*coefcount));
    randdit(8ipx,cc,nx,ny)=(
        sd=(mat_rev(ny)>>23)<<22|mat_rev(nx)>>10;
        ditp=(48271*sd)%2147483647;
    );
    if($1==0,appdit(8ipx,cc,nx,ny)=orddith(8ipx,cc,2,xor(nx,ny)&0x1);,
    if($1==1,appdit(8ipx,cc,nx,ny)=orddith(8ipx,cc,4,((xor(nx,ny)&0x1)<<1)|(ny&0x1)),
    if($1==2,appdit(8ipx,cc,nx,ny)=orddith(8ipx,cc,8,2+(ny&0x3));,
    if($1==3,appdit(8ipx,cc,nx,ny)=orddith(8ipx,cc,5,line_matrix[20*(ny%5)+2*(nx%5)]>>1);,
    if($1==4,appdit(8ipx,cc,nx,ny)=orddith(8ipx,cc,10,line_matrix[10*(ny%10)+(nx%10)]);,
    if($1==5,appdit(8ipx,cc,nx,ny)=orddith(8ipx,cc,36,custom_matrix[6*(ny%6)+(nx%6)]);,
             appdit(8ipx,cc,nx,ny)=randdit(8ipx,cc,nx,ny);
    );
    );
    );
    );
    );
    );
    const cc=color_count[$2];
    const cs=255/(cc-1);
);
appdit(i,cc,x,y);
"

A variable name cannot start with a number.

1 Like