The Big Bad G'MIC Thread of Silly Questions

Well, i knew it wasn’t going to be that easy :slight_smile:
I don’t know the fill math syntax at all, so i guess i’ll save that for later when i’ve (re?)read the tutorials.

All i can do for now is this :
gmic sp polygon 3,0,0,50%,100%,100%,0,1,255 +f "i==255?lerp([ 32,128,99 ],[ 0,0,16 ],y/(h-1))"
Which renders the triangle with a gradient (yay! :slight_smile: ) but also fills the rest of the image with black (meh! :frowning: ). This is the expression from the bouncing ball tutorial.

  1. Use polygon() in fill mode to fill a white (value 1) polygonal shape on an otherwise black (value 0) image. Call this image “Mask”.
  2. In a fill iterator, use “Mask” to select between one or another of two source images, perhaps “Solid Dark Color Background” and “Festive Bright Pattern.”

I think you can work out the details; perhaps later I can EDIT in one of any number of possible implementations.

Have fun!

EDIT:

Here’s the example of what I had in mind. Does it bear any relation to what you want?

polkadotstar

polyfunfill.gmic:

polyfunfill :
   # Data points for vertices of some star-like
   # polygon.
   star=442.52139,415.31727,\
	295.70526,374.95231,\
	179.22126,473.01240,\
	172.24195,320.90850,\
	42.985724,240.42786,\
	185.4884,186.787460,\
	222.08766,38.987605,\
	317.13847,157.93990,\
	469.01428,147.07520,\
	385.25623,274.23217,\
	442.52139,415.31727

   # Fancy polka dot to fill
   # the interior of the polygon
   -input 512,512,1,3,lerp([32,74,135],[0,180,130],y/(h-1))
   -polka_dots. 3,4,0,0,37,10,1,1,255,230,80
   -name. fancy

   # Background gradient image
   {w},{h},{d},{s},lerp([0,95,25],[75,140,0],y/(h-1))
   -name background

   # Mask
   {w},{h},{d},1
   -name mask
   -eval begin(S=[$star]);polygon(#$mask,size(S)/2,S,1,1)

   # Polka dot star on a greenish background
   -fill[background] i(#$mask,x,y)?I(#$fancy,x,y):I
   -keep[background]

Use:

 gmic -m polyfunfill.gmic  polyfunfill o. polkadotstar.png
1 Like

Hi, yes thank you! Something like this anyway. I’m trying to learn how to do this, and how to use masks. But i really thought i could just fill the polygon with maths (like input with lerp, etc). It didn’t like it that much though.

I still have a few questions :

You are using {w},{h},{d},1 where i would use .,.,.,1. Is there any difference between the two?
lerp does the gradient transition between two colors, and that’s ok.

eval begin(S=[$star]);polygon(#$mask,size(S)/2,S,1,1) I’m not really familiar with this syntax yet, it looks so mysterious, so i’m trying to guess :

  • begin just tells gmic to “evaluate something first”
  • …which is setting S, a variable containing the Star shape coords (why the […] though? vector?)
  • then comes polygon in a different syntax…
    #$mask: does it tell polygon to “modify” the image selection named mask as target (like polygon[mask])?
    size(S)/2,S,1,1 Are these the rest of the polygon params, as NB points, coords,opacity,and color?
    size(X) (vector dimension) Why do we need a vector here (and divided by 2 nonetheless xD)?
    Opacity is at 1, so fully opaque, but then what about color (1?)?

*-fill[background] i(#$mask,x,y)?I(#$fancy,x,y):I I don’t have time to try to understand this right now, I just know it fills background with the mask shape and the polka dots motif, but the syntax escapes me :stuck_out_tongue:
ì means current pixel, I means current vector, but why do we need one or the other?
Does it mean : if (i(#$mask,x,y)==1,I,I(#$fancy,x,y)) ? :sweat_smile:
If a $mask pixel is white, fill it with $fancy , else just leave it black/transparent or… what the duh is I ?

Haven’t tested your code yet so I tried guessing by myself while looking at the doc…

One is more understandable. But, in practice there is no difference. There’s things like {w#-5} and so.

Yes, that essentially what it does. It is also used to set in const (not needed in begin, but I use it for synthetic sugar reason), set in modifiable variable that does not depend on the current index of loop.

…which is setting S, a variable containing the Star shape coords (why the […] though? vector?)

The […] is used to declare a vector or an array of numbers. N=[5,2,3];N[1]; would return 2 because the index 1 refers to the second index of N.

#$mask: does it tell polygon to “modify” the image selection named mask as target (like polygon[mask])?

Yep, that is what it does.

size(S)/2,S,1,1 Are these the rest of the polygon params, as NB points, coords,opacity,and color?

Yes.

`size(X) (vector dimension)` Why do we need a vector here (and divided by 2 nonetheless xD)?

There are N set of coordinates (x,y). So, it makes sense to divide by two. Polygon, eclipse, and so on can only work on 2D plane and just the first z level.

i(#$mask,x,y)?I(#$fancy,x,y)

This means if x,y point at image index $mask is a non-zero value, then return the vector at image index $fancy.

if (i(#$mask,x,y)==1,I,I(#$fancy,x,y)) ? 

This is a incomplete syntax. What goes after ?, where is the closing braces?

I think you are starting to understand.

Or (a bit shorter):

   # Mask
   {w},{h},{d},1 polygon. {narg($star)/2},$star,1,1 => mask

   # Polka dot star on a greenish background
   j[background] [fancy],0,0,0,0,1,[mask]

It’s quite easy to find a math expression that would work for triangles, but definitely not for N-sided polygons.

The begin() statement here does actually nothing, as the eval here does not loop over image pixels, so the expression is always evaluated once. Also the polygon() function can be called outside the math evaluator, with the regular command polygon:

 {w},{h},{d},1 polygon. {narg($star)/2},$star,1,1 => mask

Here again, you can avoid using the math evaluator for that task, just use command image (a.k.a. j) with the following arguments:

   j[background] [fancy],0,0,0,0,1,[mask]
2 Likes

Thank you teachers :bowing_man:
I’m now playing with this to find how to get different kind of gradients. Haven’t found yet how to get a repeating gradient though.

you can avoid using the math evaluator

Still, i don’t know how long I’ll still be able to escape the math evaluator :stuck_out_tongue:

For now i’ve been playing with your examples. Funny how i choose a random image (Egypt from login window), started to enter random polygon coords and randomly chosen colors, and ended up with a pyramid… how random ! The var is called arc for a reason (boomerang was too long :stuck_out_tongue: ).

foreach {
=> background
arc={u(45,50)}%,{u(10)}%,{u(50,100)}%,{u(50,100)}%,{u(50)}%,{u(65,75)}%,{u(10)}%,{u(50,100)}%
.,.,.,4,lerp([32,74,135],[255,255,0],y/(h*0.8)) => fancy 

.,.,.,1
polygon. {narg($arc)/2},$arc,1,1 => mask 
j[background] [fancy],0,0,0,0,1,[mask]
autoindex 64
}

At some point I added alpha to the colors to get a gradient going from Opaque to transparent but it doesn’t work with j. So i tried ja but it doesn’t allow using masks and fills the whole image with the gradient.
Should i use shared 3 or split c instead to add a B&W (gradient) polygon to an alpha channel (filled with white, so only the polygon’s gradient turns transparent) or is there another way with j or ja ?

Mod a ramp?

multiramp

$ gmic 300,300,1,1,(y/(h-1))%0.1 normalize. 0,255 o. multiramp.png
2 Likes

Thanks!

Got a weird but cool one here :

gmic run '300,300,1,1,(y/(h-1))^(x/(w-1))%0.1 normalize. 0,255 '

3 Likes

Hear that sucking sound? It’s @prawnsushi being drawn into the math evaluator.

I thought that only happened with vim!

  30,1,1,3 rand 0,512 rbf. 512,512 %. 50 n. 0,255 map. 3 smooth. 200,0.1,1

1 Like

I haven’t tormented the cat in ages.

cutcat

catcutter.gmic

catcutter : -skip ${1=10.0}
   freq=$1
   a,b={[0.5+u(0.5),0.3+u(0.7)]}
   -name. target
   {w},{h},1,1,($a*y/(h-1))^($b*x/(w-1))%(1/$freq)
   -normalize. 0,255
   -name. warper
   -blur[warper] 1
   (255,0^0,255)
   -resize. 256,{h},{d},{s},3
   -name palette
   -map[warper] [palette],3
   -normalize[warper] -10,10
   -warp[target] [warper],1,2,3
   -keep[target]

Usage:

$ gmic -m catcutter.gmic -sample cat,512 catcutter. 13 n. 0,255 o. cutcat.png
1 Like

@David_Tschumperle Nice but this one looks a bit random though.

Now i’m wondering how to do a mirroring gradient. Like this for example, without calling mirror etc.
Or a circular one (but i guess it’s what gaussian does, in a way).
So i’m typing random pseudo-maths. And getting some pseudo-fractals :open_mouth:




@grosgood Poor cat. I thought that one day i would adapt “Slice stretch squeeze (in gmic-qt)” with warp, so it’s a bit cleaner, hopefully less blurry.

1 Like

Ah, @David_Tschumperle: you know I have a weak spot for Radial Basis Functions. Still one of my favorite tutorials, though it could use a clean-up. It deserves a life beyond CLUT (de)compression.

1 Like
foo:  200,100,1,1,"begin(
  const cx=(w-1)/2;
  const sd=1/cx;
 );
abs((x-cx)*sd);"
foo:
200,100,1,1,"begin(
  const cx=(w-1)/2;
  const cy=(h-1)/2;
  const sd=w>h?1/cy:1/cx;
 );
nx=(x-cx)*sd;
ny=(y-cy)*sd;
norm(nx,ny);"

You can replace 1/c(x|y) with c(x|y) and the multiplier with division and get the same result.

Norm in this case is pretty much hypotenuse formula.

3 Likes

Nice, @Reptorian!

Here’s another.

$ gmic 300,300,1,1,'x/(w-1)' split x,2 normalize 0,1 oneminus. append x

Circular is an easy extension:

$ gmic 300,300,1,1,'x/(w-1)' split x,2 normalize 0,1 oneminus. append x polar2euclidean ,

foo

2 Likes

Nah, it’s me sucking your ideas with a straw :man_vampire:

1 Like

It was my intention, early on, to post a riff on the image command, but @prawnsushi keeps on coming up with entertaining distractions.

Goal: Modify color images such that a specific target color remains unchanged, but other colors “less like the target” become progressively desaturated. If red is the target, colors that are more-or-less cyan-like are desaturated. Intermediary colors like green are semi-desaturated. It is an interesting way to place a particular emphasis on objects in photographs that have particular colors, with the image as a whole looking more-or-less like a black-and-white photograph.

colorpick

$ gmic -m pickcolor.gmic sp colorful,512 +pickcolor[0] 1,0,1 +pickcolor[0] 1,1,0 +pickcolor[0] 0.2,0,1
pickcolor.gmic
pickcolor :
  foreach {
  
     # Mask: colinear to provided RGB
     # color vector tends to 0, else 1
     [0]
     +fill_color. ${1--1}

     # Take cross products of unit color
     # vectors against reference color.
     -orientation[^0]
     -fill. cross(I#-2,I)
     -remove..

     # Length of cross product vectors:
     # zero length maps to provided color. 
     -norm2.
     -name. mask

     # Desaturated version of given image.
     +luminance..
     -to_rgb.
     -name.  grayscale
     -name... colorful
     
     # Colors tending to complementary also
     # tend to desaturation.
     -image[colorful] [grayscale],0,0,0,0,1,[mask]
     -keep...
   }

“Less like the target” translates to cross products, regarding colors as three dimensional vectors in the RGB color space. The cross product of parallel vectors (née colors) is zero. The cross product of transverse colors is positive, where colors’ transverses are complements, (as red is complementary to cyan). This provides a means to make a selection mask that can be harnessed by image to turn the trick. Depending on the mask image blends from the original color image or a desaturated copy, in accordance to the cross-product generated mask.

Works best with saturated target colors and saturated images: foggy mornings on the Highland moors — not so much. You don’t have to specify colors in the range [0\dots 1]; [0\dots 255] works fine, as any range (so long as you are consistent. Have fun.

1 Like

:clown_face: :person_juggling: :clown_face:
And you have enough answers to keep me busy for thousands of lifetimes.

What happens if you give a saturation boost to the Highland moors before running your command?
Anyway i like this idea, hope it’ll be integrated to g’mic officially.

Think it could make a decent gmic-qt filter. Pick the color from the preview. Run a trial solution whenever a color picker dot is dragged over a pixel. There is a use-case for a “sensitivity” slider to more-or-less control the drop-off rate from the selected color. Don’t see a reason for any more controls, so it could be simple to use.

But I won’t be doing it anytime soon — lot of tutorial work on the stocks, plus the day job. If you’re game for porting this to gmic-qt have at it.