Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
How can I get a layer ID by its position ? [Script-Fu]
#1
Hi everyone !

It seems to be the most stupid question in the world but I can't find the answer and begin to lose my hair ... 

I just want to get a layer ID by its POSITION ... (its relative position to be exact, but it doesn't matter)

In practice : I want to write a script which use the active layer (ok, so easy --> gimp-image-get-active-layer) AND the layer below ... then ... for it ... what can I do ?
Of course I know the position of my active layer in the tree (gimp-image-get-item-position) .... but I can't find the procedure to get the ID of a layer below (or above, or anything else) ...

((I could use gimp-image-get-layers to obtain the entire list, then write a loop to check each layer, one by one, until matching my active layer, then get the next ...... but ... that is a so heavy and  absurd and annoying solution ... (EDIT : Ok I can also use the position of my active layer to a bit more directly find the layer below in the list ... but I understood that I can't directly get an item in a list, so it would be more or less the same : write a loop which will review one by one each layer until reaching the position "+1"....) ))


There must be a simple and obvious way to do it... but I can't find it...


Thanks in advance to anyone who'll give me the answer !
Reply
#2
As you say you have to use an index in the layers list, but AFAIK you can get the nth item of a list using list-ref:
Code:
> (list-ref '(a b c d) 2)
c

Note: it is usually a better idea to declare your script has taking a second argument that will be the target layer (SF-LAYER), and it will be set to the active layer when the script is called from the UI. Otherwise you can be looking for an active layer when there is none (because the active "drawable" is something else, like a channel).
Reply
#3
Oh thanks a lot !!
I'm beginner in Script-fu (Scheme) and carefully studied GIMP doc, and in the tutorial about the lists I see no mention of this function ! Big Grin 
They only speak about the use of car / cdr and compounds ... Angry (Which seemed so strange and absurdly complex...)


Quote:3.3.8. Accessing Other Elements In A List

OK, great, we can get the first element in a list, as well as the rest of the list, but how do we access the second, third or other elements of a list? There exist several "convenience" functions to access, for example, the head of the head of the tail of a list (caadr), the tail of the tail of a list (cddr), etc.

The basic naming convention is easy: The a's and d's represent the heads and tails of lists, so

Code:
(car (cdr (car x) ) )


could be written as:

Code:
(cadar x)


To get some practice with list-accessing functions, try typing in the following (except all on one line if you're using the console); use different variations of car and cdr to access the different elements of the list:

     
Code:
 (let* (
                (x  '( (1 2 (3 4 5) 6)  7  8  (9 10) )
                )
             )
             ; place your car/cdr code here
       )

     

Try accessing the number 3 in the list using only two function calls. If you can do that, you're on your way to becoming a Script-Fu Master!

Angry

So ... thanks again, all becomes so easy now ! ^^

Note : I really need that the script automatically use other layers ... it's part of the main purpose of my script (purpose of automating tasks, you know Tongue)
Reply
#4
(07-22-2024, 04:05 AM)Nival Wrote: Oh thanks a lot !!
I'm beginner in Script-fu (Scheme) and carefully studied GIMP doc, and in the tutorial about the lists I see no mention of this function ! Big Grin 
They only speak about the use of car / cdr and compounds ... Angry (Which seemed so strange and absurdly complex...)


Quote:3.3.8. Accessing Other Elements In A List

OK, great, we can get the first element in a list, as well as the rest of the list, but how do we access the second, third or other elements of a list? There exist several "convenience" functions to access, for example, the head of the head of the tail of a list (caadr), the tail of the tail of a list (cddr), etc.

The basic naming convention is easy: The a's and d's represent the heads and tails of lists, so

Code:
(car (cdr (car x) ) )


could be written as:

Code:
(cadar x)


To get some practice with list-accessing functions, try typing in the following (except all on one line if you're using the console); use different variations of car and cdr to access the different elements of the list:

     
Code:
 (let* (
                (x  '( (1 2 (3 4 5) 6)  7  8  (9 10) )
                )
             )
             ; place your car/cdr code here
       )

     

Try accessing the number 3 in the list using only two function calls. If you can do that, you're on your way to becoming a Script-Fu Master!

Angry

So ... thanks again, all becomes so easy now ! ^^

Note : I really need that the script automatically use other layers ... it's part of the main purpose of my script (purpose of automating tasks, you know Tongue)

Script-fu is a subset of the Scheme language (itself a dialect of the Lisp language), so if you can google Scheme questions and answers. I found  list-ref by googling "scheme get nth item in list".

The car/cdr functions are useful and still make sense because you very often want to detatch the first element of the list (car) from the rest (cdr). In particular algorithm are often specified recursively and when processing a list you can replaced the iteration of the list by a function that processed the first item of a list and then call itself on the rest of the list. function to processing a list

Now of course you can enter the 3rd millenium and use Python for your Gimp scripts.
Reply
#5
Gimp documentation suggests Script-Fu as deafault language, I'd thought it was the best fitted ... I'll do with it, too lazy to learn another language now ... ^^

Good idea to directly seek answers for Scheme, I hadn't thought about it ... xo

Thanks for all !
Reply
#6
Ok ... So, some precisions after some tests (and losing my last hair Big Grin ) :

In fact ... list-ref doesn't work ... because gimp-image-get-layers doesn't return a list for the layer IDs ...

gimp-image-get-layers is said to return "The number of layers contained in the image (num-layers >= 0)  [INT32]" and "The list of layers contained in the image. [INT32ARRAY]".
So, as "gimp-..." procedures always return a list, I thought gimp-image-get-layers returns a list with two elements : 1- the number of layers (a number) ; 2- a list of the layers' IDs (a list). But it doesn't work with this assessment...

I experimented a lot, and the list returned is indeed a two-element list, with the first term indeed being a number = the number of layers (ok, and easy to get --> "car (gimp-image-get-layers Image)") ; but the second element is not a list ... but a vector ! (Spent hours to find that ... Dodgy  Ok the description talks about "INT32ARRAY", maybe a term to mean "vector" ... but it's not specified ... and description talks about "list of layers" ...)

Definitely bald now, but it finally works, using vector-ref !
(can get easily the IDs' list (as a vector...) with "cadr (gimp-image-get-layers Image)").

((Could be usefull if someone else is asking.))
Reply


Forum Jump: