Reptorian G'MIC Filters

The 2 px border refers to what happens when you use only resize to stimulate symmetry in the fashion shown above. Zoom in the center after doing the command below. I have made my own command which does the same, but without it, and pushed it recently, but wanted to know if there was another command like that already.

$ gmic sp cat r 200%,200%,100%,100%,0,3

Seems normal behaviour to me for mirroring. You could lop off the edges before mirroring and insert them afterwards, or do a row/column shift and then crop… If you have a command already, no problem? I suppose you are looking for something more native or established in hopes of speed or simplicity.

image

Working on adding border. I find odd borders a bit difficult though. I think I’ll just not attempt that and stick with bad offset.

That being said, here’s one example of possible output:

image

I’m trying to get this to work.

rep_test:
pal 45
echo [${1-{0+s#-1}}]

Basically it should insert arguments with the same number as the spectrum size. I’m doing it for arguments that’s basically higher than arg1.

Reading up on this, it’s not possible: G'MIC - GREYC's Magic for Image Computing: A Full-Featured Open-Source Framework for Image Processing - Command Items and Selections

So I have to use array of command argument and extract it.

Solved the above roadblock. Now, this is getting really close to release:

Looks much better. Kind of looks like a relief (elevation) map from a video game. Your animation earlier reminds me of a video game too, like a magic portal/booster.

I don’t get how it looks like elevation map other than contour.

That being said: Here’s a snapshot though there’s still the thorny problem of not being able to access target image dimensions from GUI. This is turning out to be a much tougher filter than I anticipated.

Ok, I think I’m done with the GUI filter. There’s also this:

Both are unfix-able at my end. Otherwise, the image generated on apply/ok are fine.


I have released Hitomezashi. Note that there are unfixable bugs. Particularly in relations with the fact that G’MIC can’t retrieve target image dimension, and with how preview works. Some are fixable, but I’ll do that later.


I also made +rep_split_gradient and pushed it. The cli instruction should be clear to understand in of by itself. What it does is create split gradients.

I think I have enough new equations for Thorn Fractal. And I found a really unique one:

I don’t know what to name it yet.

2 Likes

On Thorn Fractal, I just realized that you can set equation as string with arg(), and then insert it into the JIT side of thing. And finally call it out on the GUI with the usage of u. This actually would enable me to allow users to manipulate preset formulas onto custom formula, and that would make custom formulas so much easier.

EDIT: I fixed Color Harmonies [DEMO]. It’s planned to have palette export, but for now, this will do. When points change as soon as your mouse is released, it won’t go back to the center.

EDIT: Improved +pal command. See commit here for more info - https://github.com/dtschump/gmic-community/commit/960f364d5b66d2bee09fd2f693b15bcbab678a48

EDIT: Two new cli commands - rep_output_pdn_pal , rep_output_gpl . These will export to Paint.NET Palette and GIMP Palette respectively.

1 Like

I’m on my way to recreating this - Concatenations — Kerry Mitchell

The evidence:

image

Base 12

image

Base 4


It seems I finally understand Kerry Mitchell’s concatenation art. The above use base 10.

Base 5 on the above.



Now, I have done element-wise subtraction:

image



FInally, element-wise multiplication though not accurate where there is no digits, but I’m not going to bother addressing that.

Base 120, and this one starts at 14300

1 Like

Recent Changes:

  1. Color Harmonies is no longer a demo thing. It becomes an actual tool.
  2. Hitomezashi has been fixed.
  3. The two palette exporters has also been fixed.
1 Like

test_pic

test_pic_3

Back to Mitchell Concatenation. This should be finished soon.

The last 3 images were fun. The filter is coming along fine. :slight_smile:

test_pic_5

Looks like I’m almost done with it. I think all I need to do is to create the GUI filter.

Also, I’m gonna back up the user.gmic.zip here since I can’t connect to my backup drive for now -
user (2).zip (26.6 KB)

Again, backing up:

Code to Mitchell Concatenation
#@cli rep_mitchell_concatenation: startnum_a,startnum_b,_base,_base_2,_method_a={ 0=sub | 1=add | 2=mul},_method_b={ 0=sub | 1=add | 2=mul},_pixel_size,[palette],[palette],_auto_resize_pal,_shape_id,_shape_ratio,_shape_angle,shape_dir,shape_repeat_mode,shape_fit,_shape_sub,_shape_option_1..._shape_option_n
#@cli : Generates Kerry Mitchell Concatenation Art. Detailed explanation can be found at - http://www.kerrymitchell.art/spacefilling-blog/2013/11/concatenations.html
#@cli : Default values: '_int_base=10','_method_a=0','_method_b=1','_palette=n/a','hex_bg_col=n/a','_shape=n/a'
rep_mitchell_concatenation:
skip ${1=},${2=},${3=},${4=},${5=},${6=},${7=1},${8=},${9=1},${10=},${11=},${12=1},${13=0},${14=0},${15=0},${16=0},${17=1},${18=}

if narg($1)&&narg($2)
 startnum_a,startnum_b={max(1,int(abs($1)))},{max(1,int(abs($2)))}
elif narg($1)||narg($2)
 if narg($1)
  startnum_a,startnum_b={max(1,int(abs($1)))},{max(1,int(abs($1)))}
 else
  startnum_a,startnum_b={max(1,int(abs($2)))},{max(1,int(abs($2)))}
 fi
else
 startnum_a,startnum_b=1,1
fi

if narg($3)&&narg($4)
 base_a,base_b={max(2,int(abs($3)))},{max(2,int(abs($4)))}
elif narg($3)||narg($4)
 if narg($3)
  base_a,base_b={max(2,int(abs($3)))}
 else
  base_b,base_b={max(2,int(abs($4)))}
 fi
else
 base_a,base_b=10
fi

if narg($5)&&narg($6)
 method_a,method_b={abs(int($5))},{abs(int($6))}
elif narg($5)||narg($6)
 if narg($5)
  method_a,method_b={abs(int($5))}
 else
  method_a,method_b={abs(int($6))}
 fi
else
 method_a,method_b=1,1
fi

startnum_diff,base_diff,method_diff,shape_size={$startnum_a!=$startnum_b},{$base_a!=$base_b},{$method_a!=$method_b},{max(1,int(abs($7)))}

use_shape,double_concatenation_mode,use_different_dimensions,num_of_images={narg($11)?($shape_size>=4?1:0):0},{$startnum_diff||$base_diff||$method_diff},{$!>1?(use_diff=0;start_dim=[w#0,h#0];repeat($!-1,p,q=p+1;if([w#q,h#q]!=start_dim,use_diff=1;break();););use_diff;):0},{$!}

if $use_different_dimensions dim_list=[{expr('p=int(x/2);x%2?ceil(h#p/$shape_size)*$shape_size:ceil(w#p/$shape_size)*$shape_size',$!*2,1,1,1)}] fi

width,height=${-max_w},${-max_h} rm

{ceil($width/$shape_size)},{ceil($height/$shape_size)},1,2,vector(#2,-1)

if $use_shape

 ratio:=cut(abs($12),0,1)
 
 if $ratio
 
  shape_ang,mirror,tile_boundary,fit_size=$13,{$14%3},{$15%4},$17

  if ${is_image_arg\ $11}
 
   pass$11 0
  
   if s<=4&&s>1
    if s==3 to_gray.
    else
     s. c,{arg(int(s/2,-3,-1)}
    fi
   elif s==5
    s. c,-4 cmyk2rgb.. to_gray.. *[-2,-1]
   elif s>5 error inv_chans_count
   fi
 
  else
 
   shape_sub:=abs($16)+1
   sid="$11"
  
   if isnum($11) if isint($11)
    sid=${"-arg "1+$sid"","australia,barbedwire,circle,crosshair,cupid,diamond,dragon,dragonfly,fern,flip,gear,gumleaf,heart,information,kookaburra,mail,mapleleaf,paint_splat,paw,phone,polygon,rooster,shopping_cart,snowflake,star"}
   fi fi
  
   if $#>17 shape_$sid {$shape_size*$shape_sub},${18--1}
   else shape_$sid {$shape_size*$shape_sub}
   fi
  
   r. {ceil(w/$shape_size)*$shape_size},{ceil(h/$shape_size)*$shape_size},100%,100%,0,0,.5,.5
  
  fi
 
  if $shape_ang-360*floor($shape_ang/360) rotate. $shape_ang fi
  
  if $mirror==1 mirror. x
  elif $mirror==2 mirror. y
  fi
  
  n. 0,1 autocrop. 0
  
  if $fit_size
   shape_image_ratio={w#-1/h#-1}
   resize_width={1>$shape_image_ratio?w#-1*($shape_size/h#-1):$shape_size}
   resize_height={1>$shape_image_ratio?$shape_size:h#-1*($shape_size/w#-1)}
   r. {$resize_width*$ratio},{$resize_height*$ratio},1,1,5,0,.5,.5
   r. $shape_size,$shape_size,1,1,0,0,.5,.5
  else
   r. {w#-1*(1/$ratio)},{h#-1*(1/$ratio)},1,1,0,0,.5,.5
   r. $shape_size,$shape_size,1,1,5,0,.5,.5
  fi
  
  cut. 0,1 n. 0,1
  
  avgc={avg(crop(#-1))}
  
  if $tile_boundary
   if $tile_boundary==1
    +mirror. x
    a[-2,-1] z
   elif $tile_boundary==2
    +mirror. y
    a[-2,-1] z
   else
    +mirror. x
    +mirror.. y
    +mirror. x
    a[-4--1] z
   fi
  fi
  
  store. shape
  
 fi
 
fi

# End of Initialization

if $double_concatenation_mode

 if $base_b!=10 rep_concat_conset_fill_alt_base $startnum_b,$base_b
 else rep_concat_conset_fill $startnum_b
 fi
 if $base_a!=10 +rep_concat_conset_fill_alt_base. $startnum_a,$base_a
 else +rep_concat_conset_fill $startnum_a
 fi
 
 out_method_a=${arg\ $method_a+1,sub_concat_conset,add_concat_conset,mul_concat_conset}
 out_method_b=${arg\ $method_b+1,sub_concat_conset,add_concat_conset,mul_concat_conset}
 
 rep_element_$out_method_a[-2] $startnum_a,$base_a
 rep_element_$out_method_b[-1] $startnum_b,$base_b
 
 a[-2,-1] z
 
 if ${is_image_arg\ $8} 
  pass$8 0
  if h#-1>1||d#-1>1
   num_of_chans={s#-1}
   permute. cxyz
   unroll. x
   {w#-1/$num_of_chans},1,1,$num_of_chans,crop(#-1,x*$num_of_chans,0,0,0,$num_of_chans,1,1,1)
   rm..
  elif w#-1==1 error inv_dims
  fi
  if $10 r. $base_a,1,1,100%,5 fi
 fi
 
 if ${is_image_arg\ $9} 
  pass$9 0
  if h#-1>1||d#-1>1
   num_of_chans={s#-1}
   permute. cxyz
   unroll. x
   {w#-1/$num_of_chans},1,1,$num_of_chans,crop(#-1,x*$num_of_chans,0,0,0,$num_of_chans,1,1,1)
   rm..
  elif w#-1==1 error inv_dims
  fi
  if $10 r. $base_b,1,1,100%,5 fi
 fi
 
 if $use_shape

  $shape
 
  {w#0*$shape_size},{h#0*$shape_size},1,{s#-2+1}
  
  img_count={$!}
  
  {w#0},{h#0},1,1,"begin(
    const shape_size=$shape_size;
    const tile_boundary=$tile_boundary;
    const num_chan=s#1;
    const tchan=num_chan+1;
    const alpha_size=sqr(shape_size);
    const tile_size=alpha_size*num_chan;
    empty_vec=[-1,-1];
    filled_alpha=vector(#alpha_size,255);
    find_tile_mode()=(sv[0]>-1)&&(sv[1]>-1);
    $img_count==5?(
     generate_color_a()=I(#1,i(#0,x,y,0,0),0,0,0,2);
     generate_color_b()=I(#2,i(#0,x,y,1,0),0,0,0,2);
    ):
    $img_count==4?(
     generate_color_a()=I(#1,i(#0,x,y,0,0),0,0,0,2);
     generate_color_b()=I(#1,i(#0,x,y,1,0),0,0,0,2);
    ):(
     generate_color_a()=[sv[0]];
     generate_color_b()=[sv[1]];
    );
    tile_boundary==3?(
    
     shape_0=crop(#-2,0,0,0,0,shape_size,shape_size,1,1);
     shape_1=crop(#-2,0,0,1,0,shape_size,shape_size,1,1);
     shape_2=crop(#-2,0,0,2,0,shape_size,shape_size,1,1);
     shape_3=crop(#-2,0,0,3,0,shape_size,shape_size,1,1);
     tile_v0=resize(shape_0,tile_size,0,2);
     tile_v1=resize(shape_1,tile_size,0,2);
     tile_v2=resize(shape_2,tile_size,0,2);
     tile_v3=resize(shape_3,tile_size,0,2);
     
     const mx=w-1;
     const my=h-1;
     const startnum=$startnum_a;
     find_pos()=1+sum((mx-x)%2,2*((my-y+startnum)%2));
     
     generate_tile_b()=(
      shape_alp=arg(find_pos(),tile_v0,tile_v1,tile_v2,tile_v3);
      color_tile=vc_0+vc_1*shape_alp;
      tile=[color_tile,filled_alpha];
      draw(#-1,tile,x*shape_size,y*shape_size,0,0,shape_size,shape_size,1,tchan);
     );
     
     generate_tile_a()=(
      shape_alp=arg(find_pos(),shape_0,shape_1,shape_2,shape_3);
      sv[0]>=0?(
       color=generate_color_a();
       color_tile=resize(color,tile_size,1,0);
       tile=[color_tile,shape_alp*255];
       draw(#-1,tile,x*shape_size,y*shape_size,0,0,shape_size,shape_size,1,tchan);
      ):(
       color=generate_color_b();
       color_tile=resize(color,tile_size,1,0);
       tile=[color_tile,(1-shape_alp)*255];
       draw(#-1,tile,x*shape_size,y*shape_size,0,0,shape_size,shape_size,1,tchan);
      );
     );
     
    ):
    tile_boundary?(
     shape_0=crop(#-2,0,0,0,0,shape_size,shape_size,1,1);
     shape_1=crop(#-2,0,0,1,0,shape_size,shape_size,1,1);
     tile_v0=resize(shape_0,tile_size,0,2);
     tile_v1=resize(shape_1,tile_size,0,2);
     
     const max_index=(tile_boundary%2)?w-1:h-1;
     
     tile_boundary%2?(
      find_pos()=(max_index-x)%2;
     ):(
      const startnum=$startnum_a;
      find_pos()=(max_index-y+startnum)%2;
     );
     
     generate_tile_b()=(
      shape_alp=find_pos?tile_v1:tile_v0;
      color_tile=vc_0+vc_1*shape_alp;
      tile=[color_tile,filled_alpha];
      draw(#-1,tile,x*shape_size,y*shape_size,0,0,shape_size,shape_size,1,tchan);
     );
     
     generate_tile_a()=(
      shape_alp=find_pos?shape_1:shape_0;
      sv[0]>=0?(
       color=generate_color_a();
       color_tile=resize(color,tile_size,1,0);
       tile=[color_tile,shape_alp*255];
       draw(#-1,tile,x*shape_size,y*shape_size,0,0,shape_size,shape_size,1,tchan);
      ):(
       color=generate_color_b();
       color_tile=resize(color,tile_size,1,0);
       tile=[color_tile,(1-shape_alp)*255];
       draw(#-1,tile,x*shape_size,y*shape_size,0,0,shape_size,shape_size,1,tchan);
      );
     );
     
    ):(
     shape_alp=crop(#-2,0,0,0,0,shape_size,shape_size,1,1);
     alp_tile=resize(shape_alp,tile_size,0,2);
     generate_tile_b()=(
      color_tile=vc_0+vc_1*alp_tile;
      tile=[color_tile,filled_alpha];
      draw(#-1,tile,x*shape_size,y*shape_size,0,0,shape_size,shape_size,1,tchan);
     );
     generate_tile_a()=(
      sv[0]>=0?(
       color=generate_color_a();
       color_tile=resize(color,tile_size,1,0);
       tile=[color_tile,shape_alp*255];
       draw(#-1,tile,x*shape_size,y*shape_size,0,0,shape_size,shape_size,1,tchan);
      ):(
       color=generate_color_b();
       color_tile=resize(color,tile_size,1,0);
       tile=[color_tile,(1-shape_alp)*255];
       draw(#-1,tile,x*shape_size,y*shape_size,0,0,shape_size,shape_size,1,tchan);
      );
     );
    );
   );
   sv=[i(#0,x,y,0,0),i(#0,x,y,1,0)];
   if(sv!=empty_vec,
    find_tile_mode()?(
     c0=generate_color_b();
     c1=generate_color_a();
     diff=c1-c0;
     vc_0=resize(c0,tile_size,1,0);
     vc_1=resize(diff,tile_size,1,0);
     generate_tile_b();
    ):(
     generate_tile_a();
    );
   );
   "
  k..
   
  if $num_of_images>1
   r. 100%,100%,$num_of_digits,100%,1
  fi
   
  if $num_of_images>1 s. z fi
 
  if $use_different_dimensions
   repeat $num_of_images
    new_width_height:=($dim_list)[$>*2,2]
    r[$>] $new_width_height,1,100%,0,0,1,1
   done
  fi
  
 else
 
  if $!==2
   {w#-2},{h#-2},2,{s#-1+1},"v=i(#-2,x,y,z,0);
    v>=0?[I(#-1,v,0,0,2,1),255]:vector(#s,0);"
    rm[-3,-2]
  elif $!==3
   {w#-2},{h#-2},2,{s#-1+1},"v=i(#-3,x,y,z,0);
    z?(v>=0?[I(#-2,v,0,0,2,1),255]:vector(#s,0);):
    (v>=0?[I(#-1,v,0,0,2,1),255]:vector(#s,0););"
    rm[-3,-2]
  elif $!>3 error only_one_pal
  fi
  
  if ($shape_size>1)||($num_of_images>1)
   r. {w#-1*$shape_size},{h#-1*$shape_size},{2*$num_of_images},100%,1
  fi
  
  if $num_of_images s. z,-2 fi
  
  if $use_different_dimensions
   repeat $num_of_images
    new_width_height:=($dim_list)[$>*2,2]
    r[$>] $new_width_height,2,100%,0,0,1,1
   done
  fi
 
 fi
 
else

 if $base_a!=10 rep_concat_conset_fill_alt_base $startnum_a,$base_a
 else rep_concat_conset_fill $startnum_a
 fi
 
 out_method=${arg\ $method_a+1,add_concat_conset,sub_concat_conset,mul_concat_conset}
 
 rep_element_$out_method $startnum_a,$base_a
 
 if ${is_image_arg\ $8} 
  pass$8 0
  if h#-1>1||d#-1>1
   num_of_chans={s#-1}
   permute. cxyz
   unroll. x
   {w#-1/$num_of_chans},1,1,$num_of_chans,crop(#-1,x*$num_of_chans,0,0,0,$num_of_chans,1,1,1)
   rm..
  elif w#-1==1 error inv_dims
  fi
  if $10 r. $base_a,1,1,100%,5 fi
 fi
 
 if ${is_image_arg\ $9} 
  pass$9 0
  if h#-1>1||d#-1>1
   num_of_chans={s#-1}
   permute. cxyz
   unroll. x
   {w#-1/$num_of_chans},1,1,$num_of_chans,crop(#-1,x*$num_of_chans,0,0,0,$num_of_chans,1,1,1)
   rm..
  elif w#-1==1 error inv_dims
  fi
  if $10 r. $base_a,1,1,100%,5 fi
 fi
 
 if $use_shape
  $shape
  if $!>3 error only_one_pal
  else
  
   {w#0*$shape_size},{h#0*$shape_size},1,{s#-2+1}
   
   img_count={$!}
   
   eval[0] :"begin(
     const shape_size=$shape_size;
     const tile_boundary=$tile_boundary;
     const num_chan=s#1;
     const tchan=num_chan+1;
     const tile_size=sqr(shape_size)*num_chan;
     $img_count==4?(
      generate_color()=I(#-3,i,0,0,0,2);
     ):(
      generate_color()=[i];
     );
     tile_boundary==3?(
      alpha_0=crop(#-2,0,0,0,0,shape_size,shape_size,1,1)*255;
      alpha_1=crop(#-2,0,0,1,0,shape_size,shape_size,1,1)*255;
      alpha_2=crop(#-2,0,0,2,0,shape_size,shape_size,1,1)*255;
      alpha_3=crop(#-2,0,0,3,0,shape_size,shape_size,1,1)*255;
      const mx=w-1;
      const my=h-1;
      const startnum=$startnum_a;
      find_pos()=1+sum((mx-x)%2,2*((my-y+startnum)%2));
      generate_tile()=(
       alpha=arg(find_pos(),alpha_0,alpha_1,alpha_2,alpha_3);
       color=generate_color();
       color_tile=resize(color,tile_size,1);
       tile=[color_tile,alpha];
       draw(#-1,tile,x*shape_size,y*shape_size,0,0,shape_size,shape_size,1,tchan); 
      );
     ):
     tile_boundary?(
      alpha_0=crop(#-2,0,0,0,0,shape_size,shape_size,1,1)*255;
      alpha_1=crop(#-2,0,0,1,0,shape_size,shape_size,1,1)*255;
      const max_index=(tile_boundary%2)?w-1:h-1;
      tile_boundary%2?(
       find_pos()=(max_index-x)%2;
      ):(
       const startnum=$startnum_a;
       find_pos()=(max_index-y+startnum)%2;
      );
      generate_tile()=(
       alpha=find_pos()?alpha_1:alpha_0;
       color=generate_color();
       color_tile=resize(color,tile_size,1);
       tile=[color_tile,alpha];
       draw(#-1,tile,x*shape_size,y*shape_size,0,0,shape_size,shape_size,1,tchan);      
      );
     ):(
      alpha=crop(#-2,0,0,0,0,shape_size,shape_size,1,1)*255;
      generate_tile()=(
       color=generate_color();
       color_tile=resize(color,tile_size,1);
       tile=[color_tile,alpha];
       draw(#-1,tile,x*shape_size,y*shape_size,0,0,shape_size,shape_size,1,tchan);
      );
     );
    );
    if(i>=0,generate_tile(););"
    
  fi
  k.
  
 else
 
  if $!==2
   {w#-2},{h#-2},1,{s#-1+1},"v=i(#-2,x,y,z,0);
    v>=0?[I(#-1,v,0,0,2,1),255]:vector(#s,0);"
   rm[-3,-2]
  elif $!>2 error only_one_pal
  fi
 
  if ($shape_size>1)||($num_of_images>1) 
   r. {w#-1*$shape_size},{h#-1*$shape_size},$num_of_images,100%,1 
  fi

 fi
 
 if $num_of_images>1 s. z fi
 
 if $use_different_dimensions
  repeat $num_of_images
   new_width_height:=($dim_list)[$>*2,2]
   r[$>] $new_width_height,1,100%,0,0,1,1
  done
 fi
 
fi
#@cli rep_element_mul_concat_conset: start_num,_base
#@cli : Element-wise multiplication onto concat_conset image. This is not accurate, but correct in most places.
#@cli : Default values: '_int_base=10'
rep_element_mul_concat_conset:
skip ${2=10}
+channels 0
1,{h},1,1,"begin(
  const length=w#-1;
  const hh=h#-1-1;
  const startnum=int(abs($1));
  const start_x=length-1;
  const start_pos=start_x-1;
  const base=int(abs($2));
  logb(n)=log(n)/log(base);
  concat_consec_digits_count(n)=n>=base?(t=floor(logb(n));n+(n+1)*t+(base*(1-base^t))/(base-1)):n;   
 );

 N=hh-y+startnum;
 num_of_digits=concat_consec_digits_count(N);
 tx=max(0,length-num_of_digits);

 for(p=start_pos,p>=tx,p--,
 
  multiplier=i(#-2,p,y,0,1);
  off=0;
  carry_over=0;
  secondary_carry_over=0;
 
  multiplier?(
   for(q=start_x,q>=tx,q--,
    partial_result=multiplier*i(#-2,q,y,0,0)+carry_over;
    remainder=partial_result%base;
    carry_over=int(partial_result/base);
    new_num=max(0,i(#-1,p-off,y,0,0))+remainder+secondary_carry_over;
    secondary_remainder=new_num%base;
    secondary_carry_over=int(new_num/base);
    i(#-1,p-off,y,0,0)=secondary_remainder;
    off++;
    if((p-off)<0,continue(););
   );
  ):(continue(););
  
  if(secondary_carry_over&&(q!=0),
   new_num=max(0,i(#-1,p-off,y,0,0))+secondary_remainder+secondary_carry_over;
   secondary_carry_over=int(new_num/base);
   secondary_remainder=new_num%base;
   i(#-1,p-off,y,0,0)=secondary_remainder;
  );
  
  if(p==tx&&(partial_result>base)&&(tx!=0),i(#-1,p-off,y,0,0)=int(partial_result/base););

 );"
rm[-3,-1]
#@cli rep_element_sub_concat_conset: start_num,_base
#@cli : Element-wise subtraction onto concat_conset image.
#@cli : Default values: '_int_base=10'
rep_element_sub_concat_conset:
skip ${2=10}
{w},{h},1,1,-1
1,{h},1,1,"begin(
  const length=w#-1;
  const hh=h#-1-1;
  const startnum=int(abs($1));
  const start_x=length-1;
  const base=int(abs($2));
  logb(n)=log(n)/log(base);
  concat_consec_digits_count(n)=n>=base?(t=floor(logb(n));n+(n+1)*t+(base*(1-base^t))/(base-1)):n;
  zero_fill=vector(#length,0);
 );
 N=hh-y+startnum;
 num_of_digits=concat_consec_digits_count(N);
 tx=max(0,length-num_of_digits);
 minuend=-1;
 if(num_of_digits>1,
  ux=tx;
  repeat(length,
   vd=I(#-2,ux,y);
   if(vd[1]>vd[0],minuend=1;break(););
   if(vd[0]>vd[1],minuend=0;break(););
   ux++;
  );
  if(minuend!=-1,
   subtrahend=1-minuend;
   ix=start_x;
   repeat(num_of_digits,
    vd=I(#-2,ix,y);
    if(ix==tx,if(vd[minuend]==vd[subtrahend],break();););
    if(vd[minuend]<vd[subtrahend],
     vd[minuend]+=base;
     sx=ix;
     repeat(inf,
      sx--;
      if(sx<=tx,break(););
      if(i(#-2,sx,y,0,minuend),(i(#-2,sx,y,0,minuend)--;break();),i(#-2,sx,y,0,minuend)=base-1;);
     );
    );
    i(#-1,ix,y,0,0)=vd[minuend]-vd[subtrahend];
    ix--;
   );
  ,draw(#-1,zero_fill,0,y,0,0,length,1,1,1);0;
  );
 ,i(#-1,start_x,y,0,0)=0;
 );"
rm[-1,-3]
#@cli rep_element_add_concat_conset: start_num>0,_int_base>0
#@cli : Element-wise addition only on absolute numbers starting from the right. This one factors into base.
#@cli : Default values: '_int_base=10'
rep_element_add_concat_conset:
skip ${2=10}
{w},{h},1,1,-1
1,{h},1,1,:"begin(
  const length=w#-1;
  const hh=h#-1-1;
  const start_x=length-1;
  const startnum=int(abs($1));
  const base=int(abs($2));
  const s_size=s#-2;
  const ds_size=s_size-1;
  vz=vector(#s_size,0);
  logb(n)=log(n)/log(base);
  concat_consec_digits_count(n)=n>=base?(t=floor(logb(n));n+(n+1)*t+(base*(1-base^t))/(base-1)):n;
 );
 ix=start_x;
 carry_over=0;
 loop_break=0;
 N=hh-y+startnum;
 num_of_digits=concat_consec_digits_count(N);
 tx=max(0,length-num_of_digits);
 repeat(min(length,num_of_digits+ds_size),
  init_num_vec=I(#-2,ix,y);
  if(ix<tx,
   repeat(s_size,p,
    if(init_num_vec[p]<0,loop_break=1;break(););
    );
   if(!carry_over&&loop_break,break(););
  );
  num=sum(vmax(init_num_vec,vz))+carry_over;
  carry_over=int(num/base);
  i(#-1,ix,y)=num%base;
  if(loop_break,break(););
  ix--;
 );"
rm[-3,-1]
#@cli rep_concat_conset_fill: start_num
rep_concat_conset_fill:

check $!==1

startnum={max(abs($1),1)}
maxnum_a,maxnum_b,string_a,string_b=$startnum,{$startnum+(h-1)},"",""

repeat inf
 string_a.=$maxnum_a
 maxnum_a-=1
 if $maxnum_a==1||size('$string_a')>=w#0
  startnum,string_a={max($maxnum_a,1)},""
  break
 fi
done

repeat inf
 string_a..=$maxnum_b
 ({size('$maxnum_b')})
 if $> a[-2,-1] x fi
 maxnum_b-=1
 if $maxnum_b<$startnum break fi
done

ts,digits={is#-1},0

repeat inf
 string_b..={$>+1}
 digits+={size('{$>+1}')}
 if $digits>=$ts||$digits>w#0 break fi
done

('$string_a') ('$string_b') -[-2,-1] 48

repeat h#0
 ns={w#-2-i(#-3,$>)}
 if w#-2>w#-1
  j[0] [-2],1~,$>,0,0
  j[0] [-1],1~,$>,0,1
 else
  r. {w#-2},100%,100%,100%,0,0,1
  j[0] [-2],1~,$>,0,0
  j[0] [-1],1~,$>,0,1
 fi
 if $ns r.. $ns,100%,100%,100%,-1 
 else break 
 fi
done

rm[-3--1]

#@cli rep_concat_conset_fill_alt_base: start_num,base
rep_concat_conset_fill_alt_base:

check $!==1

startnum={max(abs($1),1)}
maxnum_a,maxnum_b=$startnum,{$startnum+(h-1)}

repeat inf
 +rep_num2altbase $maxnum_a,$2
 if $> a[-2,-1] x fi
 maxnum_a-=1
 if $maxnum_a<=1||w#-1>=w#0
  startnum={max($maxnum_a,1)}
  rm.
  break
 fi
done

repeat inf
 +rep_num2altbase $maxnum_b,$2
 nv={w#-1}
 if $> rv[-3,-1] a[-3,-1] x fi
 ($nv)
 if $> a[-2,-1] x fi
 maxnum_b-=1
 if $maxnum_b<$startnum break fi
done

ts={is#-1}

repeat inf
 +rep_num2altbase {$>+1},$2
 if $> rv[-2,-1] a[-2,-1] x fi
 if w#-1>=$ts||w#-1>w#0 break fi
done

repeat h#0
 ns={w#-3-i(#-2,$>)}
 if w#-3>w#-1
  j[0] [-3],1~,$>,0,0
  j[0] [-1],1~,$>,0,1
 else
  r. {w#-3},100%,100%,100%,0,0,1
  j[0] [-3],1~,$>,0,0
  j[0] [-1],1~,$>,0,1
 fi
 if $ns r... $ns,100%,100%,100%,-1 
 else break 
 fi
done

rm[-3--1]
#@cli +rep_num2altbase: abs_num,base,start_num
#@cli : Insert number in bases other than 10. Each digit is represented by the character at ASCII codepoint (start_num)+(digit value).
+rep_num2altbase:

num,base={abs($1)},{abs($2)}
digits={1+int(log($num)/log($base))}

repeat $digits
 rem={$num%$base}
 num/=$base
 ({int($rem)})
 if $>
  rv[-2,-1]
  a[-2,-1] x
 fi
done
2 Likes

New Filter! Mitchell Concatenation

Take a look at the lines of code to do both the GUI and CLI version

Hmm, where do I start with this? - The Amazing, Autotuning Sandpile - Nautilus | Science Connected

That doesn’t look easily feasible in G’MIC.

1 Like

There is a bunch of repositories on GitHub if you search.

Maybe a start :

foo :
  palette jet r. 5,1,1,3,1 n. 0,255 point. 0
  300,300 =. 1000000,50%,50%
  repeat inf
    f. ":i>4?critical(++j(-1); ++j(1); ++j(0,-1); ++j(0,1); i - 4):i"
    if !($>%500) +c. 0,4 map. ... w. rm. fi
  done

Not really hard to code, but takes forever :wink:

After several hours of computation, this is what I get. This is ugly, but correct I guess.

3 Likes

If it takes that long, then it’s not worth completing for G’MIC, then.

Here’s something I may look into the future:

This is Hitomezashi, but triangle instead. All of the possible variants of Hitomezashi:

  1. Squares (Done)
  2. Cubes (Easily doable with modifying squares version)
  3. Triangles (All I know is that this requires 2 2D array. Draw a triangle grid, and count the number of triangles of same orientation in each level. Now count the diagonals in each level. That proves it needs 2 2D array. Or maybe it needs one where 2 areas are used for different orientations.)
  4. Pyramid of 3-side (I think this require 2 3D array. It is not known yet.)

In addition, with 3 and 4. It is not easy to label them using said array.

1 Like