It is currently Mon Apr 15, 2024 7:26 am


All times are UTC - 5 hours [ DST ]



Post new topic Reply to topic  [ 15 posts ] 
Author Message
 Post subject: How can I create a 'visible layers list'?
PostPosted: Thu Dec 19, 2013 6:11 am  (#1) 
Offline
Script Coder
User avatar

Joined: Feb 18, 2011
Posts: 4827
Location: Bendigo Vic. Australia
I'm looking for a way to create a 'visible layers list' at the start of a script because after that i have to set all the layers invisible;
then at the end of the script I can set all the layers from the 'visible layers list' visible

_________________
Image
No matter how much you push the envelope, it'll still be stationery.


Share on Facebook Share on Twitter Share on Orkut Share on Digg Share on MySpace Share on Delicious Share on Technorati
Top
 Post subject: Re: How can I create a 'visible layers list'?
PostPosted: Thu Dec 19, 2013 7:03 am  (#2) 
Offline
Script Coder
User avatar

Joined: Jun 22, 2010
Posts: 1171
Location: Here and there
I think that you get a list of all the layers, then scan through that list applying gimp-drawable-get-visible and if it returns TRUE, then add it to a new list.

Kevin


Top
 Post subject: Re: How can I create a 'visible layers list'?
PostPosted: Thu Dec 19, 2013 7:03 am  (#3) 
Offline
GimpChat Founder
User avatar

Joined: May 22, 2008
Posts: 5242
Location: Gimpville
:ninja

You could just loop through all the layers and check to see which are visible with gimp-item-get-visible, then save those layers in a vector using gimp-image-get-active-layer.

At the end of the script, loop though the vector and make each of stored layers visible again using gimp-item-set-visible. Maybe there is a more efficient way but that's what I would do.

_________________
“If you reach for the stars, you just might land on a decently sized hill.” - Stuart Hill


Top
 Post subject: Re: How can I create a 'visible layers list'?
PostPosted: Thu Dec 19, 2013 7:21 am  (#4) 
Offline
Script Coder
User avatar

Joined: Oct 25, 2010
Posts: 4734
Graechan wrote:
I'm looking for a way to create a 'visible layers list' at the start of a script because after that i have to set all the layers invisible;
then at the end of the script I can set all the layers from the 'visible layers list' visible

visibleLayers=[layer for layer in image.layers if layer.visible]


But I don't see the purpose of this unless you are trying to emulate an animation by uncovering the layers one by one?

_________________
Image


Top
 Post subject: Re: How can I create a 'visible layers list'?
PostPosted: Thu Dec 19, 2013 7:47 am  (#5) 
Offline
Script Coder
User avatar

Joined: Feb 18, 2011
Posts: 4827
Location: Bendigo Vic. Australia
(set! layerList (vector->list (cadr (gimp-image-get-layers image))))
(set! visibleList (vector->list null)

(while (not (null? layerList))
(set! layerId (car layerList))
(if (= (car(gimp-drawable-get-visible layerId)) true)) (set! visibleList (+ visibleList layerId))
(set! layerList (cdr layerList)))


the highlighted section is what I'm not sure of,(e.g. how to add new layers to an existing list)

_________________
Image
No matter how much you push the envelope, it'll still be stationery.


Top
 Post subject: Re: How can I create a 'visible layers list'?
PostPosted: Thu Dec 19, 2013 7:51 am  (#6) 
Offline
GimpChat Member
User avatar

Joined: May 16, 2010
Posts: 14709
Location: USA
Probably having different layers opening on a canvas that shows them all simultaneously?
Each layer staying visible on the canvas as they open 1 at a time.

My guess anyways. Could be a lot of uses for that. Loading bars for 1.

_________________
Image
Edmund Burke nailed it when he said, "The only thing necessary for the triumph of evil is for good men to do nothing."


Top
 Post subject: Re: How can I create a 'visible layers list'?
PostPosted: Thu Dec 19, 2013 8:13 am  (#7) 
Offline
Script Coder
User avatar

Joined: Apr 23, 2010
Posts: 1553
Location: not from Guildford after all
Graechan wrote:
the highlighted section is what I'm not sure of,(e.g. how to add new layers to an existing list)

To add a new element to a list of elements, you would use 'cons', which is short for "construct". The new element is placed at the front of the list (to avoid having to walk along the length of the list to find its end).

The following code snippet uses "named let" to loop through each of the layers. This is generally considered preferable to using "while" loops since there is no need to use 'set!' to change the state of a variable. Note that I use 'reverse' on the final list of visibles to maintain the top-to-bottom ordering of the layers (this is necessary because 'cons'ing builds the list in reverse order).

(let ((visibles (let loop ((layers (vector->list (cadr (gimp-image-get-layers image))))
                           (visibles '()) )
                  (if (null? layers)
                    (reverse visibles)
                    (loop (cdr layers)
                          (if (zero? (car (gimp-drawable-get-visible layer)))
                            visibles
                            (cons (car layers) visibles) ))))))
  ; To hide all of the originally visible layers
  (map (lambda (x) (gimp-drawable-set-visible x FALSE)) visibles)
  ;
  ; DO STUFF HERE
  ;
  ; To restore all of the originally visible layers to being visible
  (map (lambda (x) (gimp-drawable-set-visible x TRUE)) visibles)
  )


Alternately, you could use 'for-each' instead of 'map'. 'for-each' is acceptable whenever you don't care about the result being returned which is the case here; however, I just prefer to use 'map' since it works either way.

Another approach to obtaining the visibles is to use folding. Script-fu's 'foldr' function is not exactly the same as the traditional 'fold-right', but it does serve the same purpose.
(let ((visibles (foldr (lambda (a x)
                         (if (zero? (car (gimp-drawable-get-visible x)))
                           a
                           (cons x a) ))
                       '()
                       (reverse (vector->list (cadr (gimp-image-get-layers image)))) )))
  ;
  ;
  ;

_________________
Any sufficiently primitive technology is indistinguishable from a rock.


Top
 Post subject: Re: How can I create a 'visible layers list'?
PostPosted: Thu Dec 19, 2013 8:19 am  (#8) 
Offline
Script Coder
User avatar

Joined: Oct 25, 2010
Posts: 4734
Graechan, come to the dark side of python-fu(*) :)

Otherwise see: http://en.wikipedia.org/wiki/List_comprehension#Scheme

(*) and the the 21th Century, 3rd millenium, etc...

_________________
Image


Top
 Post subject: Re: How can I create a 'visible layers list'?
PostPosted: Thu Dec 19, 2013 10:02 am  (#9) 
Offline
Script Coder
User avatar

Joined: Nov 06, 2012
Posts: 239
Location: Italy
Hi Graechan.
Saulgoode and the others who replied before me have already given you suitable advices on how to proceed, so I have nothing to add in this regard.

However, just one last remark: when you operate in GIMP 2.8 and above and you deal with an image fitted with one or more layer groups, notice that the "gimp-image-get-layers" procedure alone is not enough to detect and list all the layers in the image, since it can only return those placed in the main stack, while omitting the ones embedded in groups at any level of nesting.
So, in that case, you ought to recursively invoke the "gimp-item-get-children" procedure whenever a layer group is detected during the loop in order to make sure to trace every layer in each group.

If you are interested, take a glance at this procedure that I implemented in my "Identify Image Objects" script just for working around the aforesaid limitation of the "gimp-image-get-layers" command, where you can see that it produces the very same type of output, namely a list containing the actual number of layers alongside the array with their identifiers:

(define (gimp-image-get-nested-layers image)
  (letrec
   ((find-children
     (lambda (layer-ids k n)
       (if (< k n)
           (let* ((layer-k (vector-ref layer-ids k)))
             (append
              (cons layer-k
                    (if (= (car (gimp-item-is-group layer-k)) TRUE)
                        (find-children
                         (car (cdr
                               (gimp-item-get-children layer-k)))
                         0
                         (car (gimp-item-get-children layer-k)))
                        ()))
              (find-children layer-ids (+ k 1) n)))
           ()))))
    (let* ((all-layers
            (apply vector
                   (find-children
                    (car (cdr (gimp-image-get-layers image)))
                    0
                    (car (gimp-image-get-layers image))))))
      (cons (vector-length all-layers)
            (cons all-layers
                  ())))))

_________________
Gino D's GIMP scripts: https://sites.google.com/site/ginodonig/gimp-scripts


Top
 Post subject: Re: How can I create a 'visible layers list'?
PostPosted: Thu Dec 19, 2013 11:20 pm  (#10) 
Offline
Script Coder
User avatar

Joined: Feb 18, 2011
Posts: 4827
Location: Bendigo Vic. Australia
Saulgoode everything was OK untill it came time to set the visible layers visible again, probably because the
visible list should not contain the drawable Which is the active layer below is the code I used

(gimp-drawable-set-visible drawable FALSE)
  (let ((visibles (let loop ((layers (vector->list (cadr (gimp-image-get-layers img))))
                           (visibles '()) )
                  (if (null? layers)
                    (reverse visibles)
                    (loop (cdr layers)
                          (if (zero? (car (gimp-drawable-get-visible drawable)))
                            visibles
                            (cons (car layers) visibles) ))))))
  ; To hide all of the originally visible layers
    (map (lambda (x) (gimp-drawable-set-visible x FALSE)) visibles)
    (gimp-drawable-set-visible drawable TRUE)

the reason for this is that the drawable Id is changed during the script

_________________
Image
No matter how much you push the envelope, it'll still be stationery.


Top
 Post subject: Re: How can I create a 'visible layers list'?
PostPosted: Fri Dec 20, 2013 12:04 am  (#11) 
Offline
Script Coder
User avatar

Joined: Apr 23, 2010
Posts: 1553
Location: not from Guildford after all
Graechan wrote:
Saulgoode everything was OK untill it came time to set the visible layers visible again, probably because the
visible list should not contain the drawable Which is the active layer

Correct. You can remove the active layer from the list with 'delq':
(set! visibles (delq drawable visibles))

Graechan wrote:
the reason for this is that the drawable Id is changed during the script

The drawable ID will change if you perform a Merge Down or a Merge Visible Layers. It also changes when certain filters are run (but this is fairly rare). As long as you remove the original drawable's ID from your list of visibles before unhiding them, you should be fine.

_________________
Any sufficiently primitive technology is indistinguishable from a rock.


Top
 Post subject: Re: How can I create a 'visible layers list'?
PostPosted: Fri Dec 20, 2013 12:51 am  (#12) 
Offline
Script Coder
User avatar

Joined: Feb 18, 2011
Posts: 4827
Location: Bendigo Vic. Australia
Saulgoode you are right as I need to use both Gmic and merge visible layers on the drawable it didn't stand a chance of keeping its Id

_________________
Image
No matter how much you push the envelope, it'll still be stationery.


Top
 Post subject: Re: How can I create a 'visible layers list'?
PostPosted: Fri Dec 20, 2013 1:34 am  (#13) 
Offline
Script Coder
User avatar

Joined: Feb 18, 2011
Posts: 4827
Location: Bendigo Vic. Australia
Saulgoode worked OK but at the end when I restored the visible layers it set all the layers visible
entire code below

;;;; set all layers except drawable invisible   
   (let ((visibles (let loop ((layers (vector->list (cadr (gimp-image-get-layers image))))
                           (visibles '()) )
                  (if (null? layers)
                    (reverse visibles)
                    (loop (cdr layers)
                          (if (zero? (car (gimp-drawable-get-visible drawable)))
                            visibles
                            (cons (car layers) visibles) ))))))
   (set! visibles (delq drawable visibles))                  
  ; To hide all of the originally visible layers
    (map (lambda (x) (gimp-drawable-set-visible x FALSE)) visibles)

       
;;;;begin the script   

   
   
   (let* (
         (copy-layer (car (gimp-layer-copy drawable TRUE)))
       (before (vector->list (cadr (gimp-image-get-layers image))))
       (after 0)
         )

    ;; Add a copy of the layer to the image.
    (gimp-image-add-layer image copy-layer -1)

    ;; Render Split Details from the active layer, using G'MIC.
    (plug-in-gmic 1 image drawable 1
                  (string-append
                   "-v - " ; To have a silent output. Remove it to display errors from the G'MIC interpreter on stderr.
                   "-split_details "
                   (number->string nbs) ","
                   (number->string ratio) " -+[^0] 128 -c 0,255 -reverse"
                   ))
   (set! after (vector->list (cadr (gimp-image-get-layers image))))            
   (map (lambda (x) (if  (eq? (member x before) #f) (gimp-layer-set-mode x GRAIN-MERGE-MODE))) after)
   (set! drawable (car (gimp-image-merge-visible-layers image EXPAND-AS-NECESSARY)))
   
    ) ;end gmic variables   

   ; To restore all of the originally visible layers to being visible
    (map (lambda (x) (gimp-drawable-set-visible x TRUE)) visibles)

    ) ;endlet for visibles
   
   (gimp-displays-flush)
   (gimp-image-undo-group-end image)
   (gimp-context-pop)   

) ;end variables
) ;end procedure

somehow the visibles list included invisible layers

_________________
Image
No matter how much you push the envelope, it'll still be stationery.


Top
 Post subject: Re: How can I create a 'visible layers list'?
PostPosted: Fri Dec 20, 2013 1:48 am  (#14) 
Offline
Script Coder
User avatar

Joined: Apr 23, 2010
Posts: 1553
Location: not from Guildford after all
Oops! I made a mistake in my code. Here is what it should be (the reference to 'drawable' should be to the first layer in the list of layers):

(let ((visibles (let loop ((layers (vector->list (cadr (gimp-image-get-layers image))))
                           (visibles '()) )
                  (if (null? layers)
                    (reverse visibles)
                    (loop (cdr layers)
                          (if (zero? (car (gimp-drawable-get-visible (car layers))))
                            visibles
                            (cons (car layers) visibles) ))))))


Sorry about that.

_________________
Any sufficiently primitive technology is indistinguishable from a rock.


Top
 Post subject: Re: How can I create a 'visible layers list'?
PostPosted: Fri Dec 20, 2013 2:26 am  (#15) 
Offline
Script Coder
User avatar

Joined: Feb 18, 2011
Posts: 4827
Location: Bendigo Vic. Australia
Thank you Saulgoode everything OK, I look at this as my education on lists and they are interesting to use :bigthup

_________________
Image
No matter how much you push the envelope, it'll still be stationery.


Top
Post new topic Reply to topic  [ 15 posts ] 

All times are UTC - 5 hours [ DST ]


   Similar Topics   Replies 
No new posts Batch Create Layers

2

No new posts Attachment(s) Distorting Layers to Create Map "Gores"

3

No new posts Is it possible to make a new path from the visible?

5

No new posts How to find a list of enums?

5

No new posts Attachment(s) create a brush

13



* Login  



Powered by phpBB3 © phpBB Group