#!/usr/bin/env python
#
# ==============================================================================
# RangeSelection.py V7 - (c) Berthold Hinz 2009
# ==============================================================================
#
# RANGE SELECTION FOR THE GIMP
#
# ==============================================================================
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, version 3 of the License.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
#
#
# ==============================================================================
from gimpfu import *
from string import *
def RangeSelection(img,drw,channel,amount,area,width_of_range,border_l,border_r,feathering,sel_operation,addition_of_higlighting_layer,highlighting_color,mask,mask_mode, mask_format):
pdb.gimp_image_undo_group_start(img)
if pdb.gimp_drawable_is_layer_mask(drw)==1:
m="The current drawable is a layer mask."+ "\n"+"The sript doesn't work on layer masks."+ "\n"+"\n"+ "Please activate the layer and run the script again!"
gimp.message(str(m))
else:
selop={0:'add', 1:'subtract', 2:'replace', 3:'intersect'}
sel_exists=1-pdb.gimp_selection_is_empty(img)
if sel_exists==1 and sel_operation<>2:
pdb.gimp_selection_save(img)
stored_selection=pdb.gimp_image_get_active_channel(img)
elif sel_operation<>2:
m="There was no selection yet." + "\n"+ "\n"+"The chosen operation '" + str(selop[sel_operation])+ "' was ignored!"
gimp.message(m)
# deletes former selections
pdb.gimp_selection_none(img)
base_layer=drw
name=drw.name
channel_number={'R':0,'G':1,'B':2, 'S':1, 'V':2, 'L': 0, 'C':0, 'M':1, 'Y':2, 'Sr':1,'Sg':1,'Sb':1,'Sc':1,'Sm':1,'Sy':1, 'E':2}
cl={0:'V',1:'L',2:'R',3:'G',4:'B',5:'C',6:'M',7:'Y',8:'S',9:'S',10:'S',11:'S',12:'S',13:'S',14:'S', 15:'V'}
channel_letter=cl[channel]
if "RGB".find(channel_letter)>-1:
cmod="RGB"
elif "HSV".find(channel_letter)>-1:
cmod="HSV"
elif "CMY".find(channel_letter)>-1:
cmod="CMY"
elif "LAB".find(channel_letter)>-1:
cmod="LAB"
itype=cmod+"_IMAGE"
nr_base=pdb.gimp_image_get_layer_position(img,drw)
# deletes former selections
pdb.gimp_selection_none(img)
# remembers initial background color
bgc = gimp.get_background()
if channel>8:
# creates copy of drawable if channel for single colour saturation was selected
drw=img.layers[0]
layer_desat = drw.copy(True)
layer_desat.mode = NORMAL_MODE
layer_desat.name = "desaturated"
layer_desat.opacity=100.0
img.add_layer(layer_desat,-1)
drw=layer_desat
if channel<>9:
pdb.gimp_hue_saturation(drw,1,0,0,-100)
if channel<>14:
pdb.gimp_hue_saturation(drw,2,0,0,-100)
if channel<>10:
pdb.gimp_hue_saturation(drw,3,0,0,-100)
if channel<>12:
pdb.gimp_hue_saturation(drw,4,0,0,-100)
if channel<>11:
pdb.gimp_hue_saturation(drw,5,0,0,-100)
if channel<>13:
pdb.gimp_hue_saturation(drw,6,0,0,-100)
nr_base=nr_base+1
if channel==15:
pdb.plug_in_edge(img,drw,amount,1,0)
# creates new layer for displaying selection
DEC_img=pdb.plug_in_decompose(img, drw, cmod, 1)[0]
width = drw.width
height = drw.height
layer_check = gimp.Layer(img, "check", width, height, RGB_IMAGE, 100, NORMAL_MODE)
img.add_layer(layer_check, 0)
pdb.gimp_edit_copy(DEC_img.layers[channel_number[channel_letter]])
pdb.gimp_edit_paste(layer_check,0)
pdb.gimp_floating_sel_anchor(img.layers[0])
layer_check.mode = NORMAL_MODE
layer_check.opacity=50.0
drw=img.layers[0]
pdb.gimp_image_delete(DEC_img)
# calculates borders of range ('min' and 'max')
if area=="highlights":
min=255-255.0/100*width_of_range
max=255
elif area=="shadows":
min=0
max=255.0/100*width_of_range
elif area=="midtones":
min=127.5-(255.0/100*width_of_range/2.0)
max=127.5+(255.0/100*width_of_range/2.0)
else:
min=border_l
max=border_r
if max"custom":
if area=="highlights":
LName=LName+" (" + str(width_of_range)+"% HL)"
if area=="midtones":
LName=LName+" (" + str(width_of_range)+"% MT)"
if area=="shadows":
LName=LName+" (" + str(width_of_range)+"% SH)"
if channel==15:
LName=LName + " ED"+str(int(amount))
if feathering>0:
LName=LName + " F"+str(int(feathering))
if sel_exists==1:
if sel_operation==0:
LName=LName+" (add.)"
if sel_operation==1:
LName=LName+" (subtr.)"
if sel_operation==2:
LName=LName+" (repl.)"
if sel_operation==3:
LName=LName+" (inters.)"
# creates copy of drawable if conversion to layer mask is activated
if mask==True:
drw=img.layers[nr_base+1]
layer_copy = drw.copy(True)
layer_copy.mode = NORMAL_MODE
layer_copy.name = LName
layer_copy.opacity=100.0
img.add_layer(layer_copy,-1)
# creates selection
layer_number=0
if mask==True:
layer_number=layer_number+1
if min>0 and max==255:
pdb.plug_in_exchange (img,img.layers[layer_number],255,255,255,255,255,255,255-min,255-min,255-min)
pdb.gimp_by_color_select(img.layers[layer_number],(255,255,255), 0, 0, True, True, feathering, False)
if max<255 and min==0:
pdb.gimp_invert(img.layers[layer_number])
pdb.plug_in_exchange (img,img.layers[layer_number],255,255,255,255,255,255,max,max,max)
pdb.gimp_by_color_select(img.layers[layer_number],(255,255,255), 0, 0, True, True, feathering, False)
pdb.gimp_invert(img.layers[layer_number])
if max<255 and min>0:
pdb.gimp_selection_none(img)
THR=int(max-min)/2
AM=int(min+THR)
CS=(AM,AM,AM)
pdb.gimp_by_color_select(img.layers[layer_number],(AM,AM,AM), THR, 0, True, True, feathering, False)
if sel_exists==1 and sel_operation<>2:
if sel_operation<>1:
# if mode is not 'subtract'
pdb.gimp_selection_combine(stored_selection,sel_operation)
else:
# subtract new selection from old one
pdb.gimp_selection_save(img)
stored_new_selection=pdb.gimp_image_get_active_channel(img)
pdb.gimp_selection_load(stored_selection)
pdb.gimp_selection_combine(stored_new_selection,sel_operation)
pdb.gimp_layer_add_alpha(img.layers[layer_number])
if max<255 and min==0:
pdb.gimp_invert(img.layers[layer_number])
# erases unselected parts of the image
pdb.gimp_selection_invert(img)
pdb.plug_in_threshold_alpha(img,img.layers[layer_number],255)
pdb.gimp_selection_invert(img)
# highlights selection according chosen highlighting color
gimp.set_background(highlighting_color)
pdb.gimp_edit_fill(img.layers[layer_number],1)
gimp.set_background(bgc)
drw=layer_check
# conversion to layer mask
if mask==True:
drw=base_layer
layer_masked = drw.copy(True)
layer_masked.mode = NORMAL_MODE
layer_masked.name = "masked"
layer_masked.opacity=100.0
img.add_layer(layer_masked,-1)
gimp.set_background(0,0,0)
if mask_format==0:
pdb.gimp_edit_fill(img.layers[0],1)
pdb.gimp_edit_copy(layer_masked)
if pdb.gimp_layer_get_mask(img.layers[1]) <>None:
pdb.gimp_layer_remove_mask(img.layers[1],0)
mask = pdb.gimp_layer_create_mask(base_layer, ADD_WHITE_MASK)
pdb.gimp_layer_add_mask(img.layers[1],mask)
pdb.gimp_edit_paste(mask,0)
drw=mask
pdb.gimp_floating_sel_anchor(img.layers[0])
if mask_mode==0:
pdb.gimp_invert(mask)
if mask_format==1:
pdb.gimp_levels_stretch(mask)
pdb.gimp_image_remove_layer(img,img.layers[0])
pdb.gimp_image_lower_layer(img,img.layers[0])
img.layers[0].name =LName
pdb.gimp_image_set_active_layer(img,img.layers[0])
if addition_of_higlighting_layer==False:
pdb.gimp_image_remove_layer(img,img.layers[0])
if channel>8:
pdb.gimp_image_remove_layer(img,layer_desat)
pdb.gimp_image_undo_group_end(img)
register(
"plug-in-range-selection",
"",
"This plug-in creates selections of ranges (of values, colors, saturation or edges). You can chose one of 16 different channels and set a percentage width of range to be selected for highlights, midtones or shadows of this channel." + "\n"+"Alternatively you can define the left and the right border for a custom range."+"\n"+"The created selection can be converted to a layer mask if desired." +"\n"+"After running the script there will be an adittional layer on top that highlights the selection. The name of this layer contains the chosen settings.",
"Berthold Hinz",
"public domain",
"2009",
"/Select/Adagio Range Selection",
"RGB*, GRAY*",
[(PF_OPTION,"channel",("Channel: "),0,["[V] Value","[L] Luminance","[R] Red","[G] Green","[B] Blue","[C] Cyan","[M] Magenta","[Y] Yellow","[S] Saturation","[Sr] Saturation red","[Sg] Saturation green","[Sb] Saturation blue","[Sc] Saturation cyan","[Sm] Saturation magenta","[Sy] Saturation yellow","[E] Edges"]),
(PF_SLIDER,"amount"," If [E]: Amount of edge detection [ED]:",2,(1,50,1)),
(PF_RADIO,"mode",("Mode:"),"highlights",(("Highlights [HL]","highlights"),("Midtones [MT]","midtones"),("Shadows [SH]","shadows"),("Custom","custom"))),
(PF_SLIDER,"width_of_range","Width of range (%):",33,(1,100,1)),
(PF_SLIDER,"border_l"," Left border (custom mode):",0,(0,254,1)),
(PF_SLIDER,"border_r"," Right border (custom mode):",255,(1,255,1)),
(PF_SLIDER,"feathering","Feathering [F]:",2,(0,50,1)),
(PF_OPTION,"sel_operation",("Operation (if there's already a selection):"),2,["Add","Subtract","Replace","Intersect"]),
(PF_TOGGLE,"addition_of_higlighting_layer","Add highlighting layer:", True),
(PF_COLOR,"highlighting_color"," Highlighting color:",(29,255,210)),
(PF_TOGGLE,"mask","Convert to layer mask (sel. will be deleted):",True),
(PF_OPTION,"mask_mode",(" Layer mask mode:"),0,["White on black","Black on white"]),
(PF_OPTION,"mask_format",(" Layer mask format:"),1,["B&W","Grayscale"])
],
[],
RangeSelection)
main()