G'MIC exercises

@David_Tschumperle I just signed up at GitHub as afr-e . I waited too long; someone took afre. :blush:

Yes, looks like something people actually use. Looks simple but as usual the math and programming will take me a while to digest.

Are you saying that I could apply this principle to @garagecoder filter? If so, I will take a look when I have the time.

As mentioned, the current issue that I am having with Luijk’s curve is that I am getting a kink when a ≠ b. Also, the overall curve isn’t as smooth as I would like it. Maybe I am just stuck on appearances and it isn’t a big deal once I apply it to a real image.

I mis-spoke. I should have said:

The curves passses through (0.5,0.5), and that is where the inflection is. If you want a curve to pass through (a,b) instead, simply raise to the power [log(b)/log(a)].

Of course, raising it to a power will disturb the gradients at the ends, so they become non-zero.

I’ve implemented the family of smoothstep curves in IM. I will document that in my Clut Cookbook.

Personally, the curve I use most often combines IM’s “-sigmoidal-contrast” to adjust mid-tone contrast with a power curve to adjust the mean.

We can use whatever curve suits our purpose, which for me boils down to how I want to control it. I readily view an image in terms of lightness and contrast – mean and standard deviation – so I like those controls. I don’t think in terms of “I want this shade to become that shade, so the curve should pass through (a,b), so that is pow[log(b)/log(a)]”.

Yeah, I think I’m missing a few things here. I do need a little help here.

#@gui _
#@gui <i>Reptorian</i>
#@gui Modulo Operations : fx_modulo, fx_modulo_preview(0)
#@gui : note = note("Applies modulo operations based on arithmetric operations)
#@gui : Modulo Operations = choice ("Addition", Multiplication")
#@gui : Number = float(1,0,64)
#@gui : sep = separator(), note = note("<small>Author : <i>Reptorian</i>.      Latest update : <i>2018/08/18</i>.</small>")
fx_modulo:
if ($3==1} suf="_Add" elif{$3==0} suf"" else suf="_Mul" fi
if {$1==0} [0] + $2 * 256 mod 256
if {$1==1} [0] * $2 mod 256
done

I see one typo here:

({$3==1}

and here (added space)

elif {$3==0}

What is suf""?

I decided to remove the condition of it being addition or multiplication since it would be easier to code, plus it’s more flexible by mixing them.

Now, I’m having a problem on this line - Modulo Operations : fx_modulo, fx_modulo_preview(0)

Basically the second part of that is the culprit. Unknown filename or something.

There should still be an equal sign suf="", so that is a typo.

You don’t have a preview command ATM; you need to write it.

How do I write the preview command?

I keep a handy link to the main *.gmic file: https://raw.githubusercontent.com/dtschump/gmic/master/src/gmic_stdlib.gmic. Loads of examples. :wink:

EDIT: I gotten it to work, but it’s not how I wanted it. I would love for the code to ignore alpha.

@Reptorian Sorry I wasn’t clear before. It took me a long time to familiarize myself with G’MIC scripting. It wasn’t easy, given that I don’t have a math or coding background. Here is an example with remarks:

no_alpha:
  
  # Input tiger sample image and
  # gradient image with same dimensions
  sample tiger 100%,100%,1,1,x

  # Show these two layers and
  # then combine them into RGBA
  display append c
  
  # Separate into RGB [0] and A [1] layers
  split_opacity
  
  # Act on layer [0] only
  local[0]
    mirror x
  endlocal
  
  # Show the changes and
  # then restore them back to RGBA
  display append c

It’s ok, I have solved it and posted my new filter to David, so hopefully he can push it if he chooses to. Now, I know a way to replicate GIFKR Divide filter now and that will be my next filter.

  • 256-(i*((255/0.08/0.08)/(256)))

Using that on user-defined filter gives me similar result to GIFKR Divide.

Source code confuses me though

  • return (int) ((255d*divisor)/(1+channel));

What is d is?

I believe the filter basically it’s something on the line of:

  1. (((255 * i * 50)/(256)))
  2. Apply mod 256 after
  3. Invert Result

You got your GIFKR filter converted to G’MIC fashion

I am guessing it refers to the data type of the number. See: https://en.wikipedia.org/wiki/C_data_types#Basic_types

Time to figure out how to deal with this very noticeable artefact in the angular blur filter:

I can sort of fix it by rotating the unblurred image by 180 degrees, running the filter on that, rotating it by 180 degrees again and then stitching the two together:

I think it’s something to do with the way G’MIC makes ‘angular’ images like this and it’s possibly connected with the Symmetric Kaleidoscope filter (note the asymmetry of the image and the blurring - both of which cannot be fixed simply by rotating the image once and stitching it together):

I don’t know how one would fix it at all or how this was implemented in GIMP through GEGL without any of these issues…

I guess that’s because the various blur commands don’t support periodic boundary. But you can always do something like:

gmic sp rooster euclidean2polar , f. "avg(crop(x,y-10,z,c,1,21,1,1,2))" polar2euclidean ,
rooster
and could be weighted with gaussian.

note: the periodic boundary is the last parameter of the crop, 2.

Edit: I thought of another way; make the polar image periodic by extending it with a crop:

gmic sp rooster euclidean2polar , z 0,-100,100%,{h+99},2 deriche 20,0,y z 0,100,100%,{h-99} polar2euclidean ,
rooster2
this might be faster with larger amounts of blur.

Ok, I think I need to learn how to affect channels individually. Every time I look, it doesn’t look very easy to do nor understand. It’s actually a bit more understandable to do C++ and do individual channels from there.

Thanks for that, which parameter is the amplitude? I’m assuming that the weighting can be done through using the y coordinate after the euclidean2polar operation but I’m not sure how to take just the y and use it.

Edit:

I still saw the artefact in a large image (albeit very reduced) and I rewrote the filter:

#@gui Better Blur [angular] : fx_blur_angular_2, fx_blur_angular_2_preview(1)
#@gui : Amplitude = float(2,0,40)
fx_blur_angular_2 :
height={h}
euclidean2polar , z 0,{-$height},100%,{h+$height-1},2 deriche $1,0,y z 0,{$height},100%,{h-$height+1} polar2euclidean ,
fx_blur_angular_2_preview :
fx_blur_angular_2 $*

However it keeps increasing the image width by two pixels. I’m not sure why that’s happening or if it requires a simple resize.

The blur_angular command needs indeed some attention to better manage periodic borders.
I’ll probably take a look at it today, using the FFT to perform the blur (which naturally manages this kind of boundary conditions).

@Joan_Rake1
Amount is controlled by the length of the 1D “kernel”, so basically just the size of the crop you specify. One way to use a gaussian is with inner product (because each crop() produces a vector):

test_angular_blur : skip ${1=10}
  repeat $! l[$>]
    euclidean2polar ,
    {$1*2+1},1,1,1 gaussian. 15% normalize_sum.
    f.. "
    init(G=crop(#1,0,0,0,0,w#1,1,1,1));
    dot(G,crop(x,y-$1,z,c,1,size(G),1,1,2))"
    rm. polar2euclidean ,
  endl done

@Reptorian there are lots of ways to reference channels, it’s not harder than c++ just different from what most people will be used to. The first thing to know is how they are stored in memory; for an RGB image it’s simply all the red pixels, then all the green, then finally the blue.

You can simply split them to separate images, do some stuff, put them back again:
gmic sp rooster s c f[1] 0 a c # fill blue channel with 0
Or keep one channel of an image:
gmic sp rooster channels 0 # keep the red channel
Reference the current channel number during fill with “c”:
gmic 400,400,1,3,c*64
Use a “shared” image buffer to access one or more channels:
gmic sp rooster sh 1,2 f. 0 rm. # fill blue, green channels with 0

My intuition tells me that GIMP does it this way. Compare my rewrite of GC’s G’MIC filter:

…with the GIMP one:

Longitudinal banding is seen with the GIMP one, particularly in the corners.

@garagecoder Interesting result, though it’s being cropped a little too much somewhere along the line because the colours only just fall short of wrapping around completely; the artefact has returned:

With that last image, is that from the “crop the polar” version? If so, it needs work to always extend by the correct amount so I’m not surprised. It could end up quite memory hungry so I’m not sure it’s a great plan :slight_smile:

With the last thing I posted (test_angular_blur) I’m not seeing artifacts, if you are I’d like to know the settings and image size! Probably irrelevant if David is about to recode it anyway…