Reptorian G'MIC Filters

No to both. You have to input the exact name. And there are limitations of not accepting space.

@David_Tschumperle Any idea to address those limitations?

Would be nice to use part of name to sort all portraits together for example.
But anyway, if I remember well the command name names selections and not images themselves, right? At least that’s how I see it. That’s probably why you can name multiple images as “duck”, otherwise it would just lead to confusion :
gmic repeat 5 sp done name[0,2] duck negate[duck]

I’ll have to remember to use this in my scripts though haha.

Spaces and computing don’t go too well together anyway… Reminds me some headaches when i wrote a bash script to “link (from a NAS),read metadata,equalize, convert to opus,rename,rearrange folders,replaygain albums,lftp to phone” my FLAC files to use in guayadeque. And all using parallel. Spaces and single quotes in filenames are still breaking the thing sometimes.

I think I found my own answer. To treat image names as a vector of Unicode value and that requires to concatenate them somehow. That way, one can use space inside arguments.

Here’s the code:

#@cli rep_str2varj:
#@cli : Convert string to a string that represents a string that can be joined with a variable name.
rep_str2varj:
({'{'"$*"'}'})
replace[-1] {_','},{_'_'}
status _{t}
rm.

And example use:

C:\Windows\System32>gmic rep_str2varj \"Hi there, this is Reptorian.\" echo ${}
[gmic]-0./ Start G'MIC interpreter (v.3.2.7).
_72_105_32_116_104_101_114_101_44_32_116_104_105_115_32_105_115_32_82_101_112_116_111_114_105_97_110_46
[gmic]-0./ End G'MIC interpreter

However, the name sucks and so do the description.

EDIT: Nah, this doesn’t seem to work well with space case. I have to debug that. This is the full code for now:

#@cli rep_sort_images_by_images_name_order: name_a,name_b
#@cli Sort images accordingly to images name. Duplicates images name are not accepted!
#@cli : $ sample portrait2,duck,fruits,portrait1,portrait2,duck,duck,fruits rep_sort_images_by_images_name_order duck,portrait2,fruits,portrait1
rep_sort_images_by_images_name_order:
if $!<2 return fi

set_of_names_count,relative_pos=$!,0
$=arg

repeat $! {
 id=${rep_str2varj\ {'{$>,n}'}}
 if narg(${img_name_id_$id})
  img_name_id_$id+=1
  set_of_names_count-=1
 else 
  img_name_id_$id=0
 fi
}

repeat $set_of_names_count {
 id=${rep_str2varj\ {'{$>,n}'}}
 img_id=${img_name_id_$id}
 if narg($img_id)
  move[${arg{$>+1}}] {$>+$relative_pos}
  relative_pos+=$img_id
 else error name_not_found
 fi
}

#@cli rep_str2varj:
#@cli : Convert string to a string that represents a string that can be joined with a variable name.
rep_str2varj:
({'$*'})
replace[-1] {_','},{_'_'}
status _{t}
rm.

As long as you wrap the string appropriately, I recall the spaces transferring. I have a bad memory, but it has to do with a mixture of bracketing and quoting. Perhaps, it won’t work with names. Again, I don’t quite remember.

Well, David pointed to named. A command I have used before, but didn’t know specifically what it does. I fixed it, and this is the current command:

#@cli rep_sort_images_by_images_name_order: name_a,name_b
#@cli Sort images accordingly to images name. Duplicates images name are not accepted!
#@cli : $ sample portrait2,duck,fruits,portrait1,portrait2,duck,duck,fruits rep_sort_images_by_images_name_order duck,portrait2,fruits,portrait1
rep_sort_images_by_images_name_order:
img_moved=0
$=arg

for $img_moved<$! {
 named[$img_moved--1] 0,${arg{$>+1}}
 t_arg:=narg(${})
 
 if $t_arg
  move[${}] $img_moved
  img_moved+=$t_arg
 else error missing_image_name
 fi
}

Another new command, and it’s short enough to share the whole code:

