'Glitch' Art Filters - again

This doesn’t answer on how to use it outside of the math evaluator. I think the answer to @Joan_Rake1 problem requires one to insert a vector within a variable outside of the math evaluator. So that it can be accessible via {($vector)[pos,size]}.

That’s why I tested this below:

run('variable=',vector_inside_math_evaluator);

Yes. This is the problem I have. Here’s the code right now:

dct_tileset:
{$1^2},{$2^2},1,1
f. :"begin(const tw=$1;const th=$2;const stw=sqrt(tw);const sth=sqrt(th);const itw=1/tw;const ith=1/th;const istw=sqrt(itw);const isth=sqrt(ith);const s2=sqrt(2));
px=x%tw;
py=y%th;
tx=(x-(px))*itw;
ty=(y-(py))*ith;
cx=cos((tx*0.5+((tx+0.5)*x*itw))*pi)*istw;
cy=cos((ty*0.5+((ty+0.5)*y*ith))*pi)*isth;
px!=0?(cx*=s2);
py!=0?(cy*=s2);
val=cx*cy;
val;
"

idct_tileset:
{$1^2},{$2^2},1,1
f. :"begin(const tw=$1;const th=$2;const stw=sqrt(tw);const sth=sqrt(th);const itw=1/tw;const ith=1/th;const istw=sqrt(itw);const isth=sqrt(ith);const s2=sqrt(2));
px=x%tw;
py=y%th;
tx=(x-(px))*itw;
ty=(y-(py))*ith;
cx=cos((x+0.5)*tx*pi*itw)*istw;
cy=cos((y+0.5)*ty*pi*ith)*isth;
tx!=0?(cx*=s2);
ty!=0?(cy*=s2);
val=cx*cy;
((tx+ty)%2)?(val*=-1);
val;
"

fx_jpeg :

to_rgb
q=$1
tiledims=[${2-7}]
tnum=0

repeat $3
pos={find(($tiledims)["$>"*2,"$>"*2+1],0,2)*0.5}
if $>==$pos
dct_tileset $tw,$th
idct_tileset $tw,$th
nm[-2,-1] "dct"$pos"","ict"$pos""
tnum[$>]=$pos # ?
else
fi

done

