Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Skript for mirroring left and right side of portrait photo
#1
Hi everybody!

I am a total beginner to Script Fu, and am having a hard time finding good documentation. If anybody has some good general advice, it is very much welcome.

But here is my specific problem:

I would like to write a script which lets me automatically create two images out of one portrait picture: One from the left half of the face and its mirror image, one from the right side respectively. It is to show that a face is never completely symmetric.

In order to get familiar with it all, I have written a very humble script, which should create two copies of the image and flip one of them horizontally.

But already I encounter a problem: It seems to safe the pictures and layers and does not renew them if I apply the script to a new image. Only if I restart GIMP, it renews them. Could somebody please tell me, how I delete the buffer or tell it to overwrite the image/drawable?

And if someone could already tell me the names of the procedures to only copy and flip a selected part of an image and to insert it in a defined place of the new drawable, so I can already try a bit. At least I hope that procedures like this exist...

Thank you so much!
Cheers!
Kat



Here is my current script:


(define (script-fu-two-faces img drw)
  (let* (
        (drawable-width (car (gimp-drawable-width drw)))
        (halfdrawable-width (* drawable-width 0.5))
        (drawable-height (car (gimp-drawable-height drw)))
        (leftimage (car (gimp-image-new drawable-width drawable-height RGB)))
        (leftlayer (car (gimp-layer-new leftimage drawable-width drawable-height 0 "tfl" 100 0)))
        (rightimage (car (gimp-image-new drawable-width drawable-height RGB)))
        (rightlayer (car (gimp-layer-new rightimage drawable-width drawable-height 0 "tfr" 100 0)))
        )

        
        (gimp-image-insert-layer leftimage leftlayer 0 0)
        (gimp-drawable-fill leftlayer WHITE-FILL)
        (gimp-display-new leftimage)
        (gimp-image-insert-layer rightimage rightlayer 0 0)
        (gimp-drawable-fill rightlayer WHITE-FILL)
        (gimp-display-new rightimage)



        (gimp-edit-named-copy drw "tobepastedleft")
        (gimp-edit-named-paste leftlayer "tobepastedleft" TRUE)
        (gimp-displays-flush)


        (gimp-item-transform-flip drw halfdrawable-width 0 halfdrawable-width drawable-height)

        (gimp-edit-named-copy drw "tobepastedright")
        (gimp-edit-named-paste rightlayer "tobepastedright" TRUE)
        (gimp-displays-flush)

        )
        )


(script-fu-register "script-fu-two-faces"
  "Two faces..."
  "Creates an image from left side of the face"
  "K.Imai"
  "K.Imai"
  "2017"
  ""
  SF-IMAGE      "Image"             0
  SF-DRAWABLE   "Drawable to apply" 0
)

(script-fu-menu-register "script-fu-two-faces" "<Image>")
Reply
#2
welcome to gimp-forum.net

I am no coder, I am sure there will someone along soon.

In the meantime there is a script here: http://gimpchat.com/viewtopic.php?f=9&t=14568#p201077 that does similar to your requirement.

It might give some clues for modifying your script.
Reply
#3
gimp-edit-named-paste creates a floating selection that needs to be anchored:
Code:
(define (script-fu-two-faces img drw)
  (let* (
        (drawable-width (car (gimp-drawable-width drw)))
        (halfdrawable-width (* drawable-width 0.5))
        (drawable-height (car (gimp-drawable-height drw)))
        (leftimage (car (gimp-image-new drawable-width drawable-height RGB)))
        (leftlayer (car (gimp-layer-new leftimage drawable-width drawable-height 0 "tfl" 100 0)))
        (rightimage (car (gimp-image-new drawable-width drawable-height RGB)))
        (rightlayer (car (gimp-layer-new rightimage drawable-width drawable-height 0 "tfr" 100 0)))
        (floatingLayer 0)
        )

        
        (gimp-image-insert-layer leftimage leftlayer 0 0)
        (gimp-drawable-fill leftlayer WHITE-FILL)
        (gimp-display-new leftimage)
        (gimp-image-insert-layer rightimage rightlayer 0 0)
        (gimp-drawable-fill rightlayer WHITE-FILL)
        (gimp-display-new rightimage)



        (gimp-edit-named-copy drw "tobepastedleft")
        (set! floatingLayer (car (gimp-edit-named-paste leftlayer "tobepastedleft" TRUE)))
        (gimp-floating-sel-anchor floatingLayer)
        (gimp-displays-flush)


        (gimp-item-transform-flip drw halfdrawable-width 0 halfdrawable-width drawable-height)

        (gimp-edit-named-copy drw "tobepastedright")
        (set! floatingLayer (car (gimp-edit-named-paste rightlayer "tobepastedright" TRUE)))
        (gimp-floating-sel-anchor floatingLayer)
        (gimp-displays-flush)

        )
        )