#@cli rep_python_insert_integer_value:
#@cli : Allows user to insert integer values from the cli interface. Then, return the integer value.
rep_python_insert_integer_value: 
exec 1,"python -c \"import sys; sys.exit(int(input('\\n[gmic][python]-"$^"./ Input Integer Value: ')))\""

You can easily guess how this works. But, this is all I can do with mixing two languages without resorting to socket.

D:\Programs\G'MIC\gmic-community>gmic rep_python_insert_integer_value echo the_output_is_${}
[gmic]-0./ Start G'MIC interpreter (v.3.2.7).
[gmic][python]-0./ Input Integer Value: 175601

the_output_is_175601
[gmic]-0./ End G'MIC interpreter.

Which brings me to brainfuck interpreter I did. I only did this because there’s no equilavent of std::cin in G’MIC. Here - Brainfuck Code interpreter written in G'MIC

Also, realized that there’s a limitation that dependent on OS.

More progress on the upgrade to Mitchell Concatenation. I managed to get more modes working, and that means that this filter has more possibility than before, but only to the scope of said filter.


Current Code - Current Code for Mitchell Concatenation - Pastebin.com

You can tell that it’s pretty complicated.

1 Like

Ok, more updates. It looks like the base generation of Mitchell Concatenation is done. The next thing is some few code updates to handle how the images are to be created beyond just what is Mitchell Concatenation.



2 Likes

Now, I’m releasing a beta version of the rep_mitchell_concatenation. To use it, paste into user.gmic and use new_rep_mitchell_concatenation.

Code so far is 1706 lines of code. :woozy_face: And I still have to finish how to process newly created images or finalization. The generation of the Mitchell Concatenation is done.

And sample CLI interface code:

$ 2000,2000 pal {expr('int(u(0,380,1,0))',2)} new_rep_mitchell_concatenation[0] 1,15,add,1,20,sub,20,[1],[2],cubic,star,95%,10,0,2

If you’re using second or third allowed argument, you need to have at least one [palette]. And if you’re using second, the options to replace [palette] are 0 or 1. If you’re using third, the options to replace [palette] are -2,-1,1 and negative will only use either first or second set of arguments before form_pixel size.

Easiest case of Mitchell Concatenation is this:

$ new_rep_mitchell_concatenation 1,10,add

You can even verify the result by assuming the very bottom is 1. And going up to 9 and do 987654321+123456789=1111…0 and then at n=10, it would be 12345678910+10987654321. And you finally learn what is Mitchell Concatenation is. If you change the base, and in case of base 16, it’d be like 123456789abcdef10+10fedcba987654321, and it still works at base 500+ because 19 is a single digit in base 500. Honestly, this would make a good numberphile video.

The above is partly done. I’ll take a break from that until the weekend.

Here’s a new combinatoric tool in work:

