G'MIC exercises

This is the error. 1 layer.


Let’s say I want to extrude pixel in 3d form at a specific distance, then at the bottom, it is a point in space with the point being a color and everything inbetween is a gradient from 4 or 2 channel image to the point color, then finally render the orthographic output. How would I do this?

EDIT - I realized I could use a droste code. I’ll look at those.

EDIT - Nah, I couldn’t do it. I do picture it in my head, just can’t convert into math, and then code it in.

EDIT - This is the closest I could find to the solution, it’s still not the best one though :confused: - Shaped gradient - my first plugin - Plugin Developer's Central - paint.net Forum

There’s also Light Rays, but I don’t know how to make it go backward after looking at the source, and use it to convert it into shaped gradient.

I want to do 3x3 but cannot. There must be a space before x, otherwise x disappears. E.g.

foo_by_:
  t=3 e[^-1] "Filter with a "$t"x "$t" filter" # Filter with a  3 filter

Does \ works? @afre

No, that would introduce a special character. This works though:

foo_by_:
  t=3 e[^-1] "Filter with a "$t{`"120"`}$t" filter" # Filter with a 3x3 filter

Thats because $t"x " is actually equivalent to $tx" " and variable $tx is not defined.
In that case, use ${t}"x"${t} instead.

@David_Tschumperle @Reptorian I started a conversation about MATLAB / Octave having array indexing in posts 474-479 (when I focused on conditionals). Here is another example where I find it expedient.

I have been making PDFs and CDFs, and wanted to check if I got it right by matching the output, which is a long column of values in Octave and a displayed image in G’MIC. Eyeballing the values is kind of annoying, esp. the super tall column of Octave. To simplify the task, I could do find(pdf>0) and pdf(pdf>0) to find the indexes and values, respectively, that are greater than 0; or whatever else I would like to query.

octave:8> find(pdf>0)
ans =

    85
    92
   104
   106
   108
   113
   114
   116
   117
   124
   125
   126
   128

octave:9> pdf(pdf>0)
ans =

   0.066667
   0.066667
   0.066667
   0.066667
   0.133333
   0.133333
   0.066667
   0.066667
   0.066667
   0.066667
   0.066667
   0.066667
   0.066667

I am unsure whether I could do something similar in G’MIC.

Also, I wonder if there is a way to view the data in console. The default behavior is to truncate it to data = (0,0,0,0,0,0,0,0,0,0,0,0,(...),0,0,0,0,0,0,0,0,0,0,0,0).. I feel the interpreters lack what the other has in this respect. They might have the feature but I am not aware of it or it isn’t simple to do.

Without knowing what that command does in depth, I can’t help you. Would dar_insert help?

It is more of a commentary on how we can query data and / or generate new arrays or vectors from it. The example in my last post is a 256,1,1,1 image where most values are 0, so to compare the two without saving it in one environment and inputting it in another is to find values that >0.

In Octave, I can do find(pdf>0) to find the indexes and pdf(pdf>0) to find the corresponding values. In gmic, I display the image and query by zooming to the various locations to find the values. It would be nice, if I could do something similar in gmic: being able to output values in the console or querying certain subsets of the data using conditionals. The latter is possible but not convenient to do; i.e. a short statement like find(pdf>0) already does so much or my previous example from many posts ago

octave:1> N=[0,1,2]
N = 0 1 2

octave:2> med=median(N(N!=0))
med = 1.5000

Of course, the array indexing of Octave / MATLAB stretched to its full potential is a world of confusion to read. I don’t like that one bit! But simple uses are very handy and powerful.

Something like this may help :