(script-fu-register "script-fu-two-faces"
  "Two faces..."
  "Creates an image from left side of the face"
  "K.Imai"
  "K.Imai"
  "2017"
  ""
  SF-IMAGE      "Image"             0
  SF-DRAWABLE   "Drawable to apply" 0
)

(script-fu-menu-register "script-fu-two-faces" "<Image>")
Reply
#4
Do not, ever, use clipboard functions internally in scripts!

When you do that:
  • You pollute the system clipboard with stuff the user has no use for
  • You run the risk that the clipboard if overwritten by some other action between your copy and your paste.
You can always copy the object directly, and, if necessary, cut off the excess.

Use of the copy/paste clipboard functions is OK only as an explicit interface to the outside world (as in File>Create>From clipboard, or copying something to the clipboard because it will be used on some other program).
Reply
#5
(08-07-2017, 07:00 PM)Kevin Wrote: gimp-edit-named-paste creates a floating selection that needs to be anchored:
Thank you Kevin. But the problem persists: if I apply the script to another picture without restarting GIMP, it creates the new images (left and right...) from the old picture.

(08-07-2017, 09:33 PM)Ofnuts Wrote: Do not, ever, use clipboard functions internally in scripts!

When you do that:
  • You pollute the system clipboard with stuff the user has no use for
  • You run the risk that the clipboard if overwritten by some other action between your copy and your paste.
You can always copy the object directly, and, if necessary, cut off the excess.

Use of the copy/paste clipboard functions is OK only as an explicit interface to the outside world (as in File>Create>From clipboard, or copying something to the clipboard because it will be used on some other program).

Okay. What is the alternative?
Reply
#6
You need to delete the named buffer after you have used it:

Code:
       (gimp-edit-named-copy drw "tobepastedleft")
       (set! floatingLayer (car (gimp-edit-named-paste leftlayer "tobepastedleft" TRUE)))
       (gimp-floating-sel-anchor floatingLayer)
       (gimp-buffer-delete "tobepastedleft")
       (gimp-displays-flush)
Reply
#7
(08-08-2017, 02:09 PM)Juniata Wrote:
(08-07-2017, 09:33 PM)Ofnuts Wrote: Do not, ever, use clipboard functions internally in scripts!
Okay. What is the alternative?

Mu own code does:

Code:
# make a copy of the layer, with an alpha channel
    mergedLayer=layer # so we return something anyway
    symLayer=layer.copy(True)
    image.add_layer(symLayer)
    symmetryFunction(image,layer,symLayer,symmetry)
    pdb.gimp_edit_clear(symLayer)
    pdb.gimp_selection_invert(image)
    pdb.gimp_edit_clear(layer)
    mergedLayer=image.merge_down(symLayer,EXPAND_AS_NECESSARY)

Where symmetryFunction is something like this (it basically transforms the top layer, and sets a selection so that the adequate parts can be
cleared)
Code:
def straightSymmetryCore(image,layer,symLayer,side):
    # Some arrays to avoid if/else, indexed by 'side'
    flipTypes=[ORIENTATION_VERTICAL,ORIENTATION_VERTICAL,ORIENTATION_HORIZONTAL,ORIENTATION_HORIZONTAL]
    x,y=layer.offsets
    w,h=layer.width,layer.height
    # The rects we delete in the flipped layer
    rects=[(x,y,w,h/2),(x,y+h-h/2,w,h/2),(x+w-w/2,y,w/2,h),(x,y,w/2,h)]
    
    # Rotate and flip as required
    symLayer.transform_flip_simple(flipTypes[side],True,0)
    pdb.gimp_image_select_rectangle(image, CHANNEL_OP_REPLACE,*rects[side])

The complete code is here. Note that:
  • It's Python, not script-fu. if you have to learn a new language to write scripts, use Python. It's easier to learn, and can be used in many more places
    than Scheme/script-fu. If will also allow you to do more things.
  • I use my scripts as test beds for new programming techniques. I hate verbosity, and repeating myself. It may make my code a bit obscure for the beginners. Simple Python is easier to read than simple script-fu.
Reply


Forum Jump: