Reptorian G'MIC Filters

They’re identical, but for defined shapes case, rep_form_pixel is at least 3-8 times faster. If I could send image to variable, the image as shape reference case would be faster for rep_form_pixel than _rep_form_pixel.

If I am getting you right, you mean to say that defined shapes currently run faster using the apply_parallel command, and you want the same to be the case for an arbitrary image pair.

Yes, that is what I want to solve.

Have you tried changing the format of the image? E.g., (…) form as I guess-suggested? I don’t quite know which format the defined shapes are in… You probably know enough C(++) code to dig into CImg and G’MIC.

The issue been solved. Now I have finished and made a pull request on gmic-community.

Here’s a picture to go with it -

Process with polygon as shape tile on HSL colour space.

2 Likes

Another filter is in work. Here’s the code for playing around with this filter.

offset_x=0
offset_y=-0*-1
mode=0; #HARD;MEDIUM;SOFT;DESTROY#
{w},{h},100%,4,0
#Formula creates the basic donut#
f. "
ang=110;
ang=pi*(ang/180);
r=max(w,h)/min(w,h);
xx=((x/w-.5)*2)*(w>h?r:1);
yy=((y/h-.5)*2)*(h>w?r:1);
sph=sqrt(xx^2+yy^2);
mv1_sph=1;
mv2_sph=.4;
max_val_sph=max(mv1_sph,mv2_sph);
min_val_sph=min(mv1_sph,mv2_sph);
sph_bnd=sph>max_val_sph||sph<min_val_sph?0:1;
nv_sph=((1/((max_val_sph-min_val_sph)/1))*(sph-max_val_sph)+max_val_sph);
nv_sph-=.5;
nv_sph=cos(nv_sph*pi)*sph_bnd;
XX=xx*cos(ang)-yy*sin(ang);
YY=xx*sin(ang)+yy*cos(ang);
xx=XX;
yy=YY;
xx/=2*(w>h?r:1);
yy/=2*(h>w?r:1);
xx+=.5;
yy+=.5;
[nv_sph,sph_bnd,xx,yy];
"
shift. {($offset_x*100)/2}%,{($offset_y*100)/2}%
f.. "
donut_x=i2#-1+"$offset_x"/2;
donut_y=i3#-1+"$offset_y"/2;
donut_opacity=i1#-1;
donut_depth=i0#-1;
xx=(x/w);
yy=(y/h);
donut_xx=donut_opacity>0?donut_x:xx;
donut_yy=donut_opacity>0?donut_y:yy;
xx=donut_xx*donut_depth+xx*(1-donut_depth);
yy=donut_yy*donut_depth+yy*(1-donut_depth);
i(xx*w,yy*h,z,c,2,3);
"
k..

@afre I’m wondering something. Is it possible to generate non-existent color noises based on absolute integer value? I could do a script to test values and if passed, then color doesn’t exist and proceed to make it. This idea comes from pdn forum in which a member wanted to see if it is possible to automatically create non-existent color noises.

I’m thinking of using store and restore command to do this, but my idea with eq and compose_channels, I’d imagine it would be super slow.

Here’s a slow command that separates all the pixels, and then convert them to color.

s y s x remove_duplicates a x

Extended version

if w>1 s x fi if h>1 s y fi remove_duplicates a x
ww=w
repeat=15
rn=0
equality=0
alpha=0
if !$alpha to_rgb fi
do
do
chan_v1={round(u(0,255))}
chan_v2={round(u(0,255))}
chan_v3={round(u(0,255))}
chan_v4={round(u(0,255))}
{w},{h},100%,100%,$alpha?[$chan_v1,$chan_v2,$chan_v3,$chan_v4]:[$chan_v1,$chan_v2,$chan_v3]
+eq
equality={iM#-1} rm. r. 1,1
if !$equality a x else rm. fi
while $equality
rn+=1
while $rn<$repeat

I found some time to reply. Hope it helps.

By non-existent, do you mean for the entire image or for a given region (e.g., 1 or more pixels)? Depending on your criterion, you would need to approach it differently.

It would be more efficient if you could use builtin commands. colormap 0 would help you index all of the colours in an image. Then generate noise that contains colours that don’t belong to this index.

1 Like

I’m looking at trying to change my rep_frblur to use a better algorithm. The main problem is that blend alpha don’t really work on 5 channels and it’s hard to modify it so that it can work with CMYKA. Any idea where to start with? As of now, it is problematic because if I set duplicates to 200, there can be erm, issues. blend alpha doesn’t even give the same result.

I have a idea on using store image to do the job. Maybe that should give me a better result here.

First of all, you need to know what blend alpha does. It is the base blend with a parameter that controls how much A you get on top of B. You could easily do that yourself in G’MIC, Krita or GIMP.

I figured how it works. I have this proof of concept code which can be copied and pasted all over again. Source Over blending mode.

sh[-2,-1] 0,{s-2}
sh[-4,-3] {s-1}
#/[-2,-1] 255#
f[-4] "i*i0#-2*i0#-1+i*(1-i0#-1)+i#-3*(1-i0#-2)"
f[-2] "i*i#-1+i*(1-i#-1)+i#-1*(1-i)"
#*[-2] 255#
rm[-5--1]

Now, here’s something that makes me really confused.

#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.05
duplicates=5
incremental_angle={360/$duplicates}
impose={1?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
    restore fragment
    rep_sdaxy. $dist_hypo,{$initial_angle+$nn*$incremental_angle},2,1
    sh[0,1] 0,{s-2}
    sh[0,1] {s-1}
endl done

With that code, I noticed the last 2 “layers” (they’re not really layers as they’re shared) are not in 0,1 range. And yet, if I removed the part below fragment and use s c,-3 , I would note that the last channel is 0-1. So, did I ended up with a bug?

EDIT: Ok, last time I checked, {s-1} means last channel because of 0,1,2,3 in case of 4 channels image. Now, I fixed it by putting {s} instead. Now, I’m really confused as to why is this happening.

Are you getting any shared related errors? It won’t work in some cases such as with local and perhaps store. I don’t use shared much for that reason; it might not be stable. I would use it only on mature filters.

Nope. I’m just confused by the fact that I had to do {s} instead of {s-1}. 4 is outside of 0-3 range.

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 - https://forums.getpaint.net/topic/14969-introducing-mosaic-maniac-collage-paint-plugin/

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