$ +rep_string_permutations data,x v - repeat whd { ({I[#-1,"$>"]}) echo {t} rm. } rm v +
#@cli rep_string_permutations: string,_axis
#@cli : Return all the permutations of set of numbers as a image with values representing the unicode representation of characters in input string. Permutations is dependent on character appearance order.
#@cli :
#@cli : Algorithm is based on the implementation of Narayana Pandita's algorithm by PM 2Ring at stackoverflow.
#@cli : Implementation of Narayana Pandita's algorithm -  https://stackoverflow.com/questions/8306654/finding-all-possible-permutations-of-a-given-string-in-python
#@cli : Description of Narayana Pandita's algorithm - https://en.wikipedia.org/wiki/Permutation#Generation_in_lexicographic_order
#@cli : Default values: '_axis=x'
+rep_string_permutations:
skip ${2=x}
check "inrange(('$2')[0],_'x',_'z',1,1)"
1,1,1,2

eval "
 reference_information='$1';
 char_position=vector(#256,-1); # Enable O(1) index retrieval as G'MIC lack Python-like dictionary.
 ind=0;
 fill(reference_information,char_ind,
  char=reference_information[char_ind];
  is_char_found=char_position[char]>-1;
  if(is_char_found
  ,pos=char_position[char];++i(#-1,0,pos,0,1);
  ,pos=char_position[char]=ind++;da_push(#-1,[char,1]);
  );
  pos;
 );
 da_freeze(#-1);
 set('size_of_string',size(reference_information));
 sort(reference_information);
 "

axis,number_of_string_permutations={v=crop(#-1,0,0,0,1,1,h,1,1);[_'$2'-_'x',fact(sum(v))/prod(fact(v))]}
out_dim={v=vector(#3,1);v[$axis]=$number_of_string_permutations;v}

if $number_of_string_permutations>(1<<24) error exc_permut_val:$number_of_string_permutations fi

$out_dim,$size_of_string,>"begin(
  unicode=crop(#-1,0,0,0,0,1,h#-1,1,1);
  out_vector=["${}"];
  const max_index=s-1;
  const dec_max_index=max_index-1;
  started=0;
  reverse_array_starting_from(a)=(
   start=a;
   end=max_index;
   while(start<end,
    swap(out_vector[start++],out_vector[end--]);
   );
  );
 );
 if(started,
  for(jp=dec_max_index,jp>-1,--jp,
   if(out_vector[jp]<out_vector[jp+1],break(););
  );
  v=out_vector[jp];
  for(kp=max_index,kp>jp,--kp,
   if(v<out_vector[kp],break(););
  );
  swap(out_vector[kp],out_vector[jp]);
  reverse_array_starting_from(jp+1);
 ,
  started=1;
 );
 out_vector;
 "

channels[-2] 0
map[-1] [-2]
remove[-2]

The printed result:

daat
data
dtaa
adat
adta
aadt
aatd
atda
atad
tdaa
tada
taad

You can even use it for xyzc too. Good for permute.

xyzc
xycz
xzyc
xzcy
xcyz
xczy
yxzc
yxcz
yzxc
yzcx
ycxz
yczx
zxyc
zxcy
zyxc
zycx
zcxy
zcyx
cxyz
cxzy
cyxz
cyzx
czxy
czyx

Here the difference between the implementation of the algorithm at stackoverflow, and my version is that my version only depend on character appearance order. I think I should allow a option to force sorting of string before generating the permutations.

Another rep_string_permutations tool.

C:\Windows\System32>gmic echo ${rep_string_permutations_str2index\ aabbccc,ccbaacb}
[gmic]-0./ Start G'MIC interpreter (v.3.2.7).
193
[gmic]-0./ End G'MIC interpreter.

Should be useful for Lyapunov Fractal as with index2str, users can finally experiment with shuffling letters.

#@cli rep_string_permutations_str2index: test_string : reference_string,test_string,_sort_reference_string={ 0=do_not_sort_string | 1=sort_string }
#@cli : Return the lexicographic rank in which the permutation of string is found. The rank is base on character appearance order. If you provide only one argument, then rank is dependent on alphabetical order.
#@cli :
#@cli : Algorithm to find the lexicographic rank of string has been made by egoista of GeeksForGeeks and source code can be found here - https://www.geeksforgeeks.org/lexicographic-rank-string-duplicate-characters/
#@cli : Author : Reptorian.
#@cli : Default values: '_sort_reference_string=0'
rep_string_permutations_str2index:
skip "${2=}",${3=0}

1,1,1,1

eval "
 reference_information='$1';
 const size_of_info=size(reference_information);
 const contain_arg_2=narg($2);
 contain_arg_2?(
  const bool_sort_string=$3;
  reference_information='$1';
  test_string='$2';
  if(size(reference_information)!=size(test_string),run('error diff_str_dims'););
  if(bool_sort_string,reference_information=sort(reference_information););
 ):(
  test_string='$1';
  reference_information=sort(test_string);
 );
 test_string==reference_information?(
  0;
 ):(
  ind=0;
  char_position=vector(#256,-1); # Enable O(1) index retrieval as G'MIC lack Python-like dictionary.
  repeat(size_of_info,char_ind,
   char=reference_information[char_ind];
   char_position[char]>-1?(
    ++i[#-1,char_position[char]];
   ):(
    char_position[char]=ind++;
    da_push(#-1,1);
   );
  );
  test_string==reverse(reference_information)?(
   dividier=1;
   repeat(da_size(#-1),ind,
    dividier*=fact(i[#-1,ind]);
   );
   fact(size_of_info)/dividier-1;
  ):(
   num_of_chars_detected=0;
   fill(test_string,char_ind,
    new_val=char_position[test_string[char_ind]];
    if(new_val<0,run('error inval_char'););
    if(--i[#-1,new_val]==-1,run('error exec_chars_det'););
    new_val;
   );
   str_index=0;
   repeat(size_of_info,ind,
    count_of_less_index_value=0;
    for(alt_ind=ind+1,alt_ind<size_of_info,++alt_ind,
     if(test_string[ind]>test_string[alt_ind],++count_of_less_index_value;);
    );
    if(count_of_less_index_value,
     for(alt_ind=ind,alt_ind<size_of_info,++alt_ind,++i[#-1,test_string[alt_ind]];);
     dividier_factorial=1;
     repeat(da_size(#-1),element,
        dividier_factorial*=fact(i[#-1,element]);
        i[#-1,element]=0;
     );
     str_index+=(fact(size_of_info-ind-1)*count_of_less_index_value)/dividier_factorial;
    );
   );
   str_index;
  );
 );
 "
remove[-1]

Here comes the real difficult part. Doing this for index2str. Sadly, there’s not much code out there or any that I can start with.

Your code seems to be a lot easier to parse now. I am sure you will find a way in a short period of time and after gazillion of edits to your posts. Been so busy I cannot give you anything else except for encouragement. That and my coding and math sucks. :wink:

1 Like

It turns out you were correct. I actually managed to code it and pushed it. That was very difficult. Thank you for the encouragement.

Looks like this is the first time an algorithm exists to do just that. There is no other results in google, and even some experienced coders couldn’t help out.

D:\Programs\G'MIC\gmic-community>gmic +rep_string_permutations AABBC,x echo {`I[#-1,24]`}
[gmic]-0./ Start G'MIC interpreter (v.3.2.7).
CAABB
[gmic]-2./ Display image [0] = '[>begin( unicode=crop(#-1,0,0...'.
[0] = '[>begin( unicode=crop(#-1,0,0,0,0,1,h#-1,1,1); out_vector=[0,...':
  size = (30,1,1,5) [600 b of float32].
  data = (65,65,65,65,65,65,65,65,65,65,65,65, ... ,67,65,65,66,65,65,66,66,65,66,65,65).
  min = 65, max = 67, mean = 65.8, std = 0.750838, coords_min = (0,0,0,0), coords_max = (24,0,0,0).
[gmic]-1./ End G'MIC interpreter.

D:\Programs\G'MIC\gmic-community>gmic echo ${rep_string_permutation_index2str\ AABBC,24}
[gmic]-0./ Start G'MIC interpreter (v.3.2.7).
CAABB
[gmic]-0./ End G'MIC interpreter.

I’m just gonna save this here for distinct combinations of string if I ever do get to that. I finished distinct permutations of string, combination is next of course. :

    // Program to print all combination of size r in an array of size n
    #include <stdio.h>
    #include <stdlib.h>
    void combinationUtil(int arr[], int n, int r, int count, int data[], int i);
     
    // Needed for qsort.  See http://w...content-available-to-author-only...s.com/reference/cstdlib/qsort/
    int compare (const void * a, const void * b)
    {
        return ( *(int*)a - *(int*)b );
    }
     
    // The main function that prints all combinations of size r
    // in arr[] of size n. This function mainly uses combinationUtil()
    void printCombination(int arr[], int n, int r)
    {
        // A temporary array to store all combination one by one
        int data[r];
     
        // Sort array to handle duplicates
        qsort (arr, n, sizeof(int), compare);
     
        // Print all combination using temprary array 'data[]'
        combinationUtil(arr, n, r, 0, data, 0);
    }
     
    /* arr[]  ---> Input Array
       n      ---> Size of input array
       r      ---> Size of a combination to be printed
       index  ---> Current index in data[]
       data[] ---> Temporary array to store current combination
       i      ---> index of current element in arr[]     */
    void combinationUtil(int arr[], int n, int r, int index, int data[], int i)
    {
        // Current cobination is ready, print it
        if (index == r)
        {
            for (int j=0; j<r; j++)
                printf("%d ",data[j]);
            printf("\n");
            return;
        }
     
        // When no more elements are there to be put
        if (i >= n)
            return;
     
        // current is included, put next at next location
        data[index] = arr[i];
        combinationUtil(arr, n, r, index+1, data, i+1);
     
        // Remove duplicates
        while (arr[i] == arr[i+1])
            i++;
     
        // current is excluded, replace it with next (Note that
        // i+1 is passed, but index is not changed)
        combinationUtil(arr, n, r, index, data, i+1);
    }
     
    // Driver program to test above functions
    int main()
    {
        int arr[] = {1, 2, 1, 3, 1};
        int r = 3;
        int n = sizeof(arr)/sizeof(arr[0]);
        printCombination(arr, n, r);
        return 0;
    }

Problem now is to find how many distinct combination possibilities.

1 Like

Accepting palette request. I’m currently making a hash map for pal to make it constant time. At the moment, the only new palette would be: Piet Mondraine palette.

Right now, I’m trying to narrow down this list to common substrings starting from beginning:

aap
an
ap
ar
au
bl
bo
br
bw
ca
ch
cl
cmy
cr
db
de
di
edg
eu
fa
fi
gb_
gr
ho
in
je
juicy
kens
lego
lu
ma
na
ne
ni
pa
pe
pi
re
rgb
ro
sh
sp
st
sup
ta
tf
to
tr
vi

That way, I can make a tree map. With this, I can make a tree map.

Found some I can add - Art Color Chain Round 1: Start from Piet Mondrian’s Red, Blue and Yellow…|Color Apprentice

1 Like

New CLI tool: rep_echo_image_data. This echo the image data in text form. Could be improved though. Wouldn’t advice for big images though. Small images would be fine.

D:\Programs\G'MIC\gmic-community>gmic 3,3,3,3,[x,y,z,c] rep_echo_image_data rm.
[gmic]./ Start G'MIC interpreter (v.3.3.0).
[gmic]./ Input image at position 0, with values '[x,y,z,c]' (1 image 3x3x3x3).
[gmic]./ (0,1,2;0,1,2;0,1,2/0,1,2;0,1,2;0,1,2/0,1,2;0,1,2;0,1,2^0,0,0;1,1,1;2,2,2/0,0,0;1,1,1;2,2,2/0,0,0;1,1,1;2,2,2^0,0,0;0,0,0;0,0,0/1,1,1;1,1,1;1,1,1/2,2,2;2,2,2;2,2,2)
[gmic]./ Remove image [0] (0 images left).
[gmic]./ End G'MIC interpreter

This is the image data:

(0,1,2;0,1,2;0,1,2/0,1,2;0,1,2;0,1,2/0,1,2;0,1,2;0,1,2^0,0,0;1,1,1;2,2,2/0,0,0;1,1,1;2,2,2/0,0,0;1,1,1;2,2,2^0,0,0;0,0,0;0,0,0/1,1,1;1,1,1;1,1,1/2,2,2;2,2,2;2,2,2)

Another new CLI tool: rep_hex8args2pal. Create a image that represents hex input as a palette.

1 Like

Interesting! I think I have something slightly shorter:

foo :
  if w
    str={`"str = v2s(crop()); for (k = 1; p = find(str,_','), p>=0, p = find(str,_',',++p),
           str[p] = k%w?_',':k%wh?_';':k%whd?_'/':_'^'; ++k); str"`}
  fi
  e ($str)

I’ll probably modify the print command to use this trick.

1 Like

I never thought of doing it like that. That’s quite neat. I fixed up my own version recently as channel takes priority over depth, and depth takes priority over height.

:+1:

Tested it now, would it be fine to add a global variable to allow printing of more numbers? 24 chars is too small.

No news for now, but I discovered that you can make a hashmap with palettes.

Pastebin because the code is too big.

That is more efficient in terms of performance than the current code too (tested with tic toc). No need to go through if…elif…else… fi block.