The Big Bad G'MIC Thread of Silly Questions

Could you share your full code, and the relevant line? This is easy to do.

It’s not normalized. So, the image is 0,1 value only. I normalized my example image to demonstrate the output. White (255 in provided image) is 1 and Black is 0.

I’m sure of it. But i’ve re-read the tutorial and i still don’t know if i should use brackets or accolades or quotes or…

This is the closest to something that i want:

1,8,1,3,'$C1R,$C1G,$C1B,$C2R,$C2G,$C2B,$C3R,$C3G,$C3B,$C4R,$C4G,$C4B,$C5R,$C5G,$C5B,$C6R,$C6G,$C6B,$C7R,$C7G,$C7B,$C8R,$C8G,$C8B' d
map.. 3,0 d

But:

Here are the default values:

#@gui : Color 1 = color(255,0,0)
#@gui : Color 2 = color(255,113,57)
#@gui : Color 3 = color(255,255,0)
#@gui : Color 4 = color(85,0,255)
#@gui : Color 5 = color(0,0,255)
#@gui : Color 6 = color(0,113,165)
#@gui : Color 7 = color(85,170,0)
#@gui : Color 8 = color(255,255,255)

They are mixed up in the palette. 1st color became 255,0,113, etc.

Try this toy GUI filter:

#@gui 7 Color Palette Example:fx_7_color_example
#@gui:Color 0=color(44,73,88)
#@gui:Color 1=color(139,151,156)
#@gui:Color 2=color(196,196,196)
#@gui:Color 3=color(75,79,77)
#@gui:Color 4=color(34,39,37)
#@gui:Color 5=color(18,17,19)
#@gui:Color 6=color(42,19,30)
fx_7_color_example:
rm
(${1-3};${4-6};${7-9};${10-12};${13-15};${16-18};${19-21}) permute. cyzx
1 Like

Ok so i did write it with the parenthesis and “;” before, but i was missing the permute command…
Now the colors are right in my script, but the map command still outputs a 12 channel image, fully red. Note than the circles are rendered on their own with an alpha channel.

Doing an alpha blending with the background before mapping works but then i have a 9 channel image…

This also gives me a 12 channel image :
gmic run 'sp tiger s. c . a c map cool'
SHould i use compose_channels or something?

The reason map outputs a 12 channel image is that you’re mapping color array per individual channel. 4 channel image, and 3 channel palette is 12, and 1 channel gets mapped with all of the corresponding color. You should use a 1 channel image as a map target. You can have scenario where the map target consist of 2+ channels, but likely with a 1 channel palette (which is how it’s used in my Bit-Plane Shuffler filter).

'Godt brølt' og 17 andre ting vi skal holde op med at sige i 2018 : r ...

Ok, i think i’ll stick to black… good night!

2 Likes

I have not read the code, but by any chance, have you considered tiling the patterns? That may be more efficient and solve the last pixel row and column missing issue.

Ok, I’ll explain map again.

Try this code:

foo: 
 (5,4,1,7,8) 
 +resize. 100%,100%,100%,2,1 
 pal spec 
 +map[0,1] [2]

Ok, let’s break it down.

The first image is a single image of 5x1x1x1. It has only one channel.
The second image has 2 channels as it’s dimension is 5x1x1x2. But, every pixels has equal channel value. As the +resize denotes, this second image is a derivation of the first.
pal is a custom command for creating palette. In this case, we generated a palette of 12x1x1x3.
Let’s see what map does for the target images [0,1]

It appears that map assigns a color to each corresponding value. 5 will return the 6th color of pal image which is [168,45,45].

[5] => [168,45,45].
[5,5] => [168,45,45,168,45,45].

That’s why you see 12 channels.

Assuming the R value of your first color is $6 (so B value of your 8th color is $31).
Something like:

(${6-31}) r. 3,8,1,1,-1 permute. yzcx

should work.

Well my guess is that i got the radius wrong. And that maybe the outilne is drawn outside the circle, so the radius is 1px larger?

When i tiled the pattern at the beginning of this adventure, that’s how i found out it was missing a pixel, there was holes (2 whole crossing lines of them) in between the middle circles.
Also, i don’t want to use mirroring. But maybe it would work for that particular pattern.
Anyway the missing pixels are sort of fixed for now… color is another issue.

Actually i understand what’s happening with the channels, it’s just that’s it’s a bit annoying. I have a RGBA image, when i do split c i get 3 black images and the circles are all on the alpha channel…
That tells me that mapping will never work on this image. I tried mapping to a duplicated of the alpha channel: does nothing :open_mouth:

I also quickly tried match_rgb and it sort of work, it’s a bit too smooth though and only one color ( probably expected though).

(${14--1}) r. 3,8,1,1,-1 permute. yzcx
yes, this works just as good as @reptorian’s solution yesterday.
THe thing is i always end up with 12 channels. Looks like an impossible mission here. For some reason the circles are only drawn on the alpha channel, probably because I filled the image with black and 0 alpha.maybe i have to fix that first.

But i’d be perfectly fine with grayscale images, i never was good with color anyway.

