diff --git a/pythonfu-gimp3/DeepSky_StarReduction/.gitkeep b/pythonfu-gimp3/DeepSky_StarReduction/.gitkeep new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/pythonfu-gimp3/DeepSky_StarReduction/DeepSky_StarReduction.py b/pythonfu-gimp3/DeepSky_StarReduction/DeepSky_StarReduction.py new file mode 100644 index 0000000000000000000000000000000000000000..1c658ba742c62f667709b8598df85e1b6d040c6d --- /dev/null +++ b/pythonfu-gimp3/DeepSky_StarReduction/DeepSky_StarReduction.py @@ -0,0 +1,178 @@ +#!/usr/bin/env python3 +# -*- coding: UTF-8 -*- + +# ------------------------------------------------------------------------------ +# This program is provided without any guarantee. +# +# The license is LGPL-v3 +# For details, see GNU General Public License, version 3 or later. +# "https://www.gnu.org/licenses/gpl.html" +# ------------------------------------------------------------------------------ +# +# Python-Star-Reduction - Reduce the number of stars in an image. +# + +import sys +import os +import gi + +gi.require_version("Gimp", "3.0") +from gi.repository import Gimp +from gi.repository import Gtk + + +# import local lib +path_pygapm27 = os.path.dirname(os.path.dirname(os.path.dirname(__file__))) +if not path_pygapm27: + path_pygapm27 = os.path.join("..", "..") +sys.path.append(os.path.join(path_pygapm27, "library")) + +# ------------------------------------------------------------------------------ +from pyGapM27 import Pkg, menu_stars, init_language +from pyGapM27 import info_right1 as info_right + +init_language() + +from gp3_plugin import CPlugin +from libTools import check_compatibilty, undo_start, undo_stop +from libTools import create_layer, fill_layer, getMaxDyn, selection_none +from plug_in import wavelet_decompose + + +class CStarReduction(CPlugin): + def __init__(self): + shelp = _("Reduce the number of stars") + + args = [ + self.arg_double( + "threshold", _("Threshold") + "", None, 150.0, (0.0, 255.0), True + ), + self.arg_double( + "opacity", _("Opacity") + " (%)", None, 90.0, (0.0, 100.0), True + ), + self.arg_int( + "radius", _("Grow/Feather Radius") + " (px)", None, 4, (3, 5), False + ), + ] + + CPlugin.__init__( + self, + Pkg + "StarReduction", # name + _("reduce the number of stars in an image"), # blurb + shelp, # help + info_right, # author,copyright, ... + _("Star Reduction"), # menu_label + menu_stars, # menu path + "RGB*", # image_types + args, + ) # parametres + + def Processing(self, timg, tdrawable, **kwparam): + """This GIMP plugin reduces the number of stars in an image. + + Parameters: + timg : The currently selected image. + tdrawable : The layer of the currently selected image. + threshold : threshold to limit the number of stars + opacity : opacity for merging the star mask + radius : radius for the selection tool + """ + cr = check_compatibilty(self.proc_name, timg, tdrawable) + if cr != None: + return cr + + undo_start(timg) + + # duplicate existing layer + layer_dup = tdrawable.copy() + layer_dup.set_name("Mask Layer") + timg.insert_layer(layer_dup, None, -1) + + Gimp.message("Layer Duplicated") + + # wavelet decompose + wavelet_decompose( + timg, layer_dup, scales=7, create_group=False, create_masks=False + ) + + # keep only 2 layers and merge them into a new layer called "Visible" + layers = timg.get_layers() + num_layers = len(layers) + + for i in range(num_layers): + if i < 2: + layers[i].set_visible(True) + else: + layers[i].set_visible(False) + + merged_layer = Gimp.Image.merge_visible_layers( + timg, Gimp.MergeType.CLIP_TO_IMAGE + ) + merged_layer.set_name("Visible") + + # clean layers + timg.remove_layer(layers[7]) + timg.remove_layer(layers[6]) + timg.remove_layer(layers[5]) + timg.remove_layer(layers[4]) + timg.remove_layer(layers[3]) + timg.remove_layer(layers[2]) + + Gimp.message("Wavelet Decomposition Complete") + + # set VALUE threshold + layer = timg.get_layers()[0] + layer.threshold(0, kwparam["threshold"] / 255, 1.0) + + Gimp.message("Color Threshold Set") + + # add a grayscale copy of the layer as a layer mask + mask_layer = layer.create_mask(5) + layer.add_mask(mask_layer) + + timg.select_item(0, mask_layer) + + # Enable grow and feathering + Gimp.Selection.grow(timg, kwparam["radius"]) + Gimp.context_set_feather(True) + Gimp.context_set_feather_radius(kwparam["radius"], kwparam["radius"]) + + # add mask as a selection on the duplicate layer + layer = timg.get_layers()[1] + timg.set_selected_layers([layer]) + mask_selection_layer = layer.create_mask(4) + + layers = timg.get_layers() + layers[1].set_visible(True) + layers[2].set_visible(True) + timg.remove_layer(layers[0]) + selection_none(timg) + + Gimp.message("Mask Created") + + # erode mask and set opacity of the layer + layers = timg.get_layers() + layers[0].set_opacity(kwparam["opacity"]) + + dialog = Gtk.Dialog(title="Instructions", parent=None, flags=0) + dialog.add_button(Gtk.STOCK_OK, Gtk.ResponseType.OK) + + label = Gtk.Label() + label.set_markup( + "Apply Filters -> Generic -> Erode and adjust opacity. \n\nRepeat if necessary." + ) + dialog.vbox.pack_start(label, True, True, 0) + label.show() + + dialog.set_position(Gtk.WindowPosition.CENTER) + + Gimp.message("Apply Filters -> Generic -> Erode and adjust opacity.") + + dialog.run() + dialog.destroy() + + undo_stop(timg) + return ("SUCCESS", "") + + +Gimp.main(CStarReduction.__gtype__, sys.argv)