repeat {$!-2} l[$>,dct,idct]
ww={w(#0)}
hh={h(#0)}
r[0] {w(#0)+(-w(#0)%$tw)},{h(#0)+(-h(#0)%$th)},1,100%,0,3

csswap[0] 0,15 s[0] c 

repeat 3
tw={($tiledims)["$>"*2]}
th={($tiledims)["$>"*2+1]}
{w#0},{h#0},{d#0},{s#0}
f[$>] :"
begin_t(const tw="$tw";th="$th";const twh=tw*th;tn="($tnum)"[$>]); # ?
if (!(x%tw) && !(y%th),
res=vector(#twh,0);
ref(crop(x,y,tw,th),src);
for (l = 0, l<th, ++l, for (k = 0, k<tw, ++k,
off = k + tw*l;
res += src[off]*crop(#"$dct"tn"",k*tw,l*th,tw,th,1))); # ?
draw(#-1,res,x,y,0,0,tw,th);
); i"

f. :"begin_t(const qual="$tw"*(1-"$q"*0.01)^3);round(i,qual)"

f. :"
begin_t(const tw="$tw";th="$th";const twh=tw*th;tn="($tnum)"[$>]); # ?
if (!(x%tw) && !(y%th),
res=vector(#twh,0);
ref(crop(x,y,tw,th),src);
for (l = 0, l<th, ++l, for (k = 0, k<tw, ++k,
off = k + tw*l;
res += src[off]*crop(#"$idct"tn"",k*tw,l*th,tw,th,1))); # ?
draw(#"$>",res,x,y,0,0,tw,th);
); i"
rm.
done
a[0-2] c csswap[0] 15,0
r[0] {$ww},{$hh},1,100%,0,3
endl done
rm[dct,idct]

Everything with # ? afterwards is a line that includes something that I’m not sure about.

var={[{V=[1,2,3,4];V[0,2]}]+100}    # var=101,102
1 Like

Why doesn’t that output var = 101,102,103? Surely that output would require V[0,1] instead.

I was wondering that in the other thread but apparently the second value denotes the length and not the endpoint of the subset. (The third value would denote the step.)

I never knew third value is step. Now that would have been useful in one of my filter. Do not remember which. I think I could use it for Thorn Fractal.

@Joan_Rake1 Now I think I got it, and I will solve your filter soon.

This is a small preview. I’m thinking of extracting info that can be inferred from variable inputs, and using that to limit usage of dct_tileset, and idct_tileset and to copy numbers from duplicated variables. I must admit that the syntax here is iffy though as I’m not accustomed to this, but it is a step closer to solving your problem.

rep_vec:
if !(narg(${2--1})%2)
 init_v_t=${2--1}
 v_t_size={narg($init_v_t)}
else error !narg("$"2--1)%2==F fi

v_tile_duplicates={"
 v_tile_info=["$init_v_t"];
 const sub_v_s=2;
 const v_s="$v_t_size"/sub_v_s;
 v_tile_duplicates=vectorv_s(0);
 for(n=1,n<v_s,n++,
  for(m=0,m<n,m++,
   if(v_tile_info[n*sub_v_s,sub_v_s]==v_tile_info[m*sub_v_s,sub_v_s],
    v_tile_duplicates[n]=1;
   );
  );
 );
 v_tile_duplicates;
"}
echo[0] $v_tile_duplicates

Not sure if this helps, but let me explain some things:

  • In a math expression, you can set a variable for the G’MIC interpreter by using run('var=',value), when value is a scalar value. For vector-valued values, you can use run('var=',vtos(vector_value)).
  • Note that a call to run() is a bit expensive (it initializes a whole new G’MIC interpreter each time), so anything that can avoid it is good to use. For instance, if you need to set a variable value multiple time in the same expression, then there is probably something wrong.
  • run('var=',value) should be more often found in an end() or init() section when used with command fill or eval (looped version). You ensure it is run only once.
  • Apart from setting variables in a run(), and for scalar or vector-valued variables, you can still store their values in a temporary image, wich something as i(#3) = value or I(#3) = vector_value, it is way faster.
2 Likes

The temporary image trick! I forgot all about that. Now I’d have to find an equivalent of find.

For which task ?

From what I understand, the code you’ve made will tell me when there’s a duplicate value. I thought that instead I’d use find, where if the position returned is not the same as the position that we’re at, it’s found a duplicate and it’ll put that position into a new vector (I’ll replace this with a 3x1 image).

My original plan was to use find to get the first position that a pair of dimensions appears in and store that somewhere for use later. For example: if I specified tiledims={[8,2,5,3,8,2]} then I want a vector or image whose values are [1,2,1]. I was using find for this because it returns the first position that a subvector occurs within a vector (or -1 if there’s nothing, which won’t happen in this case).

I’d use that new vector for specifying which DCT and IDCT tilesets to use within the fill blocks which perform the transforms.

If your pair of dimensions is bounded (e.g. you know that it’s always less than [1024,1024], then another good trick is to use a temporary image with size 1024\times 1024 in which you put a value (e.g. 1) in (x,y) each time you use a couple [x,y].
Even if if takes a bit of memory, this will speed up the search for an already encountered couple.

You can even store some information as the value i(x,y) (rather than putting 1), like the index to something, etc… (or even a vector-valued value to store several information related to this particular couple).

This is a trick I use often. This speeds up things dramatically
(finding a duplicate is done in O(1)).

Happily, the number of pairs of dimensions is only 3, one for each channel. I could use this as some sort of grid of parameters since I want to add different block offsets for each channel later. I can create an image where different rows correspond to different parameters. I can also create my own find-like procedure for this; thanks to Reptorian I’ve figured out that it’s as easy as using a for loop.

I think it’s almost done. I just don’t know how to select the right image using a name.

fx_jpeg :

to_rgb
inum=$!
q=$1
($2,$4,$6;$3,$5,$7;0,0,0)
nm. params

eval. "begin(list=transpose(crop(0,0,3,2),2));
for(n=0,n<3,++n,
pos=n*2;
i(n,2)=(find(list,list[pos,2],0,2)*0.5
));"
tcount=0
repeat 3
tnum={i(#$params,$>,2)}
if $tnum==$>
tw={i(#$params,$>,0)}
th={i(#$params,$>,1)}
dct_tileset $tw,$th
idct_tileset $tw,$th
nm[-2,-1] "dct"$tcount"","idct"$tcount""
tcount+=1
fi
done

repeat {$inum} l[$>,{(-2*$tcount)-1}--1]
ww={w(#0)}
hh={h(#0)}
csswap[0] 0,15 s[0] c 
display
repeat 3
tw={i(#$params,$>,0)}
th={i(#$params,$>,1)}
tn={i(#$params,$>,2)}
r[$>] {w(#0)+(-w(#0)%$tw)},{h(#0)+(-h(#0)%$th)},1,100%,0,3
{w#0},{h#0},{d#0},{s#0}
f[$>] :"
begin(const tw="$tw";const th="$th";const twh=tw*th;const tn="$tn");
if (!(x%tw) && !(y%th),
res=vector(#twh,0);
ref(crop(x,y,tw,th),src);
for (l = 0, l<th, ++l, for (k = 0, k<tw, ++k,
off = k + tw*l;
res += src[off]*crop(#""$dct"tn",k*tw,l*th,tw,th,1))); # ?
draw(#-1,res,x,y,0,0,tw,th);
); i"

f. :"begin_t(const qual="$tw"*"$th"*0.0625*(1-"$q"*0.01)^3);round(i,qual)"

f. :"
begin(const tw="$tw";const th="$th";const twh=tw*th;const tn="$tn");
if (!(x%tw) && !(y%th),
res=vector(#twh,0);
ref(crop(x,y,tw,th),src);
for (l = 0, l<th, ++l, for (k = 0, k<tw, ++k,
off = k + tw*l;
res += src[off]*crop(#""$idct"tn",k*tw,l*th,tw,th,1))); # ?
draw(#"$>",res,x,y,0,0,tw,th);
); i"
rm.
r[$>] {$ww},{$hh},1,100%,0,3
done
display
a[0-2] c csswap[0] 15,0

How do I get #""$dct"tn" to turn into #$dct1 etc…?

I’m not sure if this will help, but you can concatenate strings. This is a untested solution:

repeat 3
tnum={i(#$params,$>,2)}
if $tnum==$>
tw={i(#$params,$>,0)}
th={i(#$params,$>,1)}
dct_tileset $tw,$th
idct_tileset $tw,$th
dct_id=dct
idct_id=idct
dct_id.=$tcount
idct_id.=$tcount
nm[-2,-1] $dct_id,$idct_id
tcount+=1
fi

Thanks. I now have another problem:

I have unique pairs of parameters A, B and C. Each pair of parameters is an ordered pair of two numbers, first the tile width and secondly the tile height.

I need something which can assign numbers to these in the following way:

A, B, C → 0, 1, 2
A, A, B → 0, 0, 1
A, B, A → 0, 1, 0
A, A, A → 0, 0, 0

I am far too strained to figure it out.

You can always take a break. Right now, I’m not doing any of my filters and just trying to help out.

I just keep running into problem after problem.

rm

(8,8,8;8,6,8;0,0,0)
nm. params

eval. >"begin(list=transpose(crop(0,0,3,2),3);count=0;foundlist=vector6());
for(n=0,n<3,n+=1,
pos=n*2;
currentparams=list[pos,2];
i(n,2)=count;
(n==(find(list,currentparams,0,2)*0.5))?(
count+=1;
));

"

Why does this give me an image where the bottom row is 16,17,18? It should be 0,1,1! Worse:

rm

(8,8,8;8,6,8;0,0,0)
nm. params

eval. >"begin(list=transpose(crop(0,0,3,2),3);count=0;foundlist=vector6());
for(n=0,n<3,n+=1,
pos=n*2;
currentparams=list[pos,2];
i(n,2)=count;
count+=1;

);

"

Here, the bottom row is 24,25,26 when it should be 0,1,2!

I’m not sure what’s in your head, so I would like to know what the last row number represent.

I do think that you could work with this instead.

(8,8,8^8,6,8^0,0,0)

This gives 3x1 image with 3 channels where 2 channel is tile width and tile height. You can extract it via sh 0,1 though s. c,-2 doesn’t slow down much at all.

This is my unsuccessful attempt:

jr_test_1:
(8,8,8^8,6,8^0,0,0)
sh 0,1
eval. "begin(v=expr('x',w;););
if(x,
 for(n=0,n<x,n++,
  I(n)==I?v[x]=n;
 );
);
end(
 run('v=',vtos(v););
);
"
echo $v
rm.

#0,1,0#

EDIT: Never mind, I tried. I don’t think I helped. :frowning:

EDIT:

jr_test_1:
($1,$4,$7^$2,$5,$8^$3,$6,$9)
sh. 0,1
eval. "begin(v=expr('x',w););
if(x,
 for(n=0,n<x,n++,
  I(n)==I?(v[x]=n;break(););
 );
);
end(
 run('v=',vtos(v););
);
"
echo $v
rm.

I seem to confirm A,B,A=0,1,0 and others work here.

To explain further on why it works:

  1. expr allows you to express vector just as if you were filling a image with fill. But it doesn’t create a new image. So, initial ‘v’ is [0,1,2]. I only just use the ‘algorithm’,width myself.

  2. After that it checks for duplicates, and if duplicate is found, the for loop is broken. If none are found, v is equal to [0,1,2].

  3. Thanks to what @David_Tschumperle taught me, I was able to insert v within eval into v outside of the eval.

If you want to check via GUI interface, simply change echo to u.

I wasn’t clear. Every unique pair of dimensions that’s specified in the command options is assigned a number, and each pixel’s value in that bottom row in the $params image is supposed to equal the number assigned to the pair of dimensions that sits within the same column of the image on the top two rows. For fx_jpeg 100,8,8,8,6,8,8, the image should be:

8 8 8
8 6 8
0 1 0

Your solution doesn’t work for A, A, B:

rm
(8,8,8^6,6,8)
sh. 0,1
eval. "begin(v=expr('x',w););
if(x,
 for(n=0,n<x,n++,
  I(n)==I?(v[x]=n;break(););
 );
);
end(
 run('v=',vtos(v););
);
"

rm.
i ($v)
display

This gives me 0, 0, 2 and not 0, 0, 1.

Edit: I’ve found what I’m looking for, but the filter is still not working as it should.

eval. "begin(count=0;list=transpose(crop(0,0,3,2),2);foundlist=vector6(0));
for(n=0,n<3,++n,
pos=n*2;
cp=list[pos,2];
(pos==find(list,cp,0,2))?(
foundlist[count*2]=cp[0];
foundlist[count*2+1]=cp[1];
count+=1);
i(n,2)=find(foundlist,cp,0,2)*0.5
);"

Using i(n,2)=count, I see that count is being set to the wrong things again, either being 8, 16 or 24 higher than it should be. I think this is a bug with the mathematical parser. @David_Tschumperle This is broken on both 2.9.4 and 2.9.5. count should be 2 at most…