#@cli extract : "condition",_output_type={ 0=xyzc-coordinates | 1=xyz-coordinates | 2=scalar-values | 3=vector-values }
#@cli : Extract a list of coordinates or values from selected image, where
#@cli : specified mathematical condition holds.
#@cli : For N coordinates matching, result is a 1xNx1x4 image.
#@cli : Default values: 'output_type=2'.
#@cli : sp lena +extract_coords "norm(I)>128",3
extract : check "isin(${2=2},0,1,2,3)"
  v - s0,s1,s2,s3=xyzc-coordinates,xyz-coordinates,scalar-values,vector-values
  v + e[^-1] "Extract "$s$2" from image$? verifying condition '$1'." v -
  repeat $! l[$>]
    1,32,1,{arg(1+$2,4,3,1,s)}
    str=">"${-math_lib}"($1)?("
    if $2==0   str.="dar_insert(#-1,[x,y,z,c]));i"
    elif $2==1 str.="dar_insert(#-1,[x,y,z]));I"
    elif $2==2 str.="dar_insert(#-1,i));i"
    else       str.="dar_insert(#-1,I));I"
    fi
    eval.. $str";end(resize(#-1,1,dar_size(#-1),1,s,0))" k.
  endl done v +

It is a command that extract a list of coordinates or values from an image, where specified condition holds.
Then, for instance, you can use it like this :

$ gmic 100,100,1,3,'a=y/h;oma=1-a;a*[255,0,0]+oma*[0,255,0]' 100%,100% circle. 50%,50%,30%,1,1 mul +extract[0] "I!=[0\,0\,0]",1 +extract[0] "I!=[0\,0\,0]",3

Here, I first create an image of a circle with a color gradient in it (left image).
Then I use extract to extract the list of all coordinates where the color is different from black (middle image). And I re-use extract to get the corresponding colors for these coordinates.

Thanks! Saves me the trouble of figuring out the math interpreter and other syntax. Will see how it applies to the 2 cases later.

PS I don’t know what +extract[0] "I!=[0\,0\,0]",1 does. I only see a gradient only (rotated)

eg0

and +extract[0] "I!=[0\,0\,0]",3 is exactly the same as the input image. a y below (rotated).

eg

But what is your input image ?

Sorry, I was editing the post as your were reading and also multitasking. Refer to post 551 for the outcome I would like; maybe output one column with coordinates and the other corresponding values. The input is a histogram where all other positions are 0. The output should also be a truncated set of columns. I only want to select the pixels that are within the subset defined by the conditional statement.

In the case of post 551, I expect to get something like this

 85 0.066667
 92 0.066667
104 0.066667
106 0.066667
108 0.133333
113 0.133333
114 0.066667
116 0.066667
117 0.066667
124 0.066667
125 0.066667
126 0.066667
128 0.066667

The second thought of 551 is whether we could get a text-based output in-console. I know it can be clumsy but for querying it could be helpful and saves me the stress from having to manage too many floating windows.

myprint :
  e[] {b}" = \n"
  v - eval. ">echo('   ',i)" v +
  e[] ""

And if you want to customize your input, specifically for your task, there shouldn’t be a problem:

both :

  # Create random normalized signal.
  64,1,1,1,'u<0.1' normalize_sum. nm. pdf

  # Extract locations of non-zero values.
  +extract. "i!=0",1

  # Print values.
  e[] "\n"{-2,b}" = \n"
  v - eval. ">X = i; echo('   ',X,' ',i[#0,X])" v +
  e[] ""

and then :

$ gmic both
[gmic]-0./ Start G'MIC interpreter.
[gmic]-0./both/ Input image at position 0, with values 'u<0.1' (1 image 64x1x1x1).
[gmic]-1./both/ Normalize image [0] with a unitary sum.
[gmic]-1./both/ Set name of image [0] to 'pdf'.
[gmic]-1./both/ Extract xyz-coordinates from image [0] verifying condition 'i!=0'.

pdf = 

   13 0.25
   29 0.25
   35 0.25
   63 0.25

[gmic]-2./ Display images [0,1] = 'pdf, [unnamed]_c1'.
[0] = 'pdf':
  size = (64,1,1,1) [256 b of floats].
  data = (0,0,0,0,0,0,0,0,0,0,0,0,(...),0,0,0,0,0,0,0,0,0,0,0,0.25).
  min = 0, max = 0.25, mean = 0.015625, std = 0.0609938, coords_min = (0,0,0,0), coords_max = (13,0,0,0).