You should use display, shortcut d, for debugging breakpoints (some, I understand, also use display to look at images. Interesting). See Post 7, Documentation and examples for writing scripts .

At the outset, interleave this command between those that make up your experimental pipeline. You will effectively single-step through your experimental pipeline. That way, when your pipeline diverges from how you think it should work to what it’s actually doing, then the next d , command stops the pipeline right at the genesis of that divergence, so that you can notice what is going awry, exactly at the point you are leaving the rails. Witnessing such departures is vitally important to furthering your understanding of G’MIC.

Strangely, the deepest insights to be garnered about G’MIC emerge not from my tutorials (splendid though they may be), but from seeing pipelines break. That is because bugs actually reside in our heads. Malformed code is but an outward manifestation of inward — and unsuspected — misunderstandings of G’MIC workings. When a pipeline breaks — and an aptly placed display command catches the calamity in the making — we feel a momentary frisson of bewilderment, as some hitherto cherished idea of how G’MIC works shatters. What we held to be so does not cover the facts in front of us. Fortunately, because of a breakpoint, we are still well-situated to work out the nature of the bugs in our heads, because the event in question has yet to be obscured by the running of subsequent commands. Absent such a breakpoint, and — if we are lucky — then some aspect of the calamity leads to G’MIC throwing an exception, a sort of automatic breakpoint, and we are not yet too far removed from the genesis of the mistake. However, it could be our lot that the defective pipeline runs to completion and we are confronted with a black image or a twelve channel image or an image with weird colors and have little idea of how we obtained the mess.

Now, instead of all of this seeming bother, it may be tempting to test little G’MIC snippet pipelines in the Custom Code filters of gmic-qt. Alas, that handy facility has its limits; it is not built for pipelines running more than a modest length, nor is it really possible to use display as a debugging breakpoint. Whatever is going awry, for example, may produce an image in excess of four channels, or pels with negative values. gmic, operating in a shell, easily takes in stride pels that are less than zero or deep channel images, but such sows no end of confusion within paint programs, where layers cannot exceed four channels and get hysterical with blacker-than-black pels. You need to debug in a shell, debug without the overhead and excess machinery of paint programs getting in the way and — possibly — sowing additional confusion.

So. Before becoming the lead actor in your own personal snuff film, you wrote this pipeline:

`gmic run 'sp tiger s. c . a c  map cool'`

It produced a 12 channel image. How did that happen?

Single stepping through the pipeline given as the run argument, then a debug exercise provides this narrative:

  1. sp tiger d , The image stack acquires from the sample command one w×h×d×s sample with dimensions 750x500x1x3. It appears to be a tiger image.
  2. s. c d , The single image on the stack, so selected with a pip (.) splits, channel-wise, into three scalar images. Put a pin through “scalar”. I’ll revisit the word in the sweet by-and-by. We might interpret this threesome of images, now splayed along the image stack, as the “red”, “green” and “blue” channels of the once-composited tiger, but that is just our suppositions at work. G’MIC’s split command couldn’t care less about our self-imposed interpretations.
  3. . d , The single pip is shorthand for input [-1]. This re-inputs what we interpret to be the blue channel of the tiger image and leaves an image stack with four scalar images, each dimensioned 750x500x1x1.
  4. a c d , An append command, unrestrained by any selection, consoldates the four scalar images into one 750x500x1x4 item. Because display commands have been interleaved, this gives us a readout of image geometry and a pause to consider: do we really want a four channel RGBB image (imposing, still, our color channel interpretations)? Possibly we stop to wonder if what is happening on the image stack has anything to do with our aims are. An RGBB image? we might ask ourselves. Of course, we may not pause to consider, because it is such a pain to interleave d , commands throughout our pipelines. So we let the pipeline flow on.
  5. map cool We’re off the rails now. A twelve channel image. Not our expectations. What happened?

First, a tip of the hat to @David_Tschumperle . His language is terse and efficient. When he wrote the #@cli header for map, the help text runs just so: “Map specified vector-valued palette to selected indexed scalar images” (emphasis mine). A scalar image in G’MIC-speak is a precise idea. It represents a single channel image — always. Should an image be made up of more than one channel, then it is a vector-valued image — always. That is because a pixel of a multi-channel image is multi-part, just like a vector. Though not written out anywhere in any appendix, @David_Tschumperle uses consistent expressions for each of the common image types in G’MIC. A scalar image is a one-channel image.

Second, The help text of map imposes one further quality on its selected images. Not only are selected images composed of single-channel scalars, those scalars are to be taken as indices. What do they index? The vector-valued palette given as map's first argument, either explicitly, as a selection of some palette image on the stack, or symbolically, one of the palettes known to the G’MIC palette command.

Now, I wrote earlier that, generally, G’MIC imposes no general interpretations on image channels. However, that does not preclude certain G’MIC commands from placing specific interpretations on the channels of “selected images.” In this case, map expects selected images to be composed of scalar look-up values that correspond to pixel positions of the given palette.

