Reptorian G'MIC Filters

Imma save my code here. Not ready for production use. Easier to read, faster too.

Saving rep_dla refactored code here
#@cli rep_dla : eq. to 'rep_diffusion_limited_aggregation' : (+)
rep_dla_new: rep_diffusion_limited_aggregation_new $*
#@cli rep_diffusion_limited_aggregation: _point_proximity,_escape,_mode,_target={ 0=dark | 1=light },_border,_preserve_binary_image={ 0=maskless | 1=mask }
#@cli : Generate Diffusion Limited Aggregation
#@cli : (eq. to 'rep_dla').\n
#@cli : '_point_proximity' defines how frequently noises are generated based on the proximity of pixels. The lower the number, the higher the density.
#@cli : '_escape' defines how much attempts on filling the aggregation form before finishing.
#@cli : '_mode' defines how particles aggregate on the aggregation form.
#@cli : '_target' defines where the aggregation form will fill on.
#@cli : '_border' is only applicable if there is a planting seed map. It is used to limit particles based on proximity away from existing structure.
#@cli : '_preserve_binary_image' is only applicable on images with variance.
#@cli : Author: Reptorian.
#@cli : Default values: '_point_proximity=2','_escape=10','_mode=1','_target=1','_border=0','_keep_erase_mask=1','[mask]=0'
rep_diffusion_limited_aggregation_new:
skip ${1=2},${2=100},${3=1},${4=0},${5=0},${6=1}

bg,use_altern_text={$4?1:0},{($3%4)==3}

m "dla_target_2s : n 0,1 s. c * midpoint={avg(iM,im)} f. i>$midpoint?1"
m "dla_target_3s : n 0,1 s c add / 3 midpoint={avg(iM,im)} f. i>$midpoint?1"
m "dla_target_4s_plus : n 0,1 ts={s-1} s c add[^-1] /.. $ts * midpoint={avg(iM,im)} f. i>$midpoint?1"
m "dla_target : if s==1 n 0,1 elif s==2 dla_target_2s elif s==3 dla_target_3s elif s>3 dla_target_4s_plus fi"
m "dla_check_variance : tv=0 repeat s sh $> tv+={iv#-1} rm. if $tv break fi done u {$tv?1:0}"
m "dla_clear_image : {w#0},{h#0},1,1,"{$4?0:1}" rv[-1,0] rm."

if $use_altern_text 
 altern_text_a=altern=int(u(0,2))
 altern_text_b=altern=++altern%2 
fi

n_threads,border={$_cpus},{round(abs($5))}
mt={$n_threads-1}