[1] = '[unnamed]_c1':
  size = (1,4,1,1) [16 b of floats].
  data = (13;29;35;63).
  min = 13, max = 63, mean = 35, std = 20.8487, coords_min = (0,0,0,0), coords_max = (0,3,0,0).
[gmic]-2./ End G'MIC interpreter.

Thanks. Now that you spell it out, it is very simple to do. My habit of writing one-liners certainly doesn’t help. As for the gradient confusion, I see that I was copy-pasting the condition from your example instead of using my own.

One question is if I get the user input and they use the dot shortcut how would I change it to [index] output. Or more generally, if the user input was [index pattern], how would I simplify it to a more general form like [0,1,…]?

This is related to the question that I posed in post 492 and continued in post 518. I want to simplify the index and name outputs. The user can refer to the same images in any number of ways available, and the name could be the original or a copy, but I would like to output a simplified index and retain the name (whether it be the original or a copy).

That’s actually planned in 2.8.0_pre : Command pass will return a status containing the list of all image indices, so something like this will be possible:

e[^-1] "Do something on image$?, with argument images "${"-pass$2"}"."

Also, I’m planning to change a little bit how the verbosity is managed, so that there won’t be much v + and v - necessary in a command.
Work in progress… :slight_smile:

Now, I have a problem of my own.

isophotes 15
if w>h
    dx_a={.2*w}
    dx_b={w-$dx_a}
    dp={1/max($dx_a,$dx_b)}
else
    dy_a={.7*w}
    dy_b={h-$dy_a}
    dp={1/max($dy_a,$dy_b)}
fi

iter=1

do
    rx={(1-($iter*$dp))*w#0}
    rx={$rx<1?1:$rx}
    ry={(1-($iter*$dp))*h#0}
    ry={$ry<1?1:$ry}
    +r. $rx,$ry,100%,100%,2
    iter+=1
while w!=1&&h!=1
cut 0,255
r[^0] {w#0},{h#0},100%,100%,0,0,.2,.7
rv blend alpha

The problem here is pretty clear. I don’t want the result to be black. What can I do to remedy this issue?

EDIT:

I have partly remedied the issue with adding

sh 0,{s-2}
sh.. {s}
{w},{h},1,1,i#-1?0:1
inpaint_pde[1] [-1]
k[0]

EDIT:
I figured it out by using +r[0] $rx,$ry,100%,100%,5 instead.

EDIT:
One final issue - Getting it to look smooth.

#r 1280,780,100%,100%,0,0,.5,.5#
isophotes 15
sh 0,{s-2}
sh.. {s}
max_alpha={iM-1}
{w},{h},1,1,i#-1?0:1
inpaint_pde[1] [-1]
k[0]
if w>h
    dx_a={.125*w}
    dx_b={w-$dx_a}
    dp={1/max($dx_a,$dx_b)}
else
    dy_a={.5*w}
    dy_b={h-$dy_a}
    dp={1/max($dy_a,$dy_b)}
fi

iter=1

do
    rx={round((1-($iter*$dp))*w#0)}
    rx={$rx<1?1:$rx}
    ry={round((1-($iter*$dp))*h#0)}
    ry={$ry<1?1:$ry}
    +r[0] $rx,$ry,100%,100%,5
    iter+=1
while w!=1&&h!=1
r[^0] {w#0},{h#0},100%,100%,0,0,.125,.5
rv blend alpha

image

I could do subsampling, but then it would take me a longer time to render.

Command pass has now a new ‘mode’ that just returns the list of indices of selected images from the parent context.
From now (after recompiling of course), it is possible to write something as:

foo : 
  e[^-1] "Do something with images ["${"pass$1 3"}"]." 

Thanks David. I have been busy lately but I will definitely battle test and provide feedback for any of your changes. Usually do. :slight_smile: