It is currently Wed May 08, 2024 2:38 am


All times are UTC - 5 hours [ DST ]



Post new topic Reply to topic  [ 44 posts ]  Go to page 1, 2, 3  Next
Author Message
 Post subject: Shrink Grow Feather Selection with LIVE PREVIEW
PostPosted: Tue Nov 07, 2023 12:07 pm  (#1) 
Offline
Script Coder
User avatar

Joined: May 07, 2014
Posts: 3975
Location: Canada
Shrink/Grow/Feather LIVE PREVIEW GIMP
Plug-in
Sometimes we want to be able to view our changing our selection by growing/shrinking or feathering but having to use the built in calls doesn't allow us to see the effect live and it's multiple calls too.
So I thought this plug-in should help with that takes some guess work out of making a selection.
#!/usr/bin/env python
#grow-shrink-live.py
# Creator: TT
# This should allow user to adjust grow/shrink current selection with live preview
# Open Source
from gimpfu import *
import gtk

# Global variables to store the parameters used for our effect/work to show preview or actual layer when user OK it
global_param1 = 0 #in this example it's shrinkgrow radius
global_param2 = 0   #in this example it's feather_radius
global_param3 = 10  #in this example it's iterations
global_param4 = 0   #in this example it's enhance_shadows

image = 0 #we'll set these when dialog() is called so that we can access them later
drawable = 0
has_preview = False
preview_layer = 0
#for this operation
selection_channel = 0

def apply_effect(layer): #function to do work on either preview layer or actual drawable when user clicks OK
    global image
    radius = global_param1
    feather_radius = global_param2
    pdb.gimp_image_select_item(image,CHANNEL_OP_REPLACE,selection_channel) #first we selected the original saved channel
    if radius < 0:
        pdb.gimp_selection_shrink(image,-radius)
    else:
        pdb.gimp_selection_grow(image,radius)
    pdb.gimp_selection_feather(image,feather_radius)
    #do something to it to show it's effect so that user can distinguish between selected area or not
    pdb.gimp_drawable_edit_fill(layer,FILL_FOREGROUND)

    #pdb.gimp_ellipse_select(image,image.width/2-width/2,image.height/2-height/2,width,height,CHANNEL_OP_REPLACE,TRUE,FALSE,0)
    #pdb.gimp_drawable_invert(layer,TRUE)
    #pdb.gimp_selection_none(image)
    gimp.displays_flush()

def apply_final(layer): #wrapper to apply effect on final and remove preview_layer meant to be called by on_ok_button_clicked
    global preview_layer
    #pdb.gimp_image_undo_group_start(image) #so it's undone in Ctrl+Z
    pdb.gimp_image_undo_enable(image) #so that user can undo this next step
    apply_effect(preview_layer)
    #pdb.gimp_image_undo_group_end(image)
    if has_preview:
        pdb.gimp_image_remove_channel(image,selection_channel) #so that we don't leave a saved channel laying around
        pdb.gimp_image_remove_layer(image,preview_layer)
    pdb.gimp_image_set_active_layer(image,drawable)
    pdb.gimp_context_set_foreground(save_foreground)
    gimp.displays_flush()
   
# Function to update the live preview
def update_live_preview(): #this is called everytime some parameter changes
    global global_param1, global_param2, global_param3, global_param4
    global image,drawable
    global has_preview,preview_layer #deal with preview layer
    global selection_channel #this will save our current selection
    # Apply your plugin's effect using the current parameters
    # Use global_param1 and global_param2 to access the user's inputs
    if not has_preview: #create a preview layer
        #pdb.gimp_message("Creating preview")
        preview_layer = pdb.gimp_layer_new(image,image.width,image.height,RGBA_IMAGE,"preview",70,LAYER_MODE_NORMAL)
        pdb.gimp_image_insert_layer(image,preview_layer,None,0) #insert top most so we see it
        non_empty,x1,y1,x2,y2 = pdb.gimp_selection_bounds(image)
        if non_empty == TRUE:
            pass #there's already a selection
        else:
            pdb.gimp_selection_all(image) #if there's no selection we just select the whole image and work with that   
        selection_channel = pdb.gimp_selection_save(image)
        has_preview = True #now set it true so we can deal with existing layer in later calls
    else: # already have preview layer
        pass
        #pdb.gimp_message("Removing existing and creating new Preview")
        pdb.gimp_image_remove_layer(image,preview_layer) #remove it to create a new one to work on
        preview_layer = pdb.gimp_layer_new(image,image.width,image.height,RGBA_IMAGE,"preview",50,LAYER_MODE_NORMAL)
        pdb.gimp_image_insert_layer(image,preview_layer,None,0) #insert top most so we see it
    pdb.gimp_image_set_active_layer(image,preview_layer)
    #debug message
    #pdb.gimp_message(str(global_param1)+","+str(global_param2)+","+str(global_param3)+","+str(global_param4))

    apply_effect(preview_layer)
   
    # Update the live preview layer with the modified image
   
save_foreground = 0
hilightcolor = (255,0,0)
def dialog(image_, drawable_):
    global image, drawable, save_foreground
    #save these for updates
    image = image_
    pdb.gimp_image_undo_disable(image) #for speed and also when user undo it doesn't see our preview creations/deletions
    drawable = drawable_ 
    save_foreground = pdb.gimp_context_get_foreground()
    pdb.gimp_context_set_foreground(hilightcolor)

    dialog = gtk.Dialog("Shrink/Grow Feather Selection Live Preview", None, gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT)
    dialog.set_default_size(600, 100)

    # Create an HBox to hold the label and slider -------------------------------------------------------------
    hbox = gtk.HBox()
    dialog.vbox.pack_start(hbox, expand=True, fill=True)

    # Create a label on the left-hand side
    label1 = gtk.Label("Shrink/Grow Radius:")
    hbox.pack_start(label1, expand=False, fill=False, padding=5)

    # Create an adjustment for the HScale (slider) with a range from 10 to 90
    adjustment1 = gtk.Adjustment(value=0, lower=-400, upper=400, step_incr=1, page_incr=0)
    param1_scale = gtk.HScale(adjustment=adjustment1)
    param1_scale.set_digits(0)  # Display only integers
    hbox.pack_start(param1_scale, expand=True, fill=True, padding=5)
    # Connect callback functions for user interaction
    param1_scale.connect("value-changed", on_param1_changed)

    # # Create an HBox to hold the label and slider -------------------------------------------------------------
    hbox2 = gtk.HBox()
    dialog.vbox.pack_start(hbox2, expand=True, fill=True)

    # Create a label on the left-hand side
    label2 = gtk.Label("Feather Radius:")
    hbox2.pack_start(label2, expand=False, fill=False, padding=5)

    # Create an adjustment for the HScale (slider) with a range from 10 to 90
    adjustment2 = gtk.Adjustment(value=0, lower=0, upper=400, step_incr=1, page_incr=0)
    param2_scale = gtk.HScale(adjustment=adjustment2)
    param2_scale.set_digits(0)  # Display only integers
    hbox2.pack_start(param2_scale, expand=True, fill=True, padding=5)
    # Connect callback functions for user interaction
    param2_scale.connect("value-changed", on_param2_changed)

    # # Create an HBox to hold the label and slider -------------------------------------------------------------
    # hbox3 = gtk.HBox()
    # dialog.vbox.pack_start(hbox3, expand=True, fill=True)

    # # Create a label on the left-hand side
    # label3 = gtk.Label("iterations:")
    # hbox3.pack_start(label3, expand=False, fill=False, padding=5)

    # # Create an adjustment for the HScale (slider) with a range from 10 to 90
    # adjustment3 = gtk.Adjustment(value=10, lower=1, upper=30, step_incr=1, page_incr=0)
    # param3_scale = gtk.HScale(adjustment=adjustment3)
    # param3_scale.set_digits(0)  # Display only integers
    # hbox3.pack_start(param3_scale, expand=True, fill=True, padding=5)
    # # Connect callback functions for user interaction
    # param3_scale.connect("value-changed", on_param3_changed)

    # Add an OK button
    ok_button = dialog.add_button(gtk.STOCK_OK, gtk.RESPONSE_OK)
    ok_button.connect("clicked", on_ok_button_clicked)
    # Show the dialog
    dialog.show_all()
    update_live_preview() #call this once so we see effect
    dialog.run()
   

# Callback function for updating the live preview when param1 changes
def on_param1_changed(scale):
    global global_param1
    global_param1 = scale.get_value()
    update_live_preview()

# Callback function for updating the live preview when param2 changes
def on_param2_changed(scale):
    global global_param2
    global_param2 = scale.get_value()
    update_live_preview()

def on_param3_changed(scale):
    global global_param3
    global_param3 = scale.get_value()
    update_live_preview()

# Callback function for the OK button
def on_ok_button_clicked(button, data=None):
    global drawable
    apply_final(preview_layer) #preview layer because we don't want to apply the invert to final layer it's just for viewing
    button.get_toplevel().destroy() #destroys the gtk dialog window
# Register the Python-Fu plugin
register(
    "python_fu_grow_shrink_live",
    "Grow/Shrink Current Selection with Live Preview",
    "Grow/Shrink Current Selection with Live Preview",
    "TT",
    "TT",
    "NAME",
    "<Image>/Python-Fu/Live Preview/Grow-Shrink Live",  # Menu location
    "*",  # Image type
    [],
    [],
    dialog
)

main()

preview:
Image

_________________
TinT


Last edited by trandoductin on Fri Dec 08, 2023 9:13 am, edited 1 time in total.

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: Shrink Grow Feather Selection with LIVE PREVIEW
PostPosted: Tue Nov 07, 2023 12:20 pm  (#2) 
Offline
Script Coder
User avatar

Joined: May 07, 2014
Posts: 3975
Location: Canada
I can remember the times I have to do grow or shrink then undo then redo with a different number and then decide if it's in the decent zone acceptable or it needs changing....for times like this plugin should help. Of course, if you new exact values then you would use the built in shrink/grow feather methods.

_________________
TinT


Top
 Post subject: Re: Shrink Grow Feather Selection with LIVE PREVIEW
PostPosted: Thu Nov 09, 2023 2:19 pm  (#3) 
Offline
GimpChat Member

Joined: Jul 28, 2018
Posts: 1196
Good work Tin! I like it. :jumpclap

_________________
https://www.deviantart.com/pocholo17
Image


Top
 Post subject: Re: Shrink Grow Feather Selection with LIVE PREVIEW
PostPosted: Thu Nov 09, 2023 3:03 pm  (#4) 
Offline
Script Coder
User avatar

Joined: May 07, 2014
Posts: 3975
Location: Canada
Thanks Pocholo, glad you like it.

_________________
TinT


Top
 Post subject: Re: Shrink Grow Feather Selection with LIVE PREVIEW
PostPosted: Fri Dec 08, 2023 1:08 am  (#5) 
Offline
GimpChat Member
User avatar

Joined: Jan 13, 2011
Posts: 2257
Location: Poland
Very good plugin.
This just changes the selection - I think it would be better to apply the selection to the selected image (when there are two layers: from the active (top) layer to the bottom layer).
Just for fun with the preview:


Attachments:
LP-gs.jpg
LP-gs.jpg [ 24.47 KiB | Viewed 13726 times ]

_________________
Image

Slava
Ukraini!
Top
 Post subject: Re: Shrink Grow Feather Selection with LIVE PREVIEW
PostPosted: Fri Dec 08, 2023 11:18 am  (#6) 
Offline
GimpChat Member
User avatar

Joined: Nov 15, 2014
Posts: 866
@TinT,

Great plug-in!
It is something I have thought about for a long time. I got as far as producing the layer with the highlight of the selection, but could not find a way of providing a live update in Gimp.
Keep up the good work!

david.


Top
 Post subject: Re: Shrink Grow Feather Selection with LIVE PREVIEW
PostPosted: Sat Dec 09, 2023 9:24 am  (#7) 
Offline
GimpChat Member
User avatar

Joined: Nov 15, 2014
Posts: 866
@TinT,

Never satisfied, so I have been mutilating your plug-ins once again!!!

I found that the sliders were too sensitive for smaller images. I have changed the limits so that they are 90% of the width or the height, whichever is the greater.
Done by my usual development method, trial & error, mainly error!

I have attached the modified file for your comments. I am sure you can improve on what I have done.

david.

Note: the attached file is not a legitimate update - only for Tin's comments.

Attachment:
grow-shrink-live.zip [2.87 KiB]
Downloaded 111 times


Top
 Post subject: Re: Shrink Grow Feather Selection with LIVE PREVIEW
PostPosted: Sat Dec 09, 2023 10:45 am  (#8) 
Offline
Script Coder
User avatar

Joined: May 07, 2014
Posts: 3975
Location: Canada
hi @David,
Looks fine to me. I didn't actually install it just looked at your code logics hehe.

_________________
TinT


Top
 Post subject: Re: Shrink Grow Feather Selection with LIVE PREVIEW
PostPosted: Sun Dec 10, 2023 10:41 am  (#9) 
Offline
GimpChat Member
User avatar

Joined: Nov 15, 2014
Posts: 866
My latest experimental version of Tin's program.

I have succeeded in setting the upper limit for the slider to the size of the image when there is a pre-existing selection and to zero when the program is run without a selection (selection becomes rectangular, total size of image).

The lower limit I have tried to make so that it reduces the selection to just a few pixels in the direction that has the minimum width. It sort of works, but I am not convinced that the logic is correct. Perhaps a fresh pair of eyes can uncover my mistakes!

Criticism, comments and advice greatly welcome

david.

Attachment:
grow-shrink-live.zip [3.11 KiB]
Downloaded 110 times


Top
 Post subject: Re: Shrink Grow Feather Selection with LIVE PREVIEW
PostPosted: Sun Dec 10, 2023 11:24 am  (#10) 
Offline
Script Coder
User avatar

Joined: May 07, 2014
Posts: 3975
Location: Canada
Oh it's broken? I'll look at it again after I drive mom to church... if no one else has yet.

UPDATE: I can't think of anyway to seek for minimum selection as the shape could be oddly shaped and minimum selection isn't always half width or half height, it could be much less than that if the shape is something like the letter A for example. So I used ofnuts suggestion for the other problem and used binary-ish seeking. Although there is a slight pause before the dialog is shown because of this pre-process seeking.
But here it is... you can only grow selection until it touches the closest border and you can only shrink until it has a few pixel thickness.
#!/usr/bin/env python
#grow-shrink-live.py
# Creator: TT
# This should allow user to adjust grow/shrink current selection with live preview
# Open Source
# 09/12/2023 Modified DM to make sliders sensitive to image size.
#            Minimum slider value reduces selection to small value without destruction.
#            If run without selection, selects all so slider only enables reduction.
#
# 09/12/2023 Revision 1 by DM.

from gimpfu import *
import gtk

# Global variables to store the parameters used for our effect/work to show preview or actual layer when user OK it
global_param1 = 0 #in this example it's shrinkgrow radius
global_param2 = 0   #in this example it's feather_radius
global_param3 = 10  #in this example it's iterations
global_param4 = 0   #in this example it's enhance_shadows

image = 0 #we'll set these when dialog() is called so that we can access them later
drawable = 0
has_preview = False
preview_layer = 0
#for this operation
selection_channel = 0

def apply_effect(layer): #function to do work on either preview layer or actual drawable when user clicks OK
    global image
    radius = global_param1
    feather_radius = global_param2
    pdb.gimp_image_select_item(image,CHANNEL_OP_REPLACE,selection_channel) #first we selected the original saved channel
    if radius < 0:
        pdb.gimp_selection_shrink(image,-radius)
    else:
        pdb.gimp_selection_grow(image,radius)
    pdb.gimp_selection_feather(image,feather_radius)
    #do something to it to show it's effect so that user can distinguish between selected area or not
    pdb.gimp_drawable_edit_fill(layer,FILL_FOREGROUND)

    #pdb.gimp_ellipse_select(image,image.width/2-width/2,image.height/2-height/2,width,height,CHANNEL_OP_REPLACE,TRUE,FALSE,0)
    #pdb.gimp_drawable_invert(layer,TRUE)
    #pdb.gimp_selection_none(image)
    gimp.displays_flush()

def apply_final(layer): #wrapper to apply effect on final and remove preview_layer meant to be called by on_ok_button_clicked
    global preview_layer
    #pdb.gimp_image_undo_group_start(image) #so it's undone in Ctrl+Z
    pdb.gimp_image_undo_enable(image) #so that user can undo this next step
    apply_effect(preview_layer)
    #pdb.gimp_image_undo_group_end(image)
    if has_preview:
        pdb.gimp_image_remove_channel(image,selection_channel) #so that we don't leave a saved channel laying around
        pdb.gimp_image_remove_layer(image,preview_layer)
    pdb.gimp_image_set_active_layer(image,drawable)
    pdb.gimp_context_set_foreground(save_foreground)
    gimp.displays_flush()
   
# Function to update the live preview
def update_live_preview(): #this is called everytime some parameter changes
    global global_param1, global_param2, global_param3, global_param4
    global image,drawable
    global has_preview,preview_layer #deal with preview layer
    global selection_channel #this will save our current selection
    # Apply your plugin's effect using the current parameters
    # Use global_param1 and global_param2 to access the user's inputs
    if not has_preview: #create a preview layer
        #pdb.gimp_message("Creating preview")
        preview_layer = pdb.gimp_layer_new(image,image.width,image.height,RGBA_IMAGE,"preview",70,LAYER_MODE_NORMAL)
        pdb.gimp_image_insert_layer(image,preview_layer,None,0) #insert top most so we see it
        non_empty,x1,y1,x2,y2 = pdb.gimp_selection_bounds(image)
        if non_empty == TRUE:
            pass #there's already a selection
        else:
            pdb.gimp_selection_all(image) #if there's no selection we just select the whole image and work with that   
        selection_channel = pdb.gimp_selection_save(image)
        has_preview = True #now set it true so we can deal with existing layer in later calls
    else: # already have preview layer
        pass
        #pdb.gimp_message("Removing existing and creating new Preview")
        pdb.gimp_image_remove_layer(image,preview_layer) #remove it to create a new one to work on
        preview_layer = pdb.gimp_layer_new(image,image.width,image.height,RGBA_IMAGE,"preview",70,LAYER_MODE_NORMAL)
        pdb.gimp_image_insert_layer(image,preview_layer,None,0) #insert top most so we see it
       
    pdb.gimp_image_set_active_layer(image,preview_layer)
    #debug message
    #pdb.gimp_message(str(global_param1)+","+str(global_param2)+","+str(global_param3)+","+str(global_param4))

    apply_effect(preview_layer)
   
    # Update the live preview layer with the modified image
   
save_foreground = 0
hilightcolor = (255,0,0)
def dialog(image_, drawable_):
    global image, drawable, save_foreground, selection_channel
    image = image_
    drawable = drawable_
    selection_channel = pdb.gimp_selection_save(image) #save the selection as we'll be shrinking it multiple times later to find slider_lower limit
    non_empty,x1,y1,x2,y2=pdb.gimp_selection_bounds(image)  # get limits of selection bounding box
   
    h_box = x2-x1 # horizontal width of bounding box
    v_box = y2-y1 # vertical height of bounding box
   
    width = image_.width
    height = image_.height

    left = x1; right = width-x2; #left free space and right free space
    top = y1; bottom = height-y2; #top free space and bottom free space
    slider_limit = min(left,right,top,bottom) #this gets the minimum to layer border so that our selection can only grow to touch the border

    #Do binary seeking to get minimum selection that isn't empty
    min_shrink = 0 #set at zero as minimum shrink
    max_shrink = max(h_box,v_box)/2 #some number we know is out of range but guaranteed has to be zero pixel count.
# ==================================== BINARY SEEKING STARTS
    while min_shrink < max_shrink:
        new_shrink = (min_shrink+max_shrink)//2 #get half way between max and min to see value there
        pdb.gimp_selection_shrink(image,new_shrink) #shrink it to half way
        if pdb.gimp_selection_is_empty(image) == TRUE: #if there's no selection (EMPTY SELECTION) we over shrunk
            max_shrink = new_shrink-1 #make max_shrink smaller
        else:
            min_shrink = new_shrink+1 #make min_shrink larger
        pdb.gimp_image_select_item(image,CHANNEL_OP_REPLACE,selection_channel) #select the original saved selection
    # =================================== BINARY SEEKING ENDS
    #when we get here,new_shrink is our min selection where non_empty is TRUE
    slider_lower = new_shrink-2 #-2 so that is has a tight selection but not zero selection

    pdb.gimp_image_undo_disable(image) #for speed and also when user undo it doesn't see our preview creations/deletions
    save_foreground = pdb.gimp_context_get_foreground()
    pdb.gimp_context_set_foreground(hilightcolor)

    dialog = gtk.Dialog("Shrink/Grow Feather Selection Live Preview", None, gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT)
    dialog.set_default_size(600, 100)

    # Create an HBox to hold the label and slider -------------------------------------------------------------
    hbox = gtk.HBox()
    dialog.vbox.pack_start(hbox, expand=True, fill=True)

    # Create a label on the left-hand side
    label1 = gtk.Label("Shrink/Grow Radius:")
    hbox.pack_start(label1, expand=False, fill=False, padding=5)

    # Create an adjustment for the HScale (slider) with a range from 10 to 90
    adjustment1 = gtk.Adjustment(value=0, lower=-(slider_lower), upper=slider_limit, step_incr=1, page_incr=0) # set slider lower & upper limits
    param1_scale = gtk.HScale(adjustment=adjustment1)
    param1_scale.set_digits(0)  # Display only integers
    hbox.pack_start(param1_scale, expand=True, fill=True, padding=5)
    # Connect callback functions for user interaction
    param1_scale.connect("value-changed", on_param1_changed)

    # # Create an HBox to hold the label and slider -------------------------------------------------------------
    hbox2 = gtk.HBox()
    dialog.vbox.pack_start(hbox2, expand=True, fill=True)

    # Create a label on the left-hand side
    label2 = gtk.Label("Feather Radius:")
    hbox2.pack_start(label2, expand=False, fill=False, padding=5)

    # Create an adjustment for the HScale (slider) with a range from 10 to 90
    adjustment2 = gtk.Adjustment(value=0, lower=0, upper=slider_limit, step_incr=1, page_incr=0) # set feather slider upper limit
    param2_scale = gtk.HScale(adjustment=adjustment2)
    param2_scale.set_digits(0)  # Display only integers
    hbox2.pack_start(param2_scale, expand=True, fill=True, padding=5)
    # Connect callback functions for user interaction
    param2_scale.connect("value-changed", on_param2_changed)

    # # Create an HBox to hold the label and slider -------------------------------------------------------------
    # hbox3 = gtk.HBox()
    # dialog.vbox.pack_start(hbox3, expand=True, fill=True)

    # # Create a label on the left-hand side
    # label3 = gtk.Label("iterations:")
    # hbox3.pack_start(label3, expand=False, fill=False, padding=5)

    # # Create an adjustment for the HScale (slider) with a range from 10 to 90
    # adjustment3 = gtk.Adjustment(value=10, lower=1, upper=30, step_incr=1, page_incr=0)
    # param3_scale = gtk.HScale(adjustment=adjustment3)
    # param3_scale.set_digits(0)  # Display only integers
    # hbox3.pack_start(param3_scale, expand=True, fill=True, padding=5)
    # # Connect callback functions for user interaction
    # param3_scale.connect("value-changed", on_param3_changed)

    # Add an OK button
    ok_button = dialog.add_button(gtk.STOCK_OK, gtk.RESPONSE_OK)
    ok_button.connect("clicked", on_ok_button_clicked)
    # Show the dialog
    dialog.show_all()
    update_live_preview() #call this once so we see effect
    dialog.run()
   

# Callback function for updating the live preview when param1 changes
def on_param1_changed(scale):
    global global_param1
    global_param1 = scale.get_value()
    update_live_preview()

# Callback function for updating the live preview when param2 changes
def on_param2_changed(scale):
    global global_param2
    global_param2 = scale.get_value()
    update_live_preview()

def on_param3_changed(scale):
    global global_param3
    global_param3 = scale.get_value()
    update_live_preview()

# Callback function for the OK button
def on_ok_button_clicked(button, data=None):
    global drawable
    apply_final(preview_layer) #preview layer because we don't want to apply the invert to final layer it's just for viewing
    button.get_toplevel().destroy() #destroys the gtk dialog window
# Register the Python-Fu plugin
register(
    "python_fu_grow_shrink_live",
    "Grow/Shrink Current Selection with Live Preview",
    "Grow/Shrink Current Selection with Live Preview",
    "TT",
    "DM",
    "NAME",
    "<Image>/Python-Fu/Live Preview/Grow-Shrink Live",  # Menu location
    "*",  # Image type
    [],
    [],
    dialog
)

main()

_________________
TinT


Top
 Post subject: Re: Shrink Grow Feather Selection with LIVE PREVIEW
PostPosted: Mon Dec 11, 2023 4:46 am  (#11) 
Offline
GimpChat Member
User avatar

Joined: Nov 15, 2014
Posts: 866
Thanks for the reply. I will print your new code and study it.

My logic for setting the minimum value for the slider was as follows:

A selection has a rectangular bounding box which defines it's limits horizontally and vertically.
As the size of the selection is reduced, the bounding box reduces until at some point it's horizontal or vertical dimension becomes zero and we no longer have a selection.
I attempted to code the minimum value so that it limits the smaller of the bounding box dimensions to one or two pixels.

However, my changes are unimportant. The great thing is that you have created a way of having a live preview!

david.


Top
 Post subject: Re: Shrink Grow Feather Selection with LIVE PREVIEW
PostPosted: Mon Dec 11, 2023 7:44 am  (#12) 
Offline
Script Coder
User avatar

Joined: May 07, 2014
Posts: 3975
Location: Canada
My code does that by seeking until the shrink gives you no selection.
Then I back track by -2 so that it has small selection.

_________________
TinT


Top
 Post subject: Re: Shrink Grow Feather Selection with LIVE PREVIEW
PostPosted: Tue Dec 12, 2023 11:27 am  (#13) 
Offline
GimpChat Member
User avatar

Joined: Nov 15, 2014
Posts: 866
Many years since I have seen a binary sort algorithm! It works OK for small images, but when I tried a .tif file of 145.3 MB it was very, very slow.

I think the attached code will solve the problem (it requires importing math in order to work).
However, I have been unable to test it properly as the program has become unstable and I am unable to find the cause.
It throws an invalid syntax error in the terminal at line 122 "elif h_box >= v_box:"
If I comment out this line, the error appears at line 123. Comment out this line I have an error at line 126, etc, etc.

I have attached the full listing as a zip file.

d_box = (h_box**2 + v_box**2)
    #print ("d_box = " + str(d_box))
    v = math.sqrt(d_box**2 - h_box**2)
    h = math.sqrt(d_box**2 - v_box**2)
    #print ("v = " + str(v)), ("h = " + str(h))
       
    if h_box < v_box:
        slider_lower = int((h + 1) # if h_box < v_box set slider_lower
    elif h_box >= v_box:
        #slider_lower = int(v + 1) # if h_box >= v_box set slider_lower


Attachments:
grow-shrink-live.zip [3.16 KiB]
Downloaded 95 times
Top
 Post subject: Re: Shrink Grow Feather Selection with LIVE PREVIEW
PostPosted: Tue Dec 12, 2023 11:58 am  (#14) 
Offline
Script Coder
User avatar

Joined: May 07, 2014
Posts: 3975
Location: Canada
the line below if has an extra bracket.
if you comment out the line after the elif line then you need some code or just "pass" command to do nothing as python doesn't like empty empty code block.

_________________
TinT


Top
 Post subject: Re: Shrink Grow Feather Selection with LIVE PREVIEW
PostPosted: Tue Dec 12, 2023 4:23 pm  (#15) 
Offline
GimpChat Member
User avatar

Joined: Nov 15, 2014
Posts: 866
Many thanks!!!
I have spent all day and drunk numerous cups of black coffee while failing to find my "bonus" bracket.

I have convinced myself that the diagonal of the selection bounding box is twice the radius that is going to be changed with the slider, because if you make a rectangular selection and grow it the corners are rounded.

Using the binary search to find the value of the diagonal which reduces the shortest side of the bounding box to half its value should be a way of finding the minimum value for the slider. This would save having to recreate the channel numerous times which is probably what makes it slow for a large image.
I had intended to try this today before I wasted so much time with my stupid mistake.

I will not give up. At 77 years of age it is a chance to exercise the rusty brain cells!


Top
 Post subject: Re: Shrink Grow Feather Selection with LIVE PREVIEW
PostPosted: Tue Dec 12, 2023 5:30 pm  (#16) 
Offline
GimpChat Member
User avatar

Joined: Oct 31, 2020
Posts: 1423
Thanks this is really useful for to me. It reminds me of Photoshop CS5's live preview grow and shrink.


Top
 Post subject: Re: Shrink Grow Feather Selection with LIVE PREVIEW
PostPosted: Fri Dec 15, 2023 12:00 pm  (#17) 
Offline
GimpChat Member
User avatar

Joined: Nov 15, 2014
Posts: 866
@TinT,

After running my calculator red-hot for two days, I have almost cracked the problem (thanks to help from my friends).
I had convinced myself that shrink and grow reduced a selection proportionately. Thanks to Ofnuts (see https://www.gimp-forum.net/Thread-Selct ... ink-radius ). I have changed the settings for the lower limits. They are not quite correct, I think something to do with the integer arithmetic, but it saves having to do the search routine.

I have used max() and min() constructs to remove if, elif, else statements.

Krikor tried one of my previous versions and made some comments (see https://www.gimp-forum.net/Thread-Where ... led-plugin entry No.8 ).
As a result I have reduced the opacity of the mask layer to 50% and made sure in my latest version that "feather" can be used when all the image is selected.

A couple of thoughts:
Would it be possible to have a choice of mask colours?
Would a short time delay (tenths of a second) speed up the operation when the sliders are moved by eliminating the need to redraw at every step of the change.

Your comments and criticisms are always welcome!
david.

Attachment:
grow-shrink-live_dm.zip [2.9 KiB]
Downloaded 89 times


Top
 Post subject: Re: Shrink Grow Feather Selection with LIVE PREVIEW
PostPosted: Fri Dec 15, 2023 9:35 pm  (#18) 
Offline
Script Coder
User avatar

Joined: May 07, 2014
Posts: 3975
Location: Canada
@David,
I tried for over an hour and can't get the delayed update work quite right so I gave up, gotta do something else.
But with the color choice I think it would be better if we get average color of selection using histogram call then just add 128, 128, 128 to r g and b values and mod it by 255 so that it's always going to be opposite on the spectrum of the current selection.

_________________
TinT


Top
 Post subject: Re: Shrink Grow Feather Selection with LIVE PREVIEW
PostPosted: Fri Dec 15, 2023 10:52 pm  (#19) 
Offline
GimpChat Member
User avatar

Joined: Jan 13, 2011
Posts: 2257
Location: Poland
This version has the location in the GIMP menu: Select ➤ Grow-Shrink LP...

Edit: attachment removed - next version in post #22


Attachments:
GS LP.jpg
GS LP.jpg [ 31.35 KiB | Viewed 11365 times ]

_________________
Image

Slava
Ukraini!


Last edited by MareroQ on Sun Dec 17, 2023 2:05 pm, edited 1 time in total.
Top
 Post subject: Re: Shrink Grow Feather Selection with LIVE PREVIEW
PostPosted: Sat Dec 16, 2023 8:00 am  (#20) 
Offline
GimpChat Member
User avatar

Joined: Nov 15, 2014
Posts: 866
@TinT,

I like your idea for the colour mask. Perhaps the way I did it in "col-cast-reduction.py" would be the way to go: scale the selected part of the image to a very small size and then pixelize it to it's full dimensions to get the average colour. Otherwise it could be slow for large images/selections.

To speed up the plug-in, I think we need to measure the rate of change of the scale values, but I have absolutely no idea how to code it!
Store the current slide settings and when a setting changes, compare current value after a short time interval with the original value.
While this exceeds a certain value, don't update.
Else update.

I hope this idea is sensible!

I have attached the latest version with the corrected lower limits for the sliders.

david.

Attachment:
grow-shrink-live_dm.zip [2.94 KiB]
Downloaded 77 times


Top
Post new topic Reply to topic  [ 44 posts ]  Go to page 1, 2, 3  Next

All times are UTC - 5 hours [ DST ]


   Similar Topics   Replies 
No new posts Attachment(s) Apply Selection to Layer with LIVE PREVIEW

6

No new posts Attachment(s) Use Shrink or Grow by 1 pixel on command

12

No new posts Attachment(s) Distort with LIVE PREVIEW

5

No new posts Attachment(s) AutoTrace with LIVE PREVIEW

14

No new posts Attachment(s) Potrace with LIVE PREVIEW

0



* Login  



Powered by phpBB3 © phpBB Group