Reptorian G'MIC Filters

The code is available, why not give it a go yourself? :slight_smile:

2 Likes

I don’t know how to code GMIC.

Honestly, what you are asking there represents a huge amount of work.
Unless we can be funded for this, I’m afraid it’ll never happen.

I’ve done some fixes on da, should be available hopefully in less than 1 hour :wink:

I wouldn’t exactly say it’ll never happen, but it’s unlikely. I can definitely do it, but it would take me months to know how it would work. Looking at the relevant part of the github project, it looks like a 4 to 6 month job for one-man. The palette transfer alone was a replica of an android software, and that was a 3-4 months job.

Right now, as months job to look at, there are more relevant things to look at. For example, Pixel Art Scaling, and I have only done a few of them. I would need to know how they work exactly in order to emulate the exact expected behavior. I don’t know how pixel art algorithm that interpolate pixels work exactly yet, and I lack understanding of even more complicated algorithm that does more than interpolation. But, the basics are covered which would be simple ones like SCALE series and EAGLE. SCALE2X,SCALE3X,EAGLE are done by me and @garagecoder , my version is based on vector comparison and his is based on channel comparison.


EDIT: I now feel like at a point where I am now on a break from making G’MIC filters. So, If anyone wants to edit my filter or improve on it, please contact me so I can test it, and if it’ll all good, I’ll post it up. I’ll just be leaving some things here again for any one that wants to know what I was up to.

gmic collection note.zip (5.2 KB)

**EDIT:**Removed earlier comment as it’s no longer relevant.

@afre @David_Tschumperle

Why am I getting weird result when interpolation is 4? It’s not like I can’t find a workaround to this. But I would like to know why.

Interpolation is 4 in this picture, what do you see wrong in this picture?

image

rep_st .5,4,-.5,1,40,1,.5,.5,0,50%,-25%,2,2,.5,-.5,2,4