As I whimsically noted in its tutorial, map is G’MIC’s paint-by-numbers command. It’s modus operandi is to scan each selected image, left-to-right, top-to-bottom, and with each picture element, (pel), i(x,y) , (1) take it to be a scalar value, and (2) use it to retrieve a vector-value from the palette, found by counting from the beginning of the palette until it reaches the position equal to the given i(x,y) index value. map then replaces (‘maps’) the scalar with the retrieved vector value. Here’s a knock-on effect: the selected image goes from being a single channel image of scalars to a vector valued image, one with a channel count equal to that of the of the palette.

Finally, It should be clear, now, how the map cool portion of the pipeline left the rails. map, lacking a selection decorator, defaults to selecting all images on the stack. There is only one image on the stack, the 750x500x1x4 vector4-valued RGBB tiger image. That’s not built like an indexed, scalar image. map is not getting the kind of image that it expects. So it punts.

As with many G’MIC commands, map is designed to behave as reasonably as possible when handed unreasonable selections. When its selection is vector-valued instead of the expected indexed scalar value, map internally (1) performs split c; in the case of the tiger image, it now has four indexed scalar images, inputs more to its liking. (2) map then performs its left-to-right top-to-bottom scan on each of the four split-out channels. Recall the knock-on effect: tiger's channels go from being scalar images to vector-valued ones, composed of vectors retrieved from the palette. As you may surmise, the cool palette is a three-channel vector-valued image. That means each of the four channels of the tiger image become three-channel, vector-valued images in their own right. So, finally, (3) map appends these four, three channel, vector valued images together along the spectral axis, making one output image that has 4×3=12 channels.

The key take-away is not a blow-by-blow of how some particular experimental pipeline left the rails. The key take-away is the technique of single-stepping through pipelines, using interleaved display commands that furnish the raw information on how G’MIC behaves. You observe pipelines unfold one step at a time, and can study each step in a leisurely way, as long as you want.

And — when confronted with unexpected outcomes — you can trace the incorrect results to the bugs (G’MIC misunderstandings) that are residing in your head, where all the really vexatious bugs reside. I daresay that all regular contributors to this forum follow this or a similar debugging pattern when spelunking pipelines. I routinely extract custom commands that I wish to better understand from gmic_stdlib.gmic, put the extracted commands in small foobar.gmic files, and then interleave display commands through out portions of the command’s pipeline that I want to better understand. I sometimes even re-transcribe such commands in what I call the tutorial style, not because I think all custom commands should be written that way, but to force myself to closely read the code as I go about transcribing it.

When you master this technique, there is no real reason to stick with hazy guesses about how G’MIC behaves. You can observe its behavior in a concrete fashion and develop practical understandings on how G’MIC commands work. Soon, you will be proceeding less by guess-work, and more by preconceived, deliberate, engineered plans.

That’s when the fun really begins.

1 Like
1 Like

Ha! Changed the documentation on me! :grinning:

Oh d, oh d, I know thee!
Oh Oh w! I know thou!

William Fakepears

Seriously, d is the comand i use the most, even more than " " (read: input), to the point it bceomes painful to remove them from the script afterwards. So many of them. I also use repeat N { [stuff happening] w } to "done" to check if a repeat goes on for too long (useful for these damned circles).

Lol really?

Yes. I wanted a 4 channel image here because it is what i have in my script. RGBB worked as RGBA here. It wasn’t important what the alpha what. Could have used to_a instead but nvm.
I followed your recommendations btw, drawing circles with color 0,0,0,255 over an image filled with 0,0,0,0. Except i forgot i was drawing black on black so in the end i have 3 black channels and an alpha filled with circles, which is to be expected. Went too fast there. So using map even on only one channel of this image doesn’t do much. My bad, fell into a pit trap there.

Thanks, this is the info i needed.

Reptorian summed it up here, so yes i understood then what map does. 3 x 4 = 12… 3 x 1 = RGB. It was pretty clear then. Except i need the alpha… since i think i’m going this way (Gimp simulation), or at least something like that :

@David_Tschumperle thanks, the map definition is more clear now.

Ok thanks guys. But in the end the thing that annoys me the most is my inability to fill an image evenly with these circles. It only works for square images. No portrait, no landscape. Sad. Gotta figure it out, but i keep failing. @Reptorian got it, but i can’t read his code lol. But don’t bother explaining it to me, you’ve wasted enough time already. I have to come up with my own.

1 Like

mmmm, my first shot at this :


Not there yet i guess. :man_shrugging:

Biggest uestion will be : OMG how am i gonna fill this!? (>_<)

1 Like

label_fg is your friend. It identifies what can serve as a background region. From there a mask, a color background image fashioned from such a mask, and a composite. Serve cold.

1 Like

Thanks. I somehow managed to do it with flood, by blending the leaf with a white background (leaf is just black lines on alpha). This will probably work (although not perfect) as long as the background is a plain color.

The leaf itself is not always generated properly anyway lol.

I’ll try label_fg to see if i can manage…
EDIT: got this far. There are still a feww holes and a bit of alpha but that’s a start…

You can always remove the gray area as a copy before label_fg. Still a great start.

EDIT: +neq 0 would do. neq is short for not equal. That will remove the greys.

1 Like

Ha! I was looking for a fill expression to do that.

The fill expression equivalent would be just +f bool(i).

Even more confusing. +f !!i