Can window have negative view? (Feature Request) [SOLVED]

While doing dla, I wish that I have the option to view the negated view of a layer instead. run('negate.. w[2] w#-2,h#-2,0 negate.. '); makes my whole command fail to work as expected. If I take out negate…, it does something. So, I would like to view a layer as a negative instead. It would take a huge amount of time to finally figure out how to fix this command so that it can work with $7==1 and the preview image doesn’t look inverted.

Not sure how I can fix this
#@cli rep_dla : eq. to 'rep_diffusion_limited_aggregation' : (+)
rep_dla: rep_diffusion_limited_aggregation $*
#@cli rep_diffusion_limited_aggregation: imgs==1 ? { _radius_in_space,_escape,_mode,use_original_image,_dilate,_keep_erase_mask,_negate } : { _density,_escape,_mode,[map],_dilate,_keep_erase_mask,_negate}
#@cli : Generate Diffusion Limited Aggregation
#@cli : (eq. to 'rep_dla').\n
#@cli : '_radius_in_space' 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 : '_use_original_image' is used when there is only one image. This means if the image should be used as a planting seed for aggregation form. Otherwise, aggregation form will aggregate from the center.
#@cli : '[map]' is used as a map for planting seed of aggregation form. Only applicable if there is more than one image. If an image argument is not used, then the form will aggregate from the center of the image. 
#@cli : '_dilate' is only applicable if there is a planting seed map. It is used to limit particles based on proximity away from existing structure.
#@cli : '_keep_erase_mask' is only applicable if there is a planting seed map. This means if the existing structure will be kept or erased after the aggregation form is completed.\n
#@cli : Author: Reptorian\n
#@cli : Default values: '_radius_in_space=2','_escape=80','_mode=1','_use_original_image=1','_dilate=0','_keep_erase_mask=1'
rep_diffusion_limited_aggregation:
skip ${1=2},${2=80},${3=0},${4=1},${5=0},${6=1},${7=0}

include_dla_map=${"is_image_arg $4"}
activate_remove_last=0

use_original_image=0

world_width=${-max_w}
world_height=${-max_h}

if $!==1 
activate_remove_last=1
if iv#0&&$4 use_original_image=1 fi
fi

$world_width,$world_height,1,1

if $include_dla_map||$use_original_image
 if $include_dla_map pass$4 0
 else pass[0] 0 include_dla_map=1
 fi
 if s==2
  s. c *[-2,-1]
 elif s==3
  l. n 0,1 s c add / 3 endl
 elif s>3
  l. ts={s-1} s c add[^-1] /.. $ts * endl
 fi
 store. __dla_map 
fi

