G'MIC exercises

Never mind, I finally solved how eval works and how I can use vectors!


It turns out I have one more question about vectors after getting my rep_regm (eq. to rep_reverse_engineer_gradient_map) script to work.

eval ${-math_lib}"
for(q=0,q<wh#0,q++,
I(#1,q%w#0,floor(q/w#0),z,1)=5;
);
"
s c

This doesn’t affect the second channel? How would I do it in the content of eval ${-math_lib}. This would be the solution to fixing rep_sptgwp script as it’s not compatible with rep_ced8.

I can get it to work with shared channel though. Is that really necessary for me to do?

**EDIT once again , le sigh, it takes a while to learn about eval thing: **

It turns out that changing I into i works.

But, this raises a issue. What if I wanted to modify the z section without using a for loop or while loop by using capital I?

I is a vector of values representing the pixel being processed. If you are dealing with RGB, then it would be [ R,G,B ]. Useful when the channels need to be processed together. E.g., when I create a mask, I often take all 3 channels into consideration.

Say I want to mask pixels with negative values so that I may fill them in with inpainting or another type of filtering. (I have a custom command for that, though it isn’t robust enough to share.) I would do min(I)<0. I.e., if any channel dips below 0, the whole pixel needs to be corrected, not only the offending channel at the pixel location.

If I wanted to remove negative channels, I’d use this -

repeat s#-1
    sh. $>
    if im#-1<0 +. {abs(im#-1)} fi
    rm.
done

But, I assume that you want to calculate within math-lib. In that case, I would probably use store and restore to recorrect within a while loop.

You are missing my point on two fronts.

1 Was giving an example of I usage.

2 If you merely shift the negative values into range, non-data pixels won’t magically become data. The only way is to interpolate or otherwise replace them.

As for looping, David or Andy (I don’t want to ping them) reminded me that fill and eval already loop through the pixels. So if you do another loop inside, you would be looping twice. In the case of doing a conditional threshold, we don’t want an additional loop.

In fact, the same thing might be true for your question above and might be the answer you were looking for…

Well, for me, the answer to my issue is to use a for loop to do the calculation alongside different z level. I’m not going to be much help, but a combination of for loop and if should work within eval. I’m guessing that would be your answer.

Been readying my guided filter and have come to an annoyance in terms of echoing.

gmic sp tiger guided .,1,1

Apply guided filter on image [0], with guide image [0],...

Notice guide image [0] but I can’t reproduce it with a command that uses pass.

foo_pass_:
  v - pass$1 0 v + e[] "Name : '"{b}"'\nIndex: "$1

gmic sp tiger foo_pass_ .

Name : 'tiger_c1'
Index: .

The best I can do is

1 {b}, which yields tiger_c1. I want tiger; or

2 $1, which yields . or whatever the user inputs. I want the interpreted index, which in this case is [0].

Suggestions?

A bit convoluted, but it seems to work anyway:

foo :
  v -
  N=$!
  pass[^] 1 # <- pass as shared, so almost cost anything
  l[$N--1]
    s_ind=${"if '$1'=='...' u ["{$!-3}"] elif '$1'=='..' u ["{$!-2}"] elif '$1'=='.' u ["{$!-1}"] else u $1 fi"} # <- retrieve absolute index number
  rm endl
  pass$1 s_name={`"s = ['"{b}"']; s[find(s,'_c1')] = 0; s"`} # <- retrieve image name

  v + e[^-1] "Process image$? with image "$s_ind" (name = '"$s_name"')."

The fact is that when you are in a function, it’s quite hard to get access to the information of the calling environment (which is what you need here).
So, what I do here is to use pass to get the full parent environment (in a shared way), then deduce the absolute index of the argument.

I’m giving up on the fragment blur improvement as there’s still problems that I just can’t solve. So, I went back to math-lib solution. The main issue for me right now is to be able to add all the values within z axis located at x,y,c location. In other word, I want is#i(number_input,number_input,z,{s-1}). Think of a line cutting straight through a cube from top to bottom within the 4th channel. That’s what I want to get the sum of per axis. That way, I can reduce the need to use for loop on z axis twice.

Or maybe what I really need to do is to make rep_dupsdaxy within math_lib solution, and then work from there, but that’s a lot more work.


I kept trying and came up with this. If any one has time to check, let me know if there’s a issue here.

duplicate=3
impose=0
duplicates={($impose?1)+$duplicate}
maxa={iM#i{s-1}}
sh 0,{s-2}
sh.. {s}
/. $maxa
*.. .
rm[-2,-1]
rep_dupsdaxy $duplicate,20,0,$impose
add
sh 0,{s-2}
sh.. {s}
f.. i/(i0#-1<1?1:i0#-1)
*. {$maxa/$duplicates}
rm[-2,-1]

So far, it works better than every other solution so far. Been at days to solve this. Hopefully, this is the last time I find a solution.

Again, I don’t have the slightest idea what you are trying to achieve. To my understanding, A#B means do substitution A using the image at location B.

If that is true, what does the following mean? is#i(number_input,number_input,z,{s-1}) Return (last) value from image and use image at this index value to obtain the sum? Sounds nuts, unless I am mistaken. iM#i{s-1} doesn’t make sense either. In fact, G’MIC seems to ignore the i altogether and takes the value from {s-1}.

After a long while, I solved the problem by adding another image to indicate the amount of layer in that area. See +channels {s-1} section. That fixed every bit of issue I was having. Why didn’t I thought of it at first is beyond me.

rep_frblur_1:
skip ${2={sqrt(w^2+h^2)*.05}},${3=0},${4=0},${5=1},${6=1}
duplicate=$1
impose=$4
duplicates={($impose?1)+$duplicate}
sh {s-1}
mina={im#-1}
vr={iv#-1}
maxa={iM#-1}
rm.
if $mina<=0 
    if ($vr==0)&&($mina==0)
        v + error "Cannot be used on empty alpha!" v -
    elif $mina<0
        v + error "Last channel is cannot contain values less than zero!" v - 
    fi
fi
f i{s-1}?i:0
+channels {s-1}
f. i?1
a c
rep_dupsdaxy $duplicate,$2,$3,$impose,$5,$6
add
s c,-{s-1}
f. i?i:1
sh[0] 0,{s#0-2}
sh[0] {s}
f.. i/i0#1
f. i/iM*$maxa
rm[1-3]

Also, what do you think of this formatting?

#@cli rep_frblur: (eq. to rep_fragment_blur)
rep_frblur: rep_fragment_blur $*
#@cli rep_fragment_blur: _duplicates_count>=2,_radius_offset>0,_offset_angle,_keep_original = { 0=remove_original || 1=keep_original },0<=boundary_condition,_interpolation={ 0=nearest_neighbor || 1=linear },0<=_color_space<=9
#@cli : Fragment Blur is a effect that originated from the Windows software named Paint.NET. _radius_offset can be in percentage, or pixel form. When it is percentage format, the radius of the shift is equal to percentage of hypotenuse.
#@cli : \n     _color_space = { 0=RGB | 1=SRGB | 2=RYB | 3=CMYK | 4=HCY | 5=HSI | 6=HSL | 7=HSV | 8=LAB | 9=LCH }
#@cli : \n     _boundary_condition = { 0=None | 1=Neumann | 2=Periodic | 3=Mirror }
#@cli : \n     Default values: '_radius_offset=5%','_offset_angle=0','_keep_original=0','_boundary_condition=1','_interpolation=1','_color_space=0'

This is how it looks when I do gmic h rep_fragment_blur. Looks like you haven’t double checked it yet. I will help you proofread.

rep_fragment_blur:
    _duplicates_count>=2,_radius_offset>0,_offset_angle,_keep_original = { \
     0=remove_original || 1=keep_original },0<=boundary_condition,_interpolation={ \
     0=nearest_neighbor || 1=linear },0<=_color_space<=9

  Fragment Blur is a effect that originated from the Windows software named Paint.NET.
    _radius_offset can be in percentage, or pixel form. When it is percentage format, the radius of
    the shift is equal to percentage of hypotenuse.

 _color_space = { 0=RGB | 1=SRGB | 2=RYB | 3=CMYK | 4=HCY | 5=HSI | 6=HSL | 7=HSV | 8=LAB | 9=LCH }

 _boundary_condition = { 0=None | 1=Neumann | 2=Periodic | 3=Mirror }

 Default values: '_radius_offset=5%','_offset_angle=0','_keep_original=0',
    '_boundary_condition=1','_interpolation=1','_color_space=0'

1 use | instead of ||.

2 Fold _color_space and _boundary_condition selections into the condition line. Line will wrap itself; no need to separate the expressions.

3 I am uncertain about radius_offset and _offset_angle values. May need examples and range suggestions (and / or better conditions).

4 What is the default value of _duplicates_count?

5 First parameter should not start with _ unless you have a noarg option.

I thought that was a ok output (I’m using cli only to test things as I plan to improve cli of my commands). I like it better when the lines are right about aligned though ideally aligned. There is no default value for duplicates_count, you have to set values yourself. I could set it to 2 like in the picture below.

Here’s the default radius_offset and offset_angle.

The base sample of tiger is right in the middle of the two copies. Offset angle just moves copies clockwise.

I’ll be editing my clis in a few. But what do you mean about 2? I should do \ and then insert # ?

Here’s the pull request to update - Major upgrade to Fragment Blur by Reptorian1125 · Pull Request #207 · dtschump/gmic-community · GitHub

The output I copy-pasted is the interpreter’s output. Your text alignment attempt wasn’t successful.

It is better to set a default value. Helps show the user an ideal example and good if you ever generate doc pages.

Maybe the two parameters make sense to you, but it might be a good idea to explain them further for the rest of us. Please and thank you.

By #2 I mean there is no reason to separate color_space and boundary_condition into two separate descriptions. It is redundant and can be confusing. Place them in the one-liner list and G’MIC will automagically add \ and hard wrap the long line for you.

Ok, here is the change.

#@cli rep_fragment_blur: duplicates_count>=2,_radius_offset>0,_offset_angle,_keep_original = { 0=remove_original | 1=keep_original },0<=boundary_condition,_interpolation={ 0=nearest_neighbor | 1=linear },0<=_color_space<=9 _color_space = { 0=RGB | 1=SRGB | 2=RYB | 3=CMYK | 4=HCY | 5=HSI | 6=HSL | 7=HSV | 8=LAB | 9=LCH } _boundary_condition = { 0=None | 1=Neumann | 2=Periodic | 3=Mirror }
#@cli : Fragment Blur is a effect that originated from the Windows software named Paint.NET.\n
#@cli : _radius_offset refers to the distance the duplicates are from the original image. Each circular duplicates are of the same distance. radius_offset can be in percentage form, or in integer form. When it is in percentage form, the length of each duplicates offset is equal to the percentage of hypotenuse of image.
#@cli : _offset_angle refers to the starting angle the original duplicate is at. The primary duplicate starts from the right.
#@cli : _keep_original options is to keep the original image as a duplicate without offsetting it.\n
#@cli : Default values: '_radius_offset=5%','_offset_angle=0','_keep_original=0','_boundary_condition=1','_interpolation=1','_color_space=0'

Much better?

Replace the first two color_space and boundary_condition. Help shouldn’t have two of each.

Otherwise, much better. I still think your description isn’t as straightforward as it can be. I.e.,

– Radius offset looks like it shifts the copies horizontally.
– Offset angle looks like where the first copy is shifted from the original.
– Keep original is as it sounds: the original is blended in with the copies.

If you reword the parameter names and / or make the descriptions more concise, it will begin to make much more sense.

Well, I tried to make the description descriptive. In any case, I referred to you in this pull request - Major upgrade to Fragment Blur by Reptorian1125 · Pull Request #207 · dtschump/gmic-community · GitHub . If you have any objection to the cli, let me know.

Is it possible to code a filter that makes a filter that automatically place into another image via rescaling by best fit to that image? I’m a bit tired of manually doing this to finish up one of my gaming modding history project.

Like one of these? https://www.imagemagick.org/Usage/resize/#resize

More like something like this.

Image #0 = Big Image
Image #1 = Target Small Image

You set points from the big image and then go into the small image to set point again. Then, it’ll automatically rescale and fit based on the info found on those point. Kind of an automated way to rescale to fit features from one image to another image.

Did you say features as in objects and then overlay images? In any case, I would need an example instead of just text because right now I am just guessing…