 |
| Script Coder |
 |
Joined: May 07, 2014 Posts: 4527 Location: Canada
|
This one client had a watermark automation requirement but it was unique to them so I am not sharing that but what can be shared is what's common among photo editors, gimp-users who like to apply watermarks like all the time. So here it is watermark2.py #!/usr/bin/env python # Author: Tin Tran # Created On: 2024.11.03 # License: Open source whatever the GIMP's license is. # Revisions: # 0.1 Initial Version from gimpfu import * import os import math
def watermark(image,layer,watermarkpng,opacity,stayaway,location): waterimage = pdb.gimp_file_load(watermarkpng,watermarkpng) #incase it's xcf with multiple layers, we'll do a from visible so we get result of .xcf watermarklayer = pdb.gimp_layer_new_from_visible(waterimage,image,'watermark layer') pdb.gimp_image_insert_layer(image,watermarklayer,None,0) #move it to lower right #move it to desired location (bottom right) location = int(location) if location == 0: pdb.gimp_layer_set_offsets(watermarklayer,image.width-watermarklayer.width-stayaway,image.height-watermarklayer.height-stayaway) elif location == 1: pdb.gimp_layer_set_offsets(watermarklayer,stayaway,image.height-watermarklayer.height-stayaway) elif location == 2: pdb.gimp_layer_set_offsets(watermarklayer,image.width-watermarklayer.width-stayaway,stayaway) elif location == 3: pdb.gimp_layer_set_offsets(watermarklayer,stayaway,stayaway) pdb.gimp_layer_set_opacity(watermarklayer,opacity)
register( "python_fu_watermark", "Puts an image watermark on working image", "Puts an image watermark on working image", "author name", "copyright name", "2024.11.06", "Watermark", "RGB*", # Alternately use RGB, RGB*, GRAY*, INDEXED etc. [ #INPUT BEGINS (PF_IMAGE, "image", "Image", None), (PF_DRAWABLE, "layer", "Drawable", None), (PF_FILE, "watermarkpng", "Watermark image(.xcf,.png,.jpg):", "C:\\Users\\tintr\\Desktop\\fiverr\\test\\watermark.png"), (PF_SPINNER, "opacity", "Opacity:", 65, (1, 100, 1)), (PF_INT, "stayaway", "Stay away from borders (pixels):", 50), # PF_INT8, PF_INT16, PF_INT32 similar but no difference in Python. (PF_OPTION,"location", "Location:", 0, ["Lower Right","Lower Left","Upper Right","Upper Left"]), # initially 0th is choice #INPUT ENDS ], [], watermark, menu="<Image>/Python-Fu")
main()
# Below is all the example input types for INPUTS for the plug-in which can be cut and pasted into #INPUT BEGINS section and edited to taste (found online years back that I didn't want to constantly look up) # Since GIMP is free anyways, I thought it would be handy here for me to CUT and PASTE, CHANGE, USE. # (PF_INT, "p0", "_INT:", 0), # PF_INT8, PF_INT16, PF_INT32 similar but no difference in Python. # (PF_FLOAT, "p02", "_FLOAT:", 3.141), # (PF_STRING, "p03", "_STRING:", "foo"), # alias PF_VALUE # (PF_TEXT, "p04", "TEXT:", "bar"), # # PF_VALUE # # Pick one from set of choices # (PF_OPTION,"p1", "OPTION:", 0, ["0th","1st","2nd"]), # initially 0th is choice # (PF_RADIO, "p16", "RADIO:", 0, (("0th", 1),("1st",0))), # note bool indicates initial setting of buttons # # PF_RADIO is usually called a radio button group. # # SLIDER, ADJUSTMENT types require the extra parameter of the form (min, max, step). # (PF_TOGGLE, "p2", "TOGGLE:", 1), # initially True, checked. Alias PF_BOOL # # PF_TOGGLE is usually called a checkbox. # (PF_SLIDER, "p3", "SLIDER:", 0, (0, 100, 10)), # (PF_SPINNER, "p4", "SPINNER:", 21, (1, 1000, 50)), # alias PF_ADJUSTMENT # # Pickers ie combo boxes ie choosers from lists of existing Gimp objects # (PF_COLOR, "p14", "_COLOR:", (100, 21, 40) ), # extra param is RGB triple # # PF_COLOUR is an alias by aussie PyGimp author lol # (PF_IMAGE, "p15", "IMAGE:", None), # should be type gimp.image, but None works # (PF_FONT, "p17", "FONT:", 0), # (PF_FILE, "p18", "FILE:", 0), # (PF_BRUSH, "p19", "BRUSH:", 0), # (PF_PATTERN, "p20", "PATTERN:", 0), # (PF_GRADIENT, "p21", "GRADIENT:", 0), # (PF_PALETTE, "p22", "PALETTE:", 0), # (PF_LAYER, "p23", "LAYER:", None), # (PF_CHANNEL, "p24", "CHANNEL:", None), # ??? Usually empty, I don't know why. # (PF_DRAWABLE, "p25", "DRAWABLE:", None), # # Mostly undocumented, but work # (PF_VECTORS, "p26", "VECTORS:", None), # (PF_FILENAME, "p27", "FILENAME:", 0), # (PF_DIRNAME, "p28", "DIRNAME:", 0) # # PF_REGION might work but probably of little use. See gimpfu.py.
gimp 3.0 plug-in #!/usr/bin/env python3 # Author: Tin Tran # watermark3.py Gimp 3.0 plug-in using pdbcall # # 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 3 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. # # You should have received a copy of the GNU General Public License # along with this program. If not, see <https://www.gnu.org/licenses/>.
import gi gi.require_version('Gimp', '3.0') from gi.repository import Gimp gi.require_version('GimpUi', '3.0') from gi.repository import GimpUi gi.require_version('Gegl', '0.4') from gi.repository import Gegl from gi.repository import GObject from gi.repository import GLib from gi.repository import Gio
import time import sys
def N_(message): return message def _(message): return GLib.dgettext(None, message)
def pdbcall(procedurename,paramnames,paramvalues): pdb_proc = Gimp.get_pdb().lookup_procedure(procedurename) pdb_config = pdb_proc.create_config() for i in range(0,len(paramnames)): pdb_config.set_property(paramnames[i],paramvalues[i]) return pdb_proc.run(pdb_config) def watermark(procedure, run_mode, image, drawables, config, data): if run_mode == Gimp.RunMode.INTERACTIVE: GimpUi.init('python-fu-foggify')
dialog = GimpUi.ProcedureDialog(procedure=procedure, config=config) dialog.fill(None) if not dialog.run(): dialog.destroy() return procedure.new_return_values(Gimp.PDBStatusType.CANCEL, GLib.Error()) else: dialog.destroy() file = config.get_property('file') stayaway = config.get_property('stayaway') opacity = config.get_property('opacity') location = config.get_property('location')
Gimp.context_push() image.undo_group_start() if image.get_base_type() is Gimp.ImageBaseType.RGB: type = Gimp.ImageType.RGBA_IMAGE else: type = Gimp.ImageType.GRAYA_IMAGE
wimage = Gimp.file_load(Gimp.RunMode.NONINTERACTIVE,file) print ("Hello") #calling pdb with helper function result = pdbcall('gimp-layer-new-from-visible', ['image','dest-image','name'], [wimage,image,"watermarklayer"]) watermarkLayer = result.index(1)
# Make layer from visible with destination on existing image # pdb_proc = Gimp.get_pdb().lookup_procedure('gimp-layer-new-from-visible') # pdb_config = pdb_proc.create_config() # #pdb_config.set_property('run-mode', Gimp.RunMode.NONINTERACTIVE) # pdb_config.set_property('image', wimage) # pdb_config.set_property('dest-image',image) # pdb_config.set_property('name', "watermarklayer") # resultCode,watermarkLayer = pdb_proc.run(pdb_config) #print (result.index(0)) #it returns a success and a layer in index 0 and 1 #print (result.index(1)) #watermarklayer = result.index(1)
# insert layer on top pdbcall('gimp-image-insert-layer', ['image','layer','parent','position'], [image,watermarkLayer,None,0])
if location == "lower right": pdbcall('gimp-layer-set-offsets', ['layer','offx','offy'], [watermarkLayer, image.get_width()-watermarkLayer.get_width()-stayaway, image.get_height()-watermarkLayer.get_height()-stayaway] ) elif location == "lower left": pdbcall('gimp-layer-set-offsets', ['layer','offx','offy'], [watermarkLayer, stayaway, image.get_height()-watermarkLayer.get_height()-stayaway] ) elif location == "upper right": pdbcall('gimp-layer-set-offsets', ['layer','offx','offy'], [watermarkLayer, image.get_width()-watermarkLayer.get_width()-stayaway, stayaway] ) elif location == "upper left": pdbcall('gimp-layer-set-offsets', ['layer','offx','offy'], [watermarkLayer, stayaway, stayaway] ) pdbcall('gimp-layer-set-opacity', ['layer','opacity'], [watermarkLayer,opacity]) #for drawable in drawables: # fog = Gimp.Layer.new(image, name, # drawable.get_width(), drawable.get_height(), # type, opacity, # Gimp.LayerMode.NORMAL) # fog.fill(Gimp.FillType.TRANSPARENT) # image.insert_layer(fog, drawable.get_parent(), # image.get_item_position(drawable))
# Gimp.context_set_background(color) # fog.edit_fill(Gimp.FillType.BACKGROUND)
# # create a layer mask for the new layer # mask = fog.create_mask(0) # fog.add_mask(mask)
# add some clouds to the layer # pdb_proc = Gimp.get_pdb().lookup_procedure('plug-in-plasma') # pdb_config = pdb_proc.create_config() # pdb_config.set_property('run-mode', Gimp.RunMode.NONINTERACTIVE) # pdb_config.set_property('image', image) # pdb_config.set_property('drawable', mask) # pdb_config.set_property('seed', int(time.time())) # pdb_config.set_property('stayaway',stayaway) # pdb_proc.run(pdb_config)
# apply the clouds to the layer # fog.remove_mask(Gimp.MaskApplyMode.APPLY) # fog.set_visible(True)
Gimp.displays_flush()
image.undo_group_end() Gimp.context_pop() return procedure.new_return_values(Gimp.PDBStatusType.SUCCESS, GLib.Error())
class Watermark (Gimp.PlugIn): ## GimpPlugIn virtual methods ## def do_set_i18n(self, procname): return True, 'gimp30-python', None
def do_query_procedures(self): return [ 'python-fu-watermark' ]
def do_create_procedure(self, name): Gegl.init(None)
# _color = Gegl.Color.new("black") # _color.set_rgba(0.94, 0.71, 0.27, 1.0)
procedure = Gimp.ImageProcedure.new(self,name,Gimp.PDBProcType.PLUGIN,watermark,None)
procedure.set_image_types("RGB*, GRAY*"); procedure.set_sensitivity_mask (Gimp.ProcedureSensitivityMask.DRAWABLE | Gimp.ProcedureSensitivityMask.DRAWABLES) procedure.set_documentation (_("Add a layer of fog"), _("Adds a layer of fog to the image."), name) procedure.set_menu_label(_("_Watermark...")) procedure.set_attribution("Tin Tran", "Tin Tran", "2024.11.07") procedure.add_menu_path ("<Image>/Filters/Decor") procedure.add_file_argument ("file", _("Watermark Image File"), _("Watermark Imag File"), GObject.ParamFlags.READWRITE)
#I thought I could do this below but I was wrong, so wrong #procedure.set_property('file',"C:\\Users\\tintr\\Desktop\\fiverr\\test\\watermark.png")
#procedure.add_string_argument ("name", _("Layer _name"), _("Layer name"), #_("Clouds"), GObject.ParamFlags.READWRITE) #procedure.add_color_argument ("color", _("_Fog color"), _("Fog color"), #True, _color, GObject.ParamFlags.READWRITE) procedure.add_double_argument ("stayaway", _("_Stay away from borders (pixels)"), _("Stay away from borders (pixels)"), 0.0, 500.0, 50.0, GObject.ParamFlags.READWRITE) procedure.add_double_argument ("opacity", _("O_pacity"), _("Opacity"), 0.0, 100.0, 100.0, GObject.ParamFlags.READWRITE)
#Example using choice/options choice = Gimp.Choice.new() choice.add("lower right", 0, _("Lower Right"), "") choice.add("lower left", 1, _("Lower Left"), "") choice.add("upper right", 2, _("Upper Right"), "") choice.add("upper left", 2, _("Upper Left"), "") procedure.add_choice_argument ("location", _("_Location"), _("Location"), choice, "lower right", GObject.ParamFlags.READWRITE)
return procedure
Gimp.main(Watermark.__gtype__, sys.argv)
I'll try to make another version using API documented here: https://developer.gimp.org/api/ instead of pdb lookup and call should be faster. API version without calling pdb below #!/usr/bin/env python3 # Author: Tin Tran # API version instead pdb calls # watermark3.py Gimp 3.0 plug-in using pdbcall # # 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 3 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. # # You should have received a copy of the GNU General Public License # along with this program. If not, see <https://www.gnu.org/licenses/>.
import gi gi.require_version('Gimp', '3.0') from gi.repository import Gimp gi.require_version('GimpUi', '3.0') from gi.repository import GimpUi gi.require_version('Gegl', '0.4') from gi.repository import Gegl from gi.repository import GObject from gi.repository import GLib from gi.repository import Gio
import time import sys
def N_(message): return message def _(message): return GLib.dgettext(None, message)
def pdbcall(procedurename,paramnames,paramvalues): pdb_proc = Gimp.get_pdb().lookup_procedure(procedurename) pdb_config = pdb_proc.create_config() for i in range(0,len(paramnames)): pdb_config.set_property(paramnames[i],paramvalues[i]) return pdb_proc.run(pdb_config) def watermark(procedure, run_mode, image, drawables, config, data): if run_mode == Gimp.RunMode.INTERACTIVE: GimpUi.init('python-fu-watermark')
dialog = GimpUi.ProcedureDialog(procedure=procedure, config=config) dialog.fill(None) if not dialog.run(): dialog.destroy() return procedure.new_return_values(Gimp.PDBStatusType.CANCEL, GLib.Error()) else: dialog.destroy() file = config.get_property('file') stayaway = config.get_property('stayaway') opacity = config.get_property('opacity') location = config.get_property('location')
Gimp.context_push() image.undo_group_start() if image.get_base_type() is Gimp.ImageBaseType.RGB: type = Gimp.ImageType.RGBA_IMAGE else: type = Gimp.ImageType.GRAYA_IMAGE
wimage = Gimp.file_load(Gimp.RunMode.NONINTERACTIVE,file) #calling pdb with helper function #result = pdbcall('gimp-layer-new-from-visible', # ['image','dest-image','name'], # [wimage,image,"watermarklayer"]) #watermarkLayer = result.index(1)
#api call instead of above pdbcall watermarkLayer = Gimp.Layer.new_from_visible(wimage,image,"watermark layer")
# insert layer on top #pdbcall('gimp-image-insert-layer', # ['image','layer','parent','position'], # [image,watermarkLayer,None,0]) #api call instead of above pdbcall Gimp.Image.insert_layer(image,watermarkLayer,None,0)
if location == "lower right": Gimp.Layer.set_offsets(watermarkLayer, image.get_width()-watermarkLayer.get_width()-stayaway, image.get_height()-watermarkLayer.get_height()-stayaway) elif location == "lower left": Gimp.Layer.set_offsets(watermarkLayer, stayaway, image.get_height()-watermarkLayer.get_height()-stayaway) elif location == "upper right": Gimp.Layer.set_offsets(watermarkLayer, image.get_width()-watermarkLayer.get_width()-stayaway, stayaway) elif location == "upper left": Gimp.Layer.set_offsets(watermarkLayer, stayaway, stayaway) Gimp.Layer.set_opacity(watermarkLayer,opacity)
Gimp.displays_flush() image.undo_group_end() Gimp.context_pop() return procedure.new_return_values(Gimp.PDBStatusType.SUCCESS, GLib.Error())
class Watermark (Gimp.PlugIn): ## GimpPlugIn virtual methods ## def do_set_i18n(self, procname): return True, 'gimp30-python', None
def do_query_procedures(self): return [ 'python-fu-watermark' ]
def do_create_procedure(self, name): Gegl.init(None)
# _color = Gegl.Color.new("black") # _color.set_rgba(0.94, 0.71, 0.27, 1.0)
procedure = Gimp.ImageProcedure.new(self,name,Gimp.PDBProcType.PLUGIN,watermark,None)
procedure.set_image_types("RGB*, GRAY*"); procedure.set_sensitivity_mask (Gimp.ProcedureSensitivityMask.DRAWABLE | Gimp.ProcedureSensitivityMask.DRAWABLES) procedure.set_documentation (_("Add a layer of fog"), _("Adds a layer of fog to the image."), name) procedure.set_menu_label(_("_Watermark...")) procedure.set_attribution("Tin Tran", "Tin Tran", "2024.11.07") procedure.add_menu_path ("<Image>/Filters/Decor")
procedure.add_file_argument ("file", _("_Watermark file"), _("Watermark file"), GObject.ParamFlags.READWRITE)
#try a directory/path # procedure.add_path_argument ("dirto",_("Water_mark Directory"),_("WaterMark Directory"),True, GObject.ParamFlags.READWRITE) #I thought I could do this below but I was wrong, so wrong #procedure.set_property('file',"C:\\Users\\tintr\\Desktop\\fiverr\\test\\watermark.png")
#procedure.add_string_argument ("name", _("Layer _name"), _("Layer name"), #_("Clouds"), GObject.ParamFlags.READWRITE) #procedure.add_color_argument ("color", _("_Fog color"), _("Fog color"), #True, _color, GObject.ParamFlags.READWRITE) procedure.add_double_argument ("stayaway", _("_Stayaway from borders (pixels)"), _("Stayaway from borders (pixels)"), 0.0, 500.0, 50.0, GObject.ParamFlags.READWRITE) procedure.add_double_argument ("opacity", _("O_pacity"), _("Opacity"), 0.0, 100.0, 100.0, GObject.ParamFlags.READWRITE)
#Example using choice/options choice = Gimp.Choice.new() choice.add("lower right", 0, _("Lower Right"), "") choice.add("lower left", 1, _("Lower Left"), "") choice.add("upper right", 2, _("Upper Right"), "") choice.add("upper left", 2, _("Upper Left"), "") procedure.add_choice_argument ("location", _("_Location"), _("Location"), choice, "lower right", GObject.ParamFlags.READWRITE)
return procedure
Gimp.main(Watermark.__gtype__, sys.argv)
| Attachments: |
File comment: gimp 3.0 watermark plug-in - API calls without pdb calls
watermark3.zip [2.58 KiB]
Downloaded 2109 times
|
File comment: gimp 3.0 plug-in needs to be in subfolder same name as the .py file inside it
watermark3.zip [2.97 KiB]
Downloaded 2068 times
|
File comment: watermark2.py
watermark2.zip [2 KiB]
Downloaded 1752 times
|
_________________ TinT
Last edited by trandoductin on Thu Nov 07, 2024 9:00 pm, edited 4 times in total.
|
|