TheRepoClub-DotFiles/gimp/.config/GIMP/2.10/plug-ins/plugin-heal-selection.py

185 lines
6.4 KiB
Python
Raw Normal View History

2021-01-09 12:38:56 -05:00
#!/usr/bin/env python
'''
Gimp plugin "Heal selection"
Copyright 2009 lloyd konneker (bootch at nc.rr.com)
Based on smart_remove.scm Copyright 2000 by Paul Harrison.
Version:
1.0 lloyd konneker lkk 9/21/2009 Initial version in python.
(See release notes for differences over P. Harrison's prior version in scheme language.)
License:
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; either version 2 of the License, or
(at your option) any later version.
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.
The GNU Public License is available at
http://www.gnu.org/copyleft/gpl.html
'''
from gimpfu import *
gettext.install("resynthesizer", gimp.locale_directory, unicode=True)
debug = False
def heal_selection(timg, tdrawable, samplingRadiusParam=50, directionParam=0, orderParam=0):
'''
Create stencil selection in a temp image to pass as source (corpus) to plugin resynthesizer,
which does the substantive work.
'''
if pdb.gimp_selection_is_empty(timg):
pdb.gimp_message(_("You must first select a region to heal."))
return
pdb.gimp_image_undo_group_start(timg)
targetBounds = tdrawable.mask_bounds
# In duplicate image, create the sample (corpus).
# (I tried to use a temporary layer but found it easier to use duplicate image.)
tempImage = pdb.gimp_image_duplicate(timg)
if not tempImage:
raise RuntimeError, "Failed duplicate image"
# !!! The drawable can be a mask (grayscale channel), don't restrict to layer.
work_drawable = pdb.gimp_image_get_active_drawable(tempImage)
if not work_drawable:
raise RuntimeError, "Failed get active drawable"
'''
grow and punch hole, making a frisket iow stencil iow donut
'''
orgSelection = pdb.gimp_selection_save(tempImage) # save for later use
pdb.gimp_selection_grow(tempImage, samplingRadiusParam)
# ??? returns None , docs say it returns SUCCESS
# !!! Note that if selection is a bordering ring already, growing expanded it inwards.
# Which is what we want, to make a corpus inwards.
grownSelection = pdb.gimp_selection_save(tempImage)
# Cut hole where the original selection was, so we don't sample from it.
# !!! Note that gimp enums/constants are not prefixed with GIMP_
pdb.gimp_selection_combine(orgSelection, CHANNEL_OP_SUBTRACT)
'''
Selection (to be the corpus) is donut or frisket around the original target T
xxx
xTx
xxx
'''
# crop the temp image to size of selection to save memory and for directional healing!!
frisketBounds = grownSelection.mask_bounds
frisketLowerLeftX = frisketBounds[0]
frisketLowerLeftY = frisketBounds[1]
frisketUpperRightX = frisketBounds[2]
frisketUpperRightY = frisketBounds[3]
targetLowerLeftX = targetBounds[0]
targetLowerLeftY = targetBounds[1]
targetUpperRightX = targetBounds[2]
targetUpperRightY = targetBounds[3]
frisketWidth = frisketUpperRightX - frisketLowerLeftX
frisketHeight = frisketUpperRightY - frisketLowerLeftY
# User's choice of direction affects the corpus shape, and is also passed to resynthesizer plugin
if directionParam == 0: # all around
# Crop to the entire frisket
newWidth, newHeight, newLLX, newLLY = ( frisketWidth, frisketHeight,
frisketLowerLeftX, frisketLowerLeftY )
elif directionParam == 1: # sides
# Crop to target height and frisket width: XTX
newWidth, newHeight, newLLX, newLLY = ( frisketWidth, targetUpperRightY-targetLowerLeftY,
frisketLowerLeftX, targetLowerLeftY )
elif directionParam == 2: # above and below
# X Crop to target width and frisket height
# T
# X
newWidth, newHeight, newLLX, newLLY = ( targetUpperRightX-targetLowerLeftX, frisketHeight,
targetLowerLeftX, frisketLowerLeftY )
# Restrict crop to image size (condition of gimp_image_crop) eg when off edge of image
newWidth = min(pdb.gimp_image_width(tempImage) - newLLX, newWidth)
newHeight = min(pdb.gimp_image_height(tempImage) - newLLY, newHeight)
pdb.gimp_image_crop(tempImage, newWidth, newHeight, newLLX, newLLY)
# Encode two script params into one resynthesizer param.
# use border 1 means fill target in random order
# use border 0 is for texture mapping operations, not used by this script
if not orderParam :
useBorder = 1 # User wants NO order, ie random filling
elif orderParam == 1 : # Inward to corpus. 2,3,4
useBorder = directionParam + 2 # !!! Offset by 2 to get past the original two boolean values
else:
# Outward from image center.
# 5+0=5 outward concentric
# 5+1=6 outward from sides
# 5+2=7 outward above and below
useBorder = directionParam + 5
# Note that the old resynthesizer required an inverted selection !!
if debug:
try:
gimp.Display(tempImage)
gimp.displays_flush()
except RuntimeError: # thrown if non-interactive
pass
from time import sleep
sleep(2)
# Not necessary to restore image to initial condition of selection, activity,
# the original image should not have been changed,
# and the resynthesizer should only heal, not change selection.
# Note that the API hasn't changed but use_border param now has more values.
pdb.plug_in_resynthesizer(timg, tdrawable, 0,0, useBorder, work_drawable.ID, -1, -1, 0.0, 0.117, 16, 500)
# Clean up (comment out to debug)
gimp.delete(tempImage)
pdb.gimp_image_undo_group_end(timg)
register(
"python_fu_heal_selection",
N_("Heal the selection from surroundings as if using the heal tool."),
"Requires separate resynthesizer plugin.",
"Lloyd Konneker",
"2009 Lloyd Konneker", # Copyright
"2009",
N_("_Heal selection..."),
"RGB*, GRAY*",
[
(PF_IMAGE, "image", "Input image", None),
(PF_DRAWABLE, "drawable", "Input drawable", None),
(PF_INT, "samplingRadiusParam", _("Context sampling width (pixels):"), 50),
(PF_OPTION,"directionParam", _("Sample from:"),0,[_("All around"),_("Sides"),_("Above and below")]),
(PF_OPTION, "orderParam", _("Filling order:"), 0, [_("Random"),
_("Inwards towards center"), _("Outwards from center") ])
],
[],
heal_selection,
menu="<Image>/Filters/Enhance",
domain=("resynthesizer", gimp.locale_directory)
)
main()