l. .

 image_width={w}
 image_height={h}

 noise_poissondisk.. {max($1,2)},10
 nm.. target
 
 if $include_dla_map
 
  $__dla_map
  
  half_max={iM#-1/2}
  
  f. i>=$half_max?1:0
  
  
  r. $image_width,$image_height,1,1,0,0,.5,.5
  
 if $5 
   +dilate_circ. $5
   f[-4] "i0#-1!=i0#-2?i"
   rm[-3,-1]
  else f.. "!i0#-1?i" rm..
  fi
  if !$6 f. i*.001 fi
 else
  
  f.. "begin(
   const ww=w-1;
   const hh=h-1;
  );
  xx=((x/ww)-.5)*2;
  yy=((y/hh)-.5)*2;
  sqrt(xx^2+yy^2)<1?i;
  "

  eval "
   const cx = round((w#-1-1)/2); 
   const cy = round((h#-1-1)/2);
   i(#-1,cx,cy)=1;
   i(#-2,cx,cy)=0;
  "
  
 fi
 
 extract.. "i==1",1
 
 r.. 100%,100%,100%,2
 
 if !$include_dla_map
  nm.. target
 
  +f.. "begin(
  const ww="$image_width";
  const hh="$image_height";
  const cx=ww/2;
  const cy=hh/2;
  );
  px=((i0-cx)/ww)*2;
  py=((i1-cy)/hh)*2;
  sqrt(px^2+py^2); 
  "
  sh. 0 pixelsort[target] -,x,[-1] rm[-2,-1]
 fi
 
  if $3==0 mode=(i(#-2,xp-1,yp-1,0,0,2)||i(#-2,xp-1,yp+1,0,0,2))||(i(#-2,xp+1,yp-1,0,0,2)||i(#-2,xp+1,yp+1,0,0,2))
  elif $3==1 mode=(i(#-2,xp-1,yp,0,0,2)||i(#-2,xp+1,yp,0,0,2))||(i(#-2,xp,yp-1,0,0,2)||i(#-2,xp,yp+1,0,0,2))
  elif $3==2 mode=((i(#-2,xp-1,yp,0,0,2)||i(#-2,xp+1,yp,0,0,2))||(i(#-2,xp,yp-1,0,0,2)||i(#-2,xp,yp+1,0,0,2)))||((i(#-2,xp-1,yp-1,0,0,2)||i(#-2,xp-1,yp+1,0,0,2))||(i(#-2,xp+1,yp-1,0,0,2)||i(#-2,xp+1,yp+1,0,0,2)))
  elif $3==3 mode=(altern%2?(i(#-2,xp-1,yp-1,0,0,2)||i(#-2,xp-1,yp+1,0,0,2))||(i(#-2,xp+1,yp-1,0,0,2)||i(#-2,xp+1,yp+1,0,0,2)):(i(#-2,xp-1,yp,0,0,2)||i(#-2,xp+1,yp,0,0,2))||(i(#-2,xp,yp-1,0,0,2)||i(#-2,xp,yp+1,0,0,2)))
  fi
 
 1,1,1,2
 
 eval ${-math_lib}"
  const ww=w#-2;
  const hh=h#-2;
  const w2=ww*2;
  const h2=hh*2;
  const lim_atmp=$2;
  const use_altern=$3==3;
  const use_negate=$7;
  altern=round(u(0,1));
  attempts=0;
  newpos_x=[-1,-1,-1,0,0,1,1,1];
  newpos_y=[-1,0,1,-1,1,-1,0,1];
  for(p=0,p<h#0,p++,dar_insert(#-1,I(#0,0,p)););
  do(n=0;
   do(
    temp_vec=I(#-1,0,n);
    
    xp=temp_vec[0];
    yp=temp_vec[1];
    
    if("$mode",
     i(#-2,xp%ww,yp%hh)=1;
     dar_remove(#-1,n);
     n--;
     attempts=0;
     );    
    n++;
   ,n<dar_size(#-1)
   );
   
   for(p=0,p<dar_size(#-1),p++,
    temp_vec=I(#-1,0,p);
    px=temp_vec[0];
    py=temp_vec[1];
    pv=round(u(0,7));
    npx=newpos_x[pv];
    npy=newpos_y[pv];
    I(#-1,0,p)=[px+npx,py+npy];
   );
   if(!attempts,
    run('w[-2] w#-2,h#-2,0');
    );
   attempts++;
   if(use_altern,altern++;);
   run('echo ',attempts);
  ,dar_size(#-1)&&(attempts<lim_atmp)
  );
 "
 echo pass
 if !$6 f.. i==1?i fi
 k..
endl

if $activate_remove_last k. fi

I get a flash of a window instance then nothing but an error. Output:

gmic sp tiger,flower,dog negate.. w[2] w#-2,h#-2,0 negate..
[gmic]-0./ Start G'MIC interpreter.
[gmic]-1./ Input sample image 'tiger' (1 image 750x500x1x3).
[gmic]-2./ Input sample image 'flower' (1 image 640x600x1x3).
[gmic]-3./ Input sample image 'dog' (1 image 1024x685x1x3).
[gmic]-1./ Negate values of image [1].
[gmic]-3./ Display image [2] in 1024x685 display window [0], with auto-normalization, no fullscreen and title '[G'MIC] Window #0'.
[gmic]-3./ Input file 'w#-2' at position 3
[gmic]-3./ *** Error *** Command 'input': File 'w#-2', format does not take any input options (options 'h#-2,0' specified).

Not correct, w#-2 and h#-2 must be evaluated by the math parser, if you want to replace them by their values (otherwise, they are just strings), so:

$ gmic sp tiger,flower,dog negate.. w[2] {w#-2},{h#-2},0 negate..

Probably the same issue here, so I suggest:

run('+negate.. w. {w},{h},0 rm.');

Ah, I just copied and pasted. :sweat_smile:

Before considering such a feature-request, there are a lot of problems with writing

run('negate.. w[2] w#-2,h#-2,0 negate.. ');

(apart from the fact you forgot the braces around w#-2 and h#-2).

  1. Why w[2] rather than w[-2] (or w..) ? Is the image [-2] the same as your image [2] ? If so, it’s really dangerous to write code like this. If you insert an additional image somewhere between [0] and [2], you’ll display the wrong image, possibly with the wrong image dimensions. It’s better to use relative indices, particularly when you are creating a new image at the end of the list. Absolute indices is also nice, but then used everywhere. Mixing absolute and relative indices will only bring you problems in the long run.

  2. It is rarely relevant to explicitly specify the size of the viewer window, when using command window. This indeed prevents the window from being resized in practice, for instance when using command window in a loop: the window size will be reset at each iteration of the loop. Just set -1 for the window width and height, and the command will display the image in a window with the correct size, and the user will be able to resize the window without problems.

  3. Using twice negate is slower than using it with +negate, because you are processing the image in-place twice, while you only need to process it once for the display. So, +negate.. w. -1,-1,0 rm. is definitely better (shorter and faster).