foreach {

 if s>4||d#0>1 continue fi

 +dla_create_coordinate_map $1
 gcd_shuffle.

 use_dla_map=${dla_check_variance[0]}

 if $use_dla_map

  dla_target[0]

  if !$6
   if $4
    *[0] .001
   else
    replace[0] 0,.999
   fi
  fi
  
  if $border
   if $4 +dilate_circ[0] $border
   else  +erode_circ[0] $border
   fi
   
   1,{h},1,1,y
   eval[-3] :if(i(#0,I)==i(#-2,I),i(#-1,0,y)=-1);I;
   map[-1] [-3]
   rv[-3,-1]
   rm[-2,-1]
   
  else
   if $4 val_check=>.999
   else  val_check=<.001
   fi
   
   1,{h},1,1,y
   eval.. :if(!(i(#0,I)$val_check),i(#-1,0,y)=-1;);I;
   discard. -1
   map. ..
   rm..
   
   +distance[-2] {!$4},2
   1,{h#-2},1,1,i(#-1,I(#-2))
   rm[-2]
   pixelsort[-2] +,y,[-1]
   rm[-1]
   1,{h},1,1,:"begin_t(const n_threads=$n_threads;n=t;);v=n;n+=n_threads;v;"
   map. ..
   rm..
   
  fi

 else
 
  center_x,center_y={[(w#0-1)>>1,(h#0-1)>>1]}
  
  1,{h},1,1,norm(I#-1-[$center_x,$center_y])
  pixelsort.. +,y,.
  rm.

  dla_clear_image
  set[0] $bg,50%,50%

 fi
 
 a[^0] y
 
 eval[1] :"begin_t(
   const width=w#0;
   const height=h#0;
   const limit_of_attempts=$2;
   const pixel_detection_mode=$3%4;
   const target_mode=!($4&1);
   new_pos_x=[-1, 0, 1,
              -1,    1,
              -1, 0, 1];
   new_pos_y=[-1,-1,-1,
               0,    0,
               1, 1, 1];
   !target_mode?(
    pixel_detection_mode==3?(
     pixel_detected()=
      altern?(
       i(#0,xp-1,yp-1,0,0,0,2)<1||
       i(#0,xp-1,yp+1,0,0,0,2)<1||
       i(#0,xp+1,yp-1,0,0,0,2)<1||
       i(#0,xp+1,yp+1,0,0,0,2)<1
      ):(
       i(#0,xp-1,yp,0,0,0,2)<1||
       i(#0,xp+1,yp,0,0,0,2)<1||
       i(#0,xp,yp-1,0,0,0,2)<1||
       i(#0,xp,yp+1,0,0,0,2)<1
      );
    ):
    pixel_detection_mode==2?(
     pixel_detected()=
      i(#0,xp-1,yp-1,0,0,0,2)<1||
      i(#0,xp-1,yp+1,0,0,0,2)<1||
      i(#0,xp+1,yp-1,0,0,0,2)<1||
      i(#0,xp+1,yp+1,0,0,0,2)<1||
      i(#0,xp-1,yp,0,0,0,2)<1||
      i(#0,xp+1,yp,0,0,0,2)<1||
      i(#0,xp,yp-1,0,0,0,2)<1||
      i(#0,xp,yp+1,0,0,0,2)<1;
    ):
    pixel_detection_mode==1?(
     pixel_detected()=
      i(#0,xp-1,yp,0,0,0,2)<1||
      i(#0,xp+1,yp,0,0,0,2)<1||
      i(#0,xp,yp-1,0,0,0,2)<1||
      i(#0,xp,yp+1,0,0,0,2)<1;
    ):(
     pixel_detected()=
      i(#0,xp-1,yp-1,0,0,0,2)<1||
      i(#0,xp-1,yp+1,0,0,0,2)<1||
      i(#0,xp+1,yp-1,0,0,0,2)<1||
      i(#0,xp+1,yp+1,0,0,0,2)<1;
    );
   ):(
    pixel_detection_mode==3?(
     pixel_detected()=
      altern?(
       i(#0,xp-1,yp-1,0,0,0,2)||
       i(#0,xp-1,yp+1,0,0,0,2)||
       i(#0,xp+1,yp-1,0,0,0,2)||
       i(#0,xp+1,yp+1,0,0,0,2)
      ):(
       i(#0,xp-1,yp,0,0,0,2)||
       i(#0,xp+1,yp,0,0,0,2)||
       i(#0,xp,yp-1,0,0,0,2)||
       i(#0,xp,yp+1,0,0,0,2)
      );
    ):
    pixel_detection_mode==2?(
     pixel_detected()=
      i(#0,xp-1,yp-1,0,0,0,2)||
      i(#0,xp-1,yp+1,0,0,0,2)||
      i(#0,xp+1,yp-1,0,0,0,2)||
      i(#0,xp+1,yp+1,0,0,0,2)||
      i(#0,xp-1,yp,0,0,0,2)||
      i(#0,xp+1,yp,0,0,0,2)||
      i(#0,xp,yp-1,0,0,0,2)||
      i(#0,xp,yp+1,0,0,0,2);
    ):
    pixel_detection_mode==1?(
     pixel_detected()=
      i(#0,xp-1,yp,0,0,0,2)||
      i(#0,xp+1,yp,0,0,0,2)||
      i(#0,xp,yp-1,0,0,0,2)||
      i(#0,xp,yp+1,0,0,0,2);
    ):(
     pixel_detected()=
      i(#0,xp-1,yp-1,0,0,0,2)||
      i(#0,xp-1,yp+1,0,0,0,2)||
      i(#0,xp+1,yp-1,0,0,0,2)||
      i(#0,xp+1,yp+1,0,0,0,2);
    );
   );
   "$altern_text_a"
  );
  temp_vec=I;
  xp=temp_vec[0];
  yp=temp_vec[1];
  repeat(limit_of_attempts,attempts,
   if(pixel_detected(),
    i(#0,xp,yp)=target_mode;
    break();
   );
   pv=int(u(0,8));
   xp+=new_pos_x[pv];
   yp+=new_pos_y[pv];
   xp%=width;
   yp%=height;
   "$altern_text_b"
  );
  [0,0];
  "

 k[0]

 if $use_dla_map&&!$6 round fi

}

um dla_target,dla_target_2s,dla_target_3s,dla_target_4s_plus,dla_create_coordinate_map
+dla_create_coordinate_map:
if $1
 row_a={ceil(h/2)}
 row_b={h-$row_a}
 counts_per_row_a,counts_per_row_b={[w,w+1]>>1}
 
 1,{$row_a*$counts_per_row_a+$row_b*$counts_per_row_b},1,2,:"begin(
   const row_length=w#-1;
   const half_row_length=row_length>>1;
  );
  pos_y=int(y/half_row_length);
  ny=y<<1;
  pos_x=pos_y&1?(ny%row_length):((ny+1)%row_length);
  [pos_x,pos_y];
  "
else
 1,{(w>>1)*(ceil(h/2))},1,2,:"begin(
   const row_length=w#-1;
   const half_row_length=row_length>>1;
  );
  y_pos=int(y/half_row_length)<<1;
  [(y<<1)%row_length,y_pos];
  "
fi

Also, thank you @garagecoder for making gcd_shuffle. This allows me to rearrange coordinate map pixels for more randomization.

Picture of refactored rep_dla result.
image

Hmm, it’s interesting how this flows along edge. I never made that feature in mind. Seem like it’s the result of distance-based sorting.

Also, I found that the new version is more beautiful. Here’s the old version result with identical setting.

image

Here’s the performance too:

C:\Windows\System32>gmic sp gmicky tic rep_dla_new 0,500,2,1 toc
[gmic]-0./ Start G'MIC interpreter.
[gmic]-1./ Input sample image 'gmicky' (1 image 600x601x1x3).
[gmic]-1./ Initialize timer.
[gmic]-1./ Elapsed time: 0.247 s.
[gmic]-1./ Display image [0] = 'gmicky'.
[0] = 'gmicky':
  size = (600,601,1,1) [1408 Kio of float32].
  data = (1,1,1,0,0,0,1,1,0,0,1,1,(...),0,1,1,1,0,0,0,1,1,1,1,1).
  min = 0, max = 1, mean = 0.579953, std = 0.493567, coords_min = (3,0,0,0), coords_max = (0,0,0,0).
[gmic]-1./ End G'MIC interpreter.

C:\Windows\System32>gmic sp gmicky tic rep_dla 0,500,2,0 toc
[gmic]-0./ Start G'MIC interpreter.
[gmic]-1./ Input sample image 'gmicky' (1 image 600x601x1x3).
[gmic]-1./ Initialize timer.
[gmic]-1./ Elapsed time: 1.497 s.
[gmic]-1./ Display image [0] = 'gmicky'.
[0] = 'gmicky':
  size = (600,601,1,1) [1408 Kio of float32].
  data = (1,1,1,0,1,0,1,1,1,1,1,1,(...),1,1,1,1,1,1,1,1,1,1,1,1).
  min = 0, max = 1, mean = 0.53822, std = 0.498538, coords_min = (3,0,0,0), coords_max = (0,0,0,0).
[gmic]-1./ End G'MIC interpreter.
2 Likes

Have a look at this sweet new code for rep_diffusion_limited_aggregation. Note there is a ‘_new’ next to command name, so it won’t interfere with current version. This will replace current version when I add a feature to randomly insert points via probability around appended points, and this will create thickening.

I say the code is sweet because it is easier to understand what’s going on and easier to add features or base new code off from. It’s faster too for all cases.

Also, I note that there is Laplacian Growth version, but I never was able to find code for it. Laplacian Growth is a much faster version for DLA.

image

The New Diffusion Limited Aggregation Code
$ {vector2(300)}  rep_diffusion_limited_aggregation_new 100,2,0,0,0,0
#@cli rep_dla : eq. to 'rep_diffusion_limited_aggregation' : (+)
rep_dla_new: rep_diffusion_limited_aggregation_new $*
#@cli rep_diffusion_limited_aggregation: _escape,_mode,_stem_color={ 0=dark | 1=light },_border,_initial_point_mode={ 0=less_dense | 1=more_dense },_preserve_binary_image={ 0=maskless | 1=mask }
#@cli : Generate Diffusion Limited Aggregation
#@cli : (eq. to 'rep_dla').
#@cli :
#@cli : '_escape' defines how much attempts on filling the aggregation form before finishing.
#@cli : '_mode' defines how particles aggregate on the aggregation form.
#@cli : '_stem_color' defines where the aggregation form will fill on.
#@cli : '_border' is only applicable if there is a planting seed map. It is used to limit particles based on proximity away from existing structure.
#@cli : '_initial_point_mode' defines whether to use less dense or more dense point coordinates map.
#@cli : '_preserve_binary_image' is only applicable on images with variance.
#@cli :
#@cli : Author: Reptorian.
#@cli : Default values: '_escape=10','_mode=1','_stem_color=1','_border=0','_keep_erase_mask=1','_initial_point_mode=1','_preserve_binary_image=1'
rep_diffusion_limited_aggregation_new:
skip ${1=100},${2=0},${3=0},${4=0},${5=1},${6=1}

maximum_iterations,pixel_detection_mode,stem_color,border_size,initial_coordinates_map_mode,preserve_silhouette_mode={[abs($1),int($2)%4,!$3,round(abs($4)),$5?1,$6?1]}
inv_stem_color,use_altern_text,n_threads={[!$stem_color,$pixel_detection_mode==3]},$_cpus

m "dla_target_1s:
   ge {avg(iM,im)}
  "
m "dla_target_2s:
    normalize 0,1
    split[-1] c *
    ge {avg(iM,im)}
  "
m "dla_target_3s:
    normalize 0,1
    split c
    add / 3
    ge {avg(iM,im)}
  "
m "dla_target_4s:
    normalize 0,1
    ts={s-1}
    split c
    add[^-1]
    /[-1] $ts *
    ge {avg(iM,im)}
  "
m "dla_target:
    if s==1   dla_target_1s
    elif s==2 dla_target_2s
    elif s==3 dla_target_3s
    else      dla_target_4s
    fi
  "
m "dla_check_variance:
    tv=0

    repeat s {
     shared $>
     tv+={iv#-1}
     rm.

     if $tv
      break
     fi
    }

    status {$tv?1:0}
  "
m "dla_clear_image:
   {w#0},{h#0},1,1,"$stem_color"
   rv[-1,0]
   rm.
  "

if $use_altern_text
 altern_text_a=altern=int(u(0,2))
 altern_text_b=altern=++altern%2
fi

foreach

 if s>4||d#0>1 continue fi

 +dla_create_coordinate_map $initial_coordinates_map_mode
 gcd_shuffle.

 use_dla_map=${dla_check_variance[0]}

 if $use_dla_map

  dla_target[0]

  if $border_size
   +distance.. $inv_stem_color,2
   1,{h#-2},1,1,v=i(#-1,I(#-2));v?(v<=$border_size?y:-1):-1
   discard. -1
   map. ...
   1,100%,1,1,i(#2,I(#-1))
   rm[-4,-3]
   pixelsort.. +,y,.
   rm.
   1,100%,1,1,:"begin_t(const n_threads=$n_threads;n=t;);v=n;n+=n_threads;v;"
   map. ..
   rm..

   if !$preserve_silhouette_mode
    if $stem_color
	 replace[0] 0,.999
    else
     *[0] .001
    fi
   fi

  else
   if $stem_color val_check=>.999
   else  val_check=<.001
   fi

   1,{h},1,1,y
   eval.. :if(!(i(#0,I)$val_check),i(#-1,0,y)=-1;);I;
   discard. -1
   map. ..
   rm..

   +distance[-2] $inv_stem_color,2
   1,{h#-2},1,1,i(#-1,I(#-2))
   rm[-2]
   pixelsort[-2] +,y,[-1]
   rm[-1]
   1,100%,1,1,:"begin_t(const n_threads=$n_threads;n=t;);v=n;n+=n_threads;v;"
   map. ..
   rm..

   if !$preserve_silhouette_mode
    if $stem_color
	 replace[0] 0,.999
    else
     *[0] .001
    fi
   fi

  fi

 else

  center_x,center_y={[(w#0-1)>>1,(h#0-1)>>1]}
  minimum_circle_radius={norm($center_x,$center_y)}

  1,{h},1,2,"begin(
    const sqrt_of_two=sqrt(2);
    const minimum_circle_radius=$minimum_circle_radius;
    const center_x=$center_x;
    const center_y=$center_y;
   );
   distance_from_center=norm(I#-1-[$center_x,$center_y]);
   distance_from_center<=minimum_circle_radius?(
    relative_position=distance_from_center/minimum_circle_radius;
    valid_point=lerp(1,u^.625,relative_position)>=relative_position?y:-1;
   ):(
    valid_point=-1;
   );
   [distance_from_center,valid_point];
   "

  split[-1] c
  discard[-1] -1
  [-1]
  repeat 2 { map[{$>-2}] [{$>-4}] }
  remove[-4,-3]
  pixelsort[-2] +,y,[-1]
  remove[-1]
  1,100%,1,1,:"begin_t(const n_threads=$n_threads;n=t;);v=n;n+=n_threads;v;"
  map[-1] [-2]
  remove[-2]

  dla_clear_image
  set[0] $inv_stem_color,50%,50%
 fi

 a[^0] y

 eval[1] :"begin_t(
   const width=w#0;
   const height=h#0;

   const limit_of_attempts=$maximum_iterations;
   const pixel_detection_mode=$pixel_detection_mode;
   const target_mode=$inv_stem_color;

   new_pos_x=[-1, 0, 1,
              -1,    1,
              -1, 0, 1];
   new_pos_y=[-1,-1,-1,
               0,    0,
               1, 1, 1];

   if(!target_mode
   ,det_px(pixel)=pixel<1;
   ,det_px(pixel)=pixel;
   );

   pixel_detection_mode==3?(
    pixel_detected()=
     altern?(
      det_px(i(#0,xp-1,yp-1,0,0,0,2))||
      det_px(i(#0,xp-1,yp+1,0,0,0,2))||
      det_px(i(#0,xp+1,yp-1,0,0,0,2))||
      det_px(i(#0,xp+1,yp+1,0,0,0,2))
     ):(
      det_px(i(#0,xp-1,yp,0,0,0,2))||
      det_px(i(#0,xp+1,yp,0,0,0,2))||
      det_px(i(#0,xp,yp-1,0,0,0,2))||
      det_px(i(#0,xp,yp+1,0,0,0,2))
     );
    ):
   pixel_detection_mode==2?(
    pixel_detected()=
     det_px(i(#0,xp-1,yp-1,0,0,0,2))||
     det_px(i(#0,xp-1,yp+1,0,0,0,2))||
     det_px(i(#0,xp+1,yp-1,0,0,0,2))||
     det_px(i(#0,xp+1,yp+1,0,0,0,2))||
     det_px(i(#0,xp-1,yp,0,0,0,2))||
     det_px(i(#0,xp+1,yp,0,0,0,2))||
     det_px(i(#0,xp,yp-1,0,0,0,2))||
     det_px(i(#0,xp,yp+1,0,0,0,2));
   ):
   pixel_detection_mode==1?(
    pixel_detected()=
     det_px(i(#0,xp-1,yp,0,0,0,2))||
     det_px(i(#0,xp+1,yp,0,0,0,2))||
     det_px(i(#0,xp,yp-1,0,0,0,2))||
     det_px(i(#0,xp,yp+1,0,0,0,2));
   ):(
    pixel_detected()=
     det_px(i(#0,xp-1,yp-1,0,0,0,2))||
     det_px(i(#0,xp-1,yp+1,0,0,0,2))||
     det_px(i(#0,xp+1,yp-1,0,0,0,2))||
     det_px(i(#0,xp+1,yp+1,0,0,0,2));
   );

   "$altern_text_a"
  );

  temp_vec=I;

  xp=temp_vec[0];
  yp=temp_vec[1];

  repeat(limit_of_attempts,
   pv=int(u(0,8));

   xp+=new_pos_x[pv];
   yp+=new_pos_y[pv];
   xp%=width;
   yp%=height;

   if(pixel_detected(),
    i(#0,xp,yp)=target_mode;
    break();
   );

   "$altern_text_b"
  );

  I;
  "

 k[0]

 if $use_dla_map&&!$preserve_silhouette_mode round fi

done

um dla_target,dla_target_1s,dla_target_2s,dla_target_3s,dla_target_4s,dla_check_variance,dla_clear_image
+dla_create_coordinate_map:
if $1
 row_a={ceil(h/2)}
 row_b={h-$row_a}
 counts_per_row_a,counts_per_row_b={[w,w+1]>>1}

 1,{$row_a*$counts_per_row_a+$row_b*$counts_per_row_b},1,2,:"begin(
   const row_length=w#-1;
   const half_row_length=row_length>>1;
  );
  pos_y=int(y/half_row_length);
  ny=y<<1;
  pos_x=pos_y&1?(ny%row_length):((ny+1)%row_length);
  [pos_x,pos_y];
  "
else
 1,{(w>>1)*(ceil(h/2))},1,2,:"begin(
   const row_length=w#-1;
   const half_row_length=row_length>>1;
  );
  y_pos=int(y/half_row_length)<<1;
  [(y<<1)%row_length,y_pos];
  "
fi

EDIT: I realized my algorithm fails in one way. It seems that there isn’t as much perpendicular stem at all, and that is needed in case of empty image. Hmm, that needs to be addressed. I don’t know, but smaller images doesn’t have that problem:

image

I have added a new feature to Diffusion Limited Aggregation which is spread_factor. Basically, it thickens the stems.

image
image

Not sure how to exactly implement it, but I’ll take it.

EDIT: I pushed the upgrade to Diffusion Limited Aggregation.

Ok, I fixed spread factor, now it works properly:

image

Another example:

image

Looks like I have solved the pal problem. I am able to refactor it and remove 300+ subcommands. Speed is almost kept too. A tiny bit little slower, but not by far. Only noticeable via timer. Reasonable when considering multiple subcommands can slow everything else down. Never mind. Close though. I’ll just be keeping the current solution with a few update. Faster now at least.

Guess what I managed to create in G’MIC without the use of BIGINT library?

Still, some bugs though. I’m not sure how to properly convert a image representing a large number into a image of binary yet it seems. Ooh, so close. I wish dec2bin and bin2dec would allow for humongous digits for this case or something like that.

$ 106,17 rep_tupper
#@cli rep_tupper: k
#@cli : Generates output of K onto images.
rep_tupper:
skip ${1=960939379918958884971672962127852754715004339660129306651505519271702802395266424689642842174350718121267153782770623355993237280874144307891325963941337723487857735749823926629715517173716995165232890538221612403238855866184013235585136048828693337902491454229288667081096184496091705183454067827731551705405381627380967602565625016981482083418783163849115590225610003652351370343874461848378737238198224849863465033159410054974700593138339226497249461751545728366702369745461014655997933798537483143786841806593422227898388722980000748404719}
check "$#==1"
fill "y+x*h" mirror. x

decimal_number=$1

1 # 1. Insert Binary Here

1 # 2. Create single pixel image for use dynamic processing.

eval "
 number='$1';
 const divisor=h#0;
 const n_size=size(number);
 const n_0=_'0';
 index=0;
 dividend=number[index]-n_0;
 
 while(dividend<divisor,
  dividend=dividend*10+(number[++index]-n_0);
 );
 
 while(n_size>index,
  da_push(#-1,int(dividend/divisor)+n_0);
  dividend=(dividend%divisor)*10+(number[++index]-n_0);
 );
 
 da_push(#-2,(i[#-1,da_size(#-1)-1]-n_0)&1);
 ds=da_size(#-1);
 ds?da_freeze(#-1);
 "

decimal_number={t}

repeat inf {
 rm. 1 
 
 eval "
  number='"$decimal_number"';
  const divisor=2;
  const n_size=size(number);
  const n_0=_'0';
  index=0;
  dividend=number[index]-n_0;
 
  while(dividend<divisor,
   dividend=dividend*10+(number[++index]-n_0);
  );
 
  while(n_size>index,
   da_push(#-1,int(dividend/divisor)+n_0);
   dividend=(dividend%divisor)*10+(number[++index]-n_0);
  );

  da_push(#-2,(i[#-1,da_size(#-1)-1]-n_0)&1);
  ds=da_size(#-1);
  ds?da_freeze(#-1);
  "
  
  decimal_number={t}
  
  if h#-1==1 break fi 
}

rm. eval da_freeze(#-1)

map.. . rm.

EDIT: I fixed the bug. :slight_smile:

It looks like this fun filter is happening though I can’t imagine a real use case of this other than teaching students how loading and exporting file work.

Any one have a way of converting a image of binary number to a image that represents decimal number? All commands I know of so far can’t utilize huge binary number akin to ones that don’t fit in doubles.

For example, this:

1100000000000000011111011000000000011111110000000000000111100000000000000011000000000000000000001000000000000000110000000000000000000110000110000000001111101100000000001111111000000000000011100001111000000001000111110000000000001100101110000000011100111111000000011111001111000000011110000110000000000111101100000000000111110001000000000011000011110011000000000011111111110000000001111111110000000000010001100000000000000001000011100000011110001111110000111000010001110000000000110001100000000001111111000100000000111100011100000000000000111000111100000001110011111110000001000110001100000000001110001000000000001111110000000000000111000011100000000000000111000000000000000000011100110000000000111111100000000000001111000111100000000010011111100000000000110001011110000000111100111110000000111111000110000000000111000100011110000111111001111111000000000011000110000000000011110100000000000011111011001000000000000111110001111000000011100011111100000000000100001000000000001111110001110000001111100011110000000000000001100011110000001111001111110000011100011000110000000000011111100110000000011110001001000000000000011111000000000000001110011000100000000000111111000000000000000110001100000000000000011110000000000000000110011111000000001100100011000011010001110010001111000001111100010000000000000000111100000110000000111100111111000000001001000010001111100011111100010011000011111000110000000000000001111100000000000000000000000010000000000011111110000000100000111000111111000000000000000110000000000000000000111110000000000001100110001111100011000100110001100111111001111111000000000000111100000000000000000000000010000111100011111110011111100011111100110001000000000000111110000000000000000000000000000000000000000000000000000

Using bitwise shifting?

That would not work because doubles can only go up to 308 digits.

Couldn’t you split the large binary image/number?

I believe now I found a bug which explains my frustration. And it’s pretty strange. The strangest one I have ever seen. I will file a report.

Basically, it’s this - Math evaluator requires printing vector to output correct result. · Issue #428 · GreycLab/gmic · GitHub .

That is super strange.

Maybe look into BigInteger.

There is no BigInteger library in G’MIC. Hence, my need to work around that.

Integrate gmplib? :person_shrugging:

I’ll wait for David to see what he has to say about this bug. I’ll use a temporary set of code which is this line:

  v=crop(#0,x,0,0,0,1,height,1,1,0);
  n=carry_over+sum(crop(#0,x,0,0,0,1,height,1,1,0));

And it works. I have to do crop(#0,x,0,0,0,1,height,1,1,0); twice to get the correct result. No wonder my frustration.

I finished Tupper’s Self Referential Formula as a new showcase filter. Showcase here means to demonstrate capability of G’MIC as it’s not useful outside of that and it’s a fun filter too in terms of coding it in as there were challenges like the absence of BIGINT support. To be fair, BIGINT support would make this filter run much faster, and would work with images 300x300 well, and I’m not thinking of BIGINT support in content of math parser, but in content of ('create_string_here').

I have some ideas for that like specialized commands such as bigint_hex2dec,bigint_dec2bin,bigint_bin2dec,bigint_add,bigint_sub, and all of them parse a image as if they’re string, then output a image as if it was a string. But none of them would be used on math parser.

Now I am remaking a filter. It was made by @Joan_Rake1. I am now in the process of extending it.

image

Not much news, but I made a little command which converts a large integer number into base 16,777,216 as a image. This allows to do things similar to bigint library.

$ +rep_num2base_float_max 56525845877585816763039586007520750277353196450595841567735618780688400140898024981743696598491218713015714928398271962117249251816126135758313291996549277852226925632342583919395030421983352656778405325777741906072873874481412543269713885225217255170734791425252274534182128499770100304909062813395973629729728331022409858974448530410675416671693127285242093542682941391314786490816144814610513955188130873521380296068200591469100034890490542735132321279502689903923668808556530273882231399913969596693343635681966013405787571940000044023807 echo {crop(#-1)}

The following command creates a image with these values:

131071,4162048,3375332,9705540,83968,800,3145728,1605872,6,4194528,6,7936,8388608,262145,14680064,2097183,17920,5767184,131073,2040,1597440,3840,2031616,10240,112,114688,640,7,6144,7340040,8192,448,65536,512,16646144,131073,8389792,1212416,8396800,127,3584,100,126976,0,2228225,303106,2624,25,2097120,4595712,3313735,344,762,1048564,24576,1836848,2032,1032192,4608,3145764,0,4194496,294914,1536,3670016,2048,2097376,8634368,16711680,1023,8704,2097192,0,8135840,13273173

And according to Python, it checks out after comparing numbers.

v=[131071,4162048,3375332,9705540,83968,800,3145728,1605872,6,4194528,6,7936,8388608,262145,14680064,2097183,17920,5767184,131073,2040,1597440,3840,2031616,10240,112,114688,640,7,6144,7340040,8192,448,65536,512,16646144,131073,8389792,1212416,8396800,127,3584,100,126976,0,2228225,303106,2624,25,2097120,4595712,3313735,344,762,1048564,24576,1836848,2032,1032192,4608,3145764,0,4194496,294914,1536,3670016,2048,2097376,8634368,16711680,1023,8704,2097192,0,8135840,13273173]
vn=0
base=1<<24
num_mult=1
for n in v:
    vn += n*num_mult
    num_mult *= base
    
print(vn)

Yes, digits are reversed though.

Any news on the modf fix I wonder?

I have looked a bit into refactoring, but I have not yet solved it. So, I will let you know when it’s ready.

This is my current progress
#@cli modular_formula : operation,max_channel_value={ float_value | [image] },channel_values={ float_value(%) | [image] }
#@cli : Apply modular formulas into selected images. 'channel_value' can be values outside the channel ranges of image.
#@cli : When using a image argument to max_channel_value, the dimension should be equal to the spectrum of target images.
#@cli : When using a image argument to channel_value, it can be single spectrum or equal to the spectrum of target images.
#@cli : (eq. to 'modf').
#@cli : operation can be { 0=modulo | 1=modulo_continuous | 2=divisive | 3=divisive_continuous | 4=additive | 5=additive_continuous}
#@cli : In addition, they can be the corresponding string as argument.
#@cli : Author: Reptorian.
modular_formula_new:
if isint($1)
 modular_mode={int($1)%6}
else
  modulo,modulo_continuous,divisive,divisive_continuous,additive,additive_continuous=0,1,2,3,4,5
  modular_mode=$$1
  if !narg($modular_mode) error invalid_input fi
fi

max_images_index,utilize_max_channel_image,utilize_channel_values_image={$!-1},0,0

if ${is_image_arg\ $2} pass$2 1 name[-1] max_channel_image fi
if ${is_image_arg\ $3} pass$3 1 name[-1] channel_values_image fi

fill[0-$max_images_index] "begin(
  const modular_mode=$modular_mode;
  const epsilon=.00000000000000000000000001;

  if($utilize_max_channel_image,
   const max_channel_reference=$max_channel_image;
   s#max_channel_reference>1?(
    const max_channel=i(#max_channel_reference,0,0,0,0);
    const max_channel_mod=+epsilon;
    0;
   ):(
    max_channel=crop(#max_channel_reference)+epsilon;0;
   );
  ,
   const max_channel=$2+epsilon;
   0;
  );
  
  if($utilize_channel_values_image,
   const channel_value_reference=$channel_values_image;
   dividier()=max_channel/I(#channel_value_reference);
   modular_mode==0?( modular_output()=(I*dividier())%max_channel_mod;
   ):
   modular_mode==1?(
   ):
   modular_mode==2?(
   ):
   modular_mode==3?(
   ):
   modular_mode==4?(
   ):(
   );
   0;
  ,
   const dividier=$3;
   modular_mode==0?(
   ):
   modular_mode==1?(
   ):
   modular_mode==2?(
   ):
   modular_mode==3?(
   ):
   modular_mode==4?(
   ):(
   );
   0;
  );

 );
 I;
 "

keep[0-$max_images_index]
1 Like