#@cli rep_st: (eq. to rep_spiral_transform)
rep_st: rep_spiral_transform $*
#@cli rep_spiral_transform: _frequency,_height,_refraction,_direction,_angle,_continuous_spiral,_preshift_x,_preshift_y,_preshift_boundary,_skew_x,_skew_y,_scale_coord_x,_scale_coord_y,_offx,_offy,_spiral_boundary,_interpolation
#@cli : Transform images into spiral by using spiral gradient for x coordinate, and radial gradient for y coordinate.\n
#@cli : '_frequency' defines the number of revolution within the spiral
#@cli : '_height' is the height of spiral.
#@cli : '_refraction' refers to the logarithmic distortion within spiral.
#@cli : '_direction' determines if it clockwise or counter-clockwise.
#@cli : '_angle' determines the function angle.
#@cli : '_continuous_spiral' determines whether the spiral transformation is continuous or not.
#@cli : '_preshift_x' shifts the images before the spiral transform along the x-axis.
#@cli : '_preshift_y' shifts the image before the spiral transform along the y-axis.
#@cli : '_preshift_boundary' determines the boundary within the preliminary shift.
#@cli : '_skew_x' skews the distortion alongside the x-axis.
#@cli : '_skew_y' skews the distortion alongside the y-axis.
#@cli : '_scale_x' scales the coordinates alongside the x-axis.
#@cli : '_scale_y' scales the coordinates alongside the y-axis.
#@cli : '_offx' determines the offset-placement of the distortion alongside the x-axis.
#@cli : '_offy' determines the offset-placement of the distortion alongside the y-axis.
#@cli : '_spiral_boundary' determines the out-of-bound values is to be treated.
#@cli : '_interpolation' determines the interpolation of the spiral transform.
#@cli : Author: Reptorian.
#@cli : Default values: '_frequency=1','_height=1','_refraction=0','_direction=0','_angle=0','_continuous_spiral=0','_preshift_boundary=0','_skew_x=0','_skew_y=0','_scale_x=1','_scale_y=1','_offx=0','_offy=0','_spiral_boundary=3','_interpolation=3'
rep_spiral_transform:
skip ${1=1},${2=1},${3=0},${4=0},${5=0},${6=0},${7=0},${8=0},${9=0},${10=0},${11=0},${12=1},${13=1},${14=0},${15=0},${16=3},${17=3}
if abs($17)>1 r2dx 200%,{abs($17)} fi
f "begin(offx=(w/2)*$7*-1;offy=(h/2)*$8;interpolation=abs($17)>2?2:abs($17);boundary=($9+2););
i(x+offx,y+offy,z,c,interpolation,boundary);
"
f "begin(
    sd=max(w,h)/min(w,h);
    sx=w>h?sd:1;
    sy=w>h?1:sd;
    ang=pi*(($5*-1)/180);
    skew_x=$10/2;
    skew_y=$11/2;
    offx=-.5+($14/2*-1);
    offy=-.5+($15/2);
    nw=abs(w*sin(ang))+abs(h*cos(ang));
    nh=abs(w*cos(ang))+abs(h*sin(ang));
    rot_x(a,b)=a*cos(ang)-b*sin(ang);
    rot_y(a,b)=a*sin(ang)+b*cos(ang);
    interpolation=abs($17)>2?2:abs($17);
    boundary=$16;
);
xx=(x/w+offx)*sx;
yy=(y/h+offy)*sy;
mx=((rot_x(xx,yy)/sx)+.5)*w;
my=((rot_y(xx,yy)/sy)+.5)*h;
nx=mx-abs(skew_x)*rot_x(xx,yy)*(skew_x>0?nw-mx:mx);
ny=my-abs(skew_y)*rot_y(xx,yy)*(skew_y>0?nh-my:my);
xx=(nx/w-.5)*2*$12*sx;
yy=(ny/h-.5)*2*$13*sy;
radial=sqrt(xx^2+yy^2);
if($4,sur_atan=1-(atan2(xx,yy)+pi)/(2*pi);,sur_atan=(atan2(xx,yy)+pi)/(2*pi););
es=(sur_atan+radial*$1)*$2;
es=es-floor(es);
if($6,es=(es>.5?1-es:es)*2;);
i((es^(1+$3))*w,radial*h,z,c,interpolation,boundary);
"
if abs($17)>1 r2dx 50%,{abs($17)} fi

Easy. This is what 4=grid does.

Oh. I never seen that before. Ok, guess I’ll have to add more text to make sure 4 is not used.

Just don’t make the option possible.

New Filter Spiral Distort.


This was inspired by Xhin’s ‘Self Spiral’ made for Paint.NET , so I decided to make my own version.

It’s a slightly more flexible version of Xhin’s plugin if we’re going to compare by features rather than the underlying mathematics. For example, he created the skewing feature by adding into coordinate from the x,y pixel location while my skewing feature use -1,1 range and multiply within a exponential expression. The exponential enables you to alter the degree of distortion within skewing. And then, this one gives you the option to alter other variables that aren’t found in Xhin’s version like the height of spiral and/or the refraction based on exponential. You can use Lanczos interpolation, and that gives clean result.

CLI Information:

#@cli rep_sd: (eq. to rep_spiral_distort)
rep_sd: rep_spiral_distort $*
#@cli rep_spiral_distort: _revolution!=0,_height!=0,_refraction>0,_direction={ 0=clockwise | 1=counterclockwise },_angle,_continuous_spiral={ 0=periodic | 1=continuous },-1<=_preshift_x<=1,-1<=_preshift_y<=1,_preshift_boundary={ 0=periodic | 1=mirror },_skew_x,_skew_y,_skew_m,_scale_coord_x,_scale_coord_y,_offx,_offy,_spiral_boundary={ 0=none | 1=neumann | 2=periodic | 3=mirror },_interpolation={ 0=nearest | 1=average | 2=linear | 3=bicubic | 4=lanczos }
#@cli : Transform images into spiral by using spiral gradient for x coordinate, and radial gradient for y coordinate.\n
#@cli : '_revolution' defines the number of revolution within the spiral assuming coordinates range of [-1,1].
#@cli : '_height' is the height of spiral. The higher the height of the spiral, the more duplicates will repeat within one revolution.
#@cli : '_refraction' refers to the logarithmic distortion within spiral.
#@cli : '_direction' determines if it clockwise or counter-clockwise.
#@cli : '_angle' determines the function angle.
#@cli : '_continuous_spiral' determines whether the spiral distortion is continuous or not.
#@cli : '_preshift_x' shifts the images before the spiral distortion along the x-axis.
#@cli : '_preshift_y' shifts the image before the spiral distortion along the y-axis.
#@cli : '_preshift_boundary' determines the boundary within the preliminary shift.
#@cli : '_skew_x' skews the distortion alongside the x-axis. It is recommended to keep ranges to -100% to 100%.
#@cli : '_skew_y' skews the distortion alongside the y-axis. It is recommended to keep ranges to -100% to 100%.
#@cli : '_skew_m' is the multiplier for skewing.
#@cli : '_scale_x' scales the coordinates alongside the x-axis.
#@cli : '_scale_y' scales the coordinates alongside the y-axis.
#@cli : '_offx' determines the offset-placement of the distortion alongside the x-axis. It is recommended to keep ranges to -100% to 100%.
#@cli : '_offy' determines the offset-placement of the distortion alongside the y-axis. It is recommended to keep ranges to -100% to 100%.
#@cli : '_spiral_boundary' determines how the out-of-bound values is to be evaluated.
#@cli : '_interpolation' determines the interpolation of the spiral distortion.\n
#@cli : Default values: '_frequency=1','_height=1','_refraction=0','_direction=0','_angle=0','_continuous_spiral=0','_preshift_x=0','_preshift_y=0','_preshift_boundary=0','_skew_x=0','_skew_y=0','_skew_m=1','_scale_x=1','_scale_y=1','_offx=0','_offy=0','_spiral_boundary=3','_interpolation=4'\n
1 Like

Released two new cli commands. rep_polrectrans and rep_polrectrans_inv. I also have fixed so many cli commands.

What’s the purpose of these filters? The main purpose is enable recreating perspective. That’s why I have made these filters. The next part of that is on the pull request. For a preview on what these do.

$ sp lena rep_polrectrans_inv 0,0,1

image

EDIT: This is actually the inverse of polar rectangular coordinates. So, I swapped the cli names.

Picture a line. That’s your scanning line. The scanning line length depends on distance to edge. Now rotate it around the center. This is what you’re going to get. Also, the point of scanning revolution can be changed, and that’s what you’re going to get.


EDIT: No longer on the roadblock! Though it had to be asked, should this be own effect?

image

That you see above is made with the aid of my own streak filter. It takes opacity into account though it only works by axis.


@afre

This is the thing I wanted to do. It was difficult, but I’m about to solve it.

isophotes 3
rep_recpoltrans 0,0,-3
+rep_axis_streak_distance 1,1
rep_axis_streak.. 1,1
*.. .
rm.
rep_recpoltrans 0,0,2,0

After I finish up this filter, I will release it.

1 Like

Must say that is pretty neat. Reminds me pixel sort but toward a point on the canvas.

1 Like

Finally, I am finished with the perspective streak filter! Hoorah! Released into PR!

700+ line change just to make this possible.

Sample picture

image


Another new update. modf or modular_formula received a big boost in usability.

@afre Thank you so much for making this happen!


Now, I’m working on trying to solve this filter - Gossamer - released 10/02/2015 - Plugins - Publishing ONLY! - paint.net Forum

To do that, I’m writing macros involving finding coordinates, number of alphas that is not equal to 0, and searching based on radius. After that, the writing of that filter gets a lot easier. As G’MIC supports the 3rd dimension, it’s even possible to write the 3d version of that filter.

EDIT:
Just finished on number of non-zero alpha.

EDIT as of 6:12 at 12/12/2019:
Now, I was able to extract coordinates. Now, I’m going to need to find a way to search by radius in 3-dimensions.

#@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)
"}

EDIT: Thanks to @afre advice about avoiding as much loop as possible. I came up with these as an ongoing solution to replicating that very difficult PDN filter (It doesn’t help that I been rejected to have the source code, so I have to do this myself).

#@cli rep_sphere_search_coords: radius,exception={ 0=exclude_zero_coords | 1=include_zero_coords }
#@cli : Return coordinates values within radius.
rep_sphere_search_coords:
skip ${2=0}
if $!!=1 error "Only one image is accepted!" fi
nw={min($1,w#-1)}
nh={min($1,h#-1)}
nd={min($1,d#-1)}
val={$1+((1-($1%2))*2)}
$val,$val,$val,4,"
    hw=int(w/2);
    hh=int(h/2);
    hd=int(d/2);
    xd=((x/(w-1))-.5)*2;
    yd=((y/(h-1))-.5)*2;
    zd=((z/(d-1))-.5)*2;
    dist=(sqrt(sum(xd^2+yd^2+zd^2))<=1?1:0);
    nx=x-hw;ny=y-hh;nz=z-hd;
    [nx,ny,nz,dist];
"
if 1-($1%2) shrink_xyz. 1 fi
r. $nw,$nh,$nd,4,0,0,.5,.5,.5
sh. {s-1}
if !$2 f. x==int(w/2)&&y==int(h/2)&&z==int(d/2)?0:i fi
total_area={is#-1} total_area*=3 rm.
u {"rel_coords=vector"$total_area"(0);pos=0;
for(pz=0,pz<d#-1,pz++,
    for(py=0,py<w#-1,py++,
        for(px=0,px<h#-1,px++,
            if(i(#-1,px,py,pz,3),
                rel_coords[pos*3]=px-int(w#-1/2);
                rel_coords[pos*3+1]=py-int(h#-1/2);
                rel_coords[pos*3+2]=pz-int(d#-1/2);
                pos++;
            );
        );
    );
);
(rel_coords)
"}
rm.
#@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 coordinates of non-zero alpha of selected images.
#@cli : (eq. to 'rep_n0_alp_coords').
rep_nonzero_alpha_coordinates:
imgs={$!}
1,1,1,1
eval ${-math_lib}"
for(img=0,img<"$imgs",img++,
    alpc=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,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.

My next step is to first create a basic filter that creates line using a point as connector. After that, I would need to convert the image into series of dots. Finally, loop the connections using found coordinates. I’m golden from there.

1 Like

I have added Projects to my g’mic-community fork. I’ll put things to do there.


@bazza Does Autofill Coloring Book crash with you using this image?

1 Like

images as an example?

No, just confirming if the image crash G’MIC. @nrcarla reported that the image crash Autofill Coloring Book. I wonder if it also crash one of the Colorize made by @David_Tschumperle which is similar to Autofill Coloring Book on @nrcarla end.

This image works well.

Checked with several builds, it was crashing on that single build.
I built that again and now the filter seems to be working perfectly.
Sorry for the false alarm.

1 Like
repeat $! l[$>]
    +to_gray /. 5
    f.. "begin(val=0;);
    off=abs(round(i(#-1,x,y,z,0)));
    if(off,
    for(xx=off*-1,xx<=off,xx++,
        for(yy=off*-1,yy<=off,yy++,
            val+=j(xx,yy,0,0,0,1);
        );
    );
    val/=sqr(off*2+1);,i
    );
    "
    rm.
endl done

Made this command which average blur depending on pixel values. Is anyone interested in this? I didn’t use crop here because I don’t see boundary condition, and strictly positive only.

A box filter with per pixel kernel size? Hmm I wonder if there’s a quicker way…
By the way, is that correct to only set val=0 for the first pixel?