def something(): #MyPaint.init() # Create a brush, load from disk brush = MyPaint.Brush() brush_def = open("brushes/classic/brush.myb").read() brush.from_string(brush_def) # List all settings # TODO: Is there a better way to list all enums with GI? settings = [getattr(MyPaint.BrushSetting, attr) for attr in dir(MyPaint.BrushSetting) if attr.startswith("SETTING_")] print "Available settings: %s\n" % str(settings) # Get info about a given setting setting = MyPaint.BrushSetting.SETTING_RADIUS_LOGARITHMIC info = MyPaint.brush_setting_info(setting) # TODO: rename "def_" to "default" print "Setting: %s\n\t Max: %f \n\t Default: %f \n\t Min: %f" % (info.cname, info.max, info.def_, info.min) print "\t Name: %s\n\t Tooltip: '%s'\n" % (info.get_name(), info.get_tooltip()) # Use the getters so that i18n works # TODO: should be MyPaint.BrushSetting.from_cname # Same with MyPaint.Brush.input_from_cname assert (MyPaint.Brush.setting_from_cname(info.cname) == setting) # Get/Set current base value for the given setting print "Base value is: %f" % brush.get_base_value(setting) brush.set_base_value(setting, 2.0) assert brush.get_base_value(setting) == 2.0 # Get dynamics for given setting inputs = [getattr(MyPaint.BrushInput, a) for a in dir(MyPaint.BrushInput) if a.startswith('INPUT_')] if not brush.is_constant(setting): for input in inputs: mapping_points = brush.get_mapping_n(setting, input) if mapping_points > 1: # If 0, no dynamics for this input points = [brush.get_mapping_point(setting, input, i) for i in range(mapping_points)] print "Has dynamics for input %s:\n%s" % (input, str(points)) # Create a surface to paint on Gegl.init(0, "") surface = MyPaintGegl.TiledSurface() s = surface.interface() print surface.get_buffer() for x, y in [(0.0, 0.0), (100.0, 100.0), (100.0, 200.0)]: dtime = 0.1 # XXX: Important to set correctly for speed calculations s.begin_atomic() brush.stroke_to(s, x, y, pressure=1.0, xtilt=0.0, ytilt=0.0, dtime=dtime) rect = s.end_atomic() print rect.x, rect.y, rect.width, rect.height Gegl.exit()
def main(): # Parse options parser = argparse.ArgumentParser(description='An argparse snippet.') parser.add_argument("--infile", "-i", help="the input file", required=True, metavar="STRING") parser.add_argument("--outfile", "-o", help="the output file", required=True, metavar="STRING") args = parser.parse_args() infile = args.infile outfile = args.outfile # GEGL ###################################### gegl.init([]) #print(gegl.list_operations()) # Make nodes node1 = gegl.Node() node2 = gegl.Node() # png-load node3 = gegl.Node() # invert node4 = gegl.Node() # png-save # Set properties node2.set_property("operation", "gegl:png-load") node2.set_property("path", infile) node3.set_property("operation", "gegl:invert") node4.set_property("operation", "gegl:png-save") node4.set_property("path", outfile) # Make the graph node1.add_child(node2) node1.add_child(node3) node1.add_child(node4) node2.connect_to("output", node3, "input") node3.connect_to("output", node4, "input") # Process node4.process()
def run(self, procedure, args, data): runmode = args.index(0) if runmode == Gimp.RunMode.INTERACTIVE: gi.require_version('Gtk', '3.0') from gi.repository import Gtk gi.require_version('Gdk', '3.0') from gi.repository import Gdk Gimp.ui_init("palette-offset.py", False) dialog = Gimp.Dialog(use_header_bar=True, title=_("Exercise a goat (Python 3)"), role="goat-exercise-Python3") dialog.add_button("_Cancel", Gtk.ResponseType.CANCEL) dialog.add_button("_Source", Gtk.ResponseType.APPLY) dialog.add_button("_OK", Gtk.ResponseType.OK) geometry = Gdk.Geometry(); geometry.min_aspect = 0.5; geometry.max_aspect = 1.0; dialog.set_geometry_hints(None, geometry, Gdk.WindowHints.ASPECT); box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=2) dialog.get_content_area().add(box) box.show() # XXX We use printf-style string for sharing the localized # string. You may just use recommended Python format() or # any style you like in your plug-ins. head_text=("This plug-in is an exercise in '%s' to " "demo plug-in creation.\nCheck out the last " "version of the source code online by clicking " "the \"Source\" button." % ("Python 3")) label = Gtk.Label(label=head_text) box.pack_start(label, False, False, 1) label.show() contents = None # Get the file contents Python-style instead of using # GLib.file_get_contents() which returns bytes result, and # when converting to string, get newlines as text contents. # Rather than wasting time to figure this out, use Python # core API! with open(os.path.realpath(__file__), 'r') as f: contents = f.read() if contents is not None: scrolled = Gtk.ScrolledWindow() scrolled.set_vexpand (True) box.pack_start(scrolled, True, True, 1) scrolled.show() view = Gtk.TextView() view.set_wrap_mode(Gtk.WrapMode.WORD) view.set_editable(False) buffer = view.get_buffer() buffer.set_text(contents, -1) scrolled.add(view) view.show() while (True): response = dialog.run() if response == Gtk.ResponseType.OK: dialog.destroy() break elif response == Gtk.ResponseType.APPLY: Gio.app_info_launch_default_for_uri(url, None) continue else: dialog.destroy() return procedure.new_return_values(Gimp.PDBStatusType.CANCEL, GLib.Error()) # Parameters are not working fine yet because properties should # be Gimp.ImageID/Gimp.DrawableID but we can't make these with # pygobject. Until I figure out how to make it work, you could # uncomment the following lines instead of using the args value. #images = Gimp.image_list() #image_id = images[0] #drawable_id = Gimp.image_get_active_drawable(image_id) drawable_id = args.index(2) success, x, y, width, height = Gimp.drawable_mask_intersect(drawable_id); if success: Gegl.init(None); buffer = Gimp.drawable_get_buffer(drawable_id) shadow_buffer = Gimp.drawable_get_shadow_buffer(drawable_id) graph = Gegl.Node() input = graph.create_child("gegl:buffer-source") input.set_property("buffer", buffer) invert = graph.create_child("gegl:invert") output = graph.create_child("gegl:write-buffer") output.set_property("buffer", shadow_buffer) input.link(invert) invert.link(output) output.process() # This is extremely important in bindings, since we don't # unref buffers. If we don't explicitly flush a buffer, we # may left hanging forever. This step is usually done # during an unref(). shadow_buffer.flush() Gimp.drawable_merge_shadow(drawable_id, True) Gimp.drawable_update(drawable_id, x, y, width, height) Gimp.displays_flush() else: retval = procedure.new_return_values(Gimp.PDBStatusType.CALLING_ERROR, GLib.Error("No pixels to process in the selected area.")) return procedure.new_return_values(Gimp.PDBStatusType.SUCCESS, GLib.Error())
#!/usr/bin/env python from gi.repository import Gegl from gi.repository import Gtk from application import Application Gegl.init([]) Gtk.init([]) application = Application() application.run()
def test_100_init(self): Gegl.init(None);
Intended as bootstrap for building larger scripts. License: Creative Commons - Atribution required. Author: João S. O. Bueno """ import sys from gi.repository import Gegl as gegl try: origin, target = sys.argv[1:3] except IndexError: sys.stderr.write("Usage: %s origin_png target_png" % __file__) sys.exit(1) gegl.init([]) ops = gegl.list_operations() x = gegl.Node() y = gegl.Node() y.set_property("operation", "gegl:png-load") y.set_property("path", origin) x.add_child(y) z = gegl.Node() z.set_property("operation", "gegl:invert") x.add_child(z) w = gegl.Node()
self.assertFalse(crop_rect.equal(trans_node.get_bounding_box())) trans_rect = crop_rect.dup() trans_rect.x += 10 self.assertTrue(trans_rect.equal(trans_node.get_bounding_box())) class TestGeglXml(unittest.TestCase): def test_load_xml(self): graph = Gegl.Node.new_from_xml(invert_crop_xml, "") children = graph.get_children() self.assertEqual(len(children), 2) self.assertEqual(children[0].get_operation(), "gegl:crop") self.assertEqual(children[1].get_operation(), "gegl:invert-linear") def test_load_save_roundtrip(self): graph = Gegl.Node.new_from_xml(invert_crop_xml, "") output = graph.to_xml("") self.assertEqual(output, invert_crop_xml) if __name__ == '__main__': Gegl.init(None) unittest.main() Gegl.exit()
# Get/Set current base value for the given setting print "Base value is: %f" % brush.get_base_value(setting) brush.set_base_value(setting, 2.0) assert brush.get_base_value(setting) == 2.0 # Get dynamics for given setting inputs = [getattr(MyPaint.BrushInput, a) for a in dir(MyPaint.BrushInput) if a.startswith("INPUT_")] if not brush.is_constant(setting): for input in inputs: mapping_points = brush.get_mapping_n(setting, input) if mapping_points > 1: # If 0, no dynamics for this input points = [brush.get_mapping_point(setting, input, i) for i in range(mapping_points)] print "Has dynamics for input %s:\n%s" % (input, str(points)) # Create a surface to paint on Gegl.init(0, "") surface = MyPaintGegl.TiledSurface() s = surface.interface() print surface.get_buffer() for x, y in [(0.0, 0.0), (100.0, 100.0), (100.0, 200.0)]: dtime = 0.1 # XXX: Important to set correctly for speed calculations s.begin_atomic() brush.stroke_to(s, x, y, pressure=1.0, xtilt=0.0, ytilt=0.0, dtime=dtime) rect = s.end_atomic() print rect.x, rect.y, rect.width, rect.height Gegl.exit()
def test_init(self): Gegl.init(0, "")
# This is a very minimal example, that doesnt even construct the graph and # instantiate the nodes, but cheats and uses XML to get at an intial graph. # it expect a file /tmp/lena.png to exist def locate_by_type(self, opname): for i in self.get_children(): if i.get_operation() == opname: return i Gegl.Node.locate_by_type = locate_by_type if __name__ == '__main__': Gegl.init(0, "") # < that is rather ugly node = Gegl.Node.new_from_xml( """ <gegl> <gegl:save path='/tmp/output.png'/> <gegl:crop width='512' height='512'/> <gegl:over > <gegl:translate x='30' y='30'/> <gegl:dropshadow radius='1.5' x='3' y='3'/> <gegl:text size='80' color='white' ><params><param name='string'>GEGL I R</param></params></gegl:text> </gegl:over> <gegl:unsharp-mask std-dev='30'/>
#!/usr/bin/env python from gi.repository import Gegl import sys if __name__ == '__main__': Gegl.init(sys.argv) ptn = Gegl.Node() # Disable caching on all child nodes ptn.set_property("dont-cache", True) # Create our background buffer. A gegl:color node would # make more sense, we just use a buffer here as an example. background_buffer = Gegl.Buffer.new("RGBA float", 246, -10, 276, 276) white = Gegl.Color.new("#FFF") background_buffer.set_color(background_buffer.get_extent(), white) src = ptn.create_child("gegl:load") src.set_property("path", "data/surfer.png") crop = ptn.create_child("gegl:crop") crop.set_property("x", 256) crop.set_property("y", 0) crop.set_property("width", 256) crop.set_property("height", 256) buffer_src = ptn.create_child("gegl:buffer-source") buffer_src.set_property("buffer",background_buffer)
def run(self, procedure, run_mode, image, drawable, args, run_data): if run_mode == Gimp.RunMode.INTERACTIVE: gi.require_version('Gtk', '3.0') from gi.repository import Gtk gi.require_version('Gdk', '3.0') from gi.repository import Gdk GimpUi.ui_init("palette-offset.py") dialog = GimpUi.Dialog(use_header_bar=True, title=_("Exercise a goat (Python 3)"), role="goat-exercise-Python3") dialog.add_button("_Cancel", Gtk.ResponseType.CANCEL) dialog.add_button("_Source", Gtk.ResponseType.APPLY) dialog.add_button("_OK", Gtk.ResponseType.OK) geometry = Gdk.Geometry() geometry.min_aspect = 0.5 geometry.max_aspect = 1.0 dialog.set_geometry_hints(None, geometry, Gdk.WindowHints.ASPECT) box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=2) dialog.get_content_area().add(box) box.show() # XXX We use printf-style string for sharing the localized # string. You may just use recommended Python format() or # any style you like in your plug-ins. head_text = ("This plug-in is an exercise in '%s' to " "demo plug-in creation.\nCheck out the last " "version of the source code online by clicking " "the \"Source\" button." % ("Python 3")) label = Gtk.Label(label=head_text) box.pack_start(label, False, False, 1) label.show() contents = None # Get the file contents Python-style instead of using # GLib.file_get_contents() which returns bytes result, and # when converting to string, get newlines as text contents. # Rather than wasting time to figure this out, use Python # core API! with open(os.path.realpath(__file__), 'r') as f: contents = f.read() if contents is not None: scrolled = Gtk.ScrolledWindow() scrolled.set_vexpand(True) box.pack_start(scrolled, True, True, 1) scrolled.show() view = Gtk.TextView() view.set_wrap_mode(Gtk.WrapMode.WORD) view.set_editable(False) buffer = view.get_buffer() buffer.set_text(contents, -1) scrolled.add(view) view.show() while (True): response = dialog.run() if response == Gtk.ResponseType.OK: dialog.destroy() break elif response == Gtk.ResponseType.APPLY: url = "https://gitlab.gnome.org/GNOME/gimp/-/blob/master/plug-ins/goat-exercises/goat-exercise-py3.py" Gio.app_info_launch_default_for_uri(url, None) continue else: dialog.destroy() return procedure.new_return_values( Gimp.PDBStatusType.CANCEL, GLib.Error()) intersect, x, y, width, height = drawable.mask_intersect() if intersect: Gegl.init(None) buffer = drawable.get_buffer() shadow_buffer = drawable.get_shadow_buffer() graph = Gegl.Node() input = graph.create_child("gegl:buffer-source") input.set_property("buffer", buffer) invert = graph.create_child("gegl:invert") output = graph.create_child("gegl:write-buffer") output.set_property("buffer", shadow_buffer) input.link(invert) invert.link(output) output.process() # This is extremely important in bindings, since we don't # unref buffers. If we don't explicitly flush a buffer, we # may left hanging forever. This step is usually done # during an unref(). shadow_buffer.flush() drawable.merge_shadow(True) drawable.update(x, y, width, height) Gimp.displays_flush() return procedure.new_return_values(Gimp.PDBStatusType.SUCCESS, GLib.Error())
#!/usr/bin/env python from gi.repository import Gegl import sys if __name__ == '__main__': Gegl.init(sys.argv) ptn = Gegl.Node() # Disable caching on all child nodes ptn.set_property("dont-cache", True) # Create our background buffer. A gegl:color node would # make more sense, we just use a buffer here as an example. background_buffer = Gegl.Buffer.new("RGBA float", 246, -10, 276, 276) white = Gegl.Color.new("#FFF") background_buffer.set_color(background_buffer.get_extent(), white) src = ptn.create_child("gegl:load") src.set_property("path", "data/surfer.png") crop = ptn.create_child("gegl:crop") crop.set_property("x", 256) crop.set_property("y", 0) crop.set_property("width", 256) crop.set_property("height", 256) buffer_src = ptn.create_child("gegl:buffer-source") buffer_src.set_property("buffer", background_buffer)
# coding: utf-8 # Author: João S. O. Bueno import sys import gi gi.require_version("Gegl", "0.4") from gi.repository import Gegl as _gegl from .path import Path DEFAULT_OP_NAMESPACE = "gegl" _gegl.init(sys.argv[1:]) def list_operations(filter=""): ops = _gegl.list_operations() return [op for op in ops if filter in op] class OpNode(object): """ Wrapper for a GEGL node with an operation You can access OpNode._node attribute for raw access to the GEGL node as exposed by pygobject """ def __init__(self, operation, **kw): object.__setattr__(self, "_node", _gegl.Node()) # cyclic - TODO: replace with weakref self._node._wrapper = self self.operation = operation for key, value in kw.items(): setattr(self, key, value)
def test_100_init(self): Gegl.init(None)
def test_number_of_children(self): children = self.graph.get_children() self.assertEqual(len(children), 2) def test_child_operation(self): children = self.graph.get_children() self.assertEqual(children[0].get_operation(), "gegl:crop") self.assertEqual(children[1].get_operation(), "gegl:invert") class TestGeglNodeSaveXml(unittest.TestCase): def setUp(self): self.graph = Gegl.Node.new() # Easiest way to test to_xml when we can't yet build graphs programatically def test_load_save_roundtrip(self): graph = Gegl.Node.new_from_xml(invert_crop_xml, "") output = graph.to_xml("") self.assertEqual(output, invert_crop_xml) if __name__ == '__main__': Gegl.init(0, ""); #print dir(Gegl.Node) unittest.main()
# this binding would itself just import things using GI # This is a very minimal example, that doesnt even construct the graph and # instantiate the nodes, but cheats and uses XML to get at an intial graph. # it expect a file /tmp/lena.png to exist def locate_by_type(self, opname): for i in self.get_children(): if i.get_operation() == opname: return i Gegl.Node.locate_by_type = locate_by_type if __name__ == '__main__': Gegl.init(0,"") # < that is rather ugly node = Gegl.Node.new_from_xml(""" <gegl> <gegl:save path='/tmp/output.png'/> <gegl:crop width='512' height='512'/> <gegl:over > <gegl:translate x='30' y='30'/> <gegl:dropshadow radius='1.5' x='3' y='3'/> <gegl:text size='80' color='white' ><params><param name='string'>GEGL I R</param></params></gegl:text> </gegl:over> <gegl:unsharp-mask std-dev='30'/> <gegl:load path='/tmp/lena.png'/>
def test_init_exit(self): Gegl.init(0, "") Gegl.exit()
self.assertFalse(crop_rect.equal(trans_node.get_bounding_box())) trans_rect = crop_rect.dup() trans_rect.x += 10 self.assertTrue(trans_rect.equal(trans_node.get_bounding_box())) class TestGeglXml(unittest.TestCase): def test_load_xml(self): graph = Gegl.Node.new_from_xml(invert_crop_xml, "") children = graph.get_children() self.assertEqual(len(children), 2) self.assertEqual(children[0].get_operation(), "gegl:crop") self.assertEqual(children[1].get_operation(), "gegl:invert-linear") def test_load_save_roundtrip(self): graph = Gegl.Node.new_from_xml(invert_crop_xml, "") output = graph.to_xml("") self.assertEqual(output, invert_crop_xml) if __name__ == '__main__': Gegl.init(None); unittest.main() Gegl.exit()
def test_number_of_children(self): children = self.graph.get_children() self.assertEqual(len(children), 2) def test_child_operation(self): children = self.graph.get_children() self.assertEqual(children[0].get_operation(), "gegl:crop") self.assertEqual(children[1].get_operation(), "gegl:invert") class TestGeglNodeSaveXml(unittest.TestCase): def setUp(self): self.graph = Gegl.Node.new() # Easiest way to test to_xml when we can't yet build graphs programatically def test_load_save_roundtrip(self): graph = Gegl.Node.new_from_xml(invert_crop_xml, "") output = graph.to_xml("") self.assertEqual(output, invert_crop_xml) if __name__ == '__main__': Gegl.init(0, "") #print dir(Gegl.Node) unittest.main()
def init_ui(self): window = Gtk.Window() window.connect("destroy", self.destroy_cb) window.connect("size-allocate", self.size_allocate_cb) view_widget = GeglGtk.View() view_widget.set_node(self.add) view_widget.set_autoscale_policy(GeglGtk.ViewAutoscale.DISABLED) view_widget.set_size_request(800, 400) window.add(view_widget) window.show_all() def run(self): return Gtk.main() def destroy_cb(self, *ignored): Gtk.main_quit() def size_allocate_cb(self, widget, allocation): self.color.set_property("width", allocation.width) self.color.set_property("height", allocation.height) if __name__ == '__main__': Gegl.init([]) Gtk.init([]) app = TintApp() app.run()
def something(): #MyPaint.init() # Create a brush, load from disk brush = MyPaint.Brush() brush_def = open("brushes/classic/brush.myb").read() brush.from_string(brush_def) # List all settings # TODO: Is there a better way to list all enums with GI? settings = [ getattr(MyPaint.BrushSetting, attr) for attr in dir(MyPaint.BrushSetting) if attr.startswith("SETTING_") ] print "Available settings: %s\n" % str(settings) # Get info about a given setting setting = MyPaint.BrushSetting.SETTING_RADIUS_LOGARITHMIC info = MyPaint.brush_setting_info(setting) # TODO: rename "def_" to "default" print "Setting: %s\n\t Max: %f \n\t Default: %f \n\t Min: %f" % ( info.cname, info.max, info.def_, info.min) print "\t Name: %s\n\t Tooltip: '%s'\n" % ( info.get_name(), info.get_tooltip() ) # Use the getters so that i18n works # TODO: should be MyPaint.BrushSetting.from_cname # Same with MyPaint.Brush.input_from_cname assert (MyPaint.Brush.setting_from_cname(info.cname) == setting) # Get/Set current base value for the given setting print "Base value is: %f" % brush.get_base_value(setting) brush.set_base_value(setting, 2.0) assert brush.get_base_value(setting) == 2.0 # Get dynamics for given setting inputs = [ getattr(MyPaint.BrushInput, a) for a in dir(MyPaint.BrushInput) if a.startswith('INPUT_') ] if not brush.is_constant(setting): for input in inputs: mapping_points = brush.get_mapping_n(setting, input) if mapping_points > 1: # If 0, no dynamics for this input points = [ brush.get_mapping_point(setting, input, i) for i in range(mapping_points) ] print "Has dynamics for input %s:\n%s" % (input, str(points)) # Create a surface to paint on Gegl.init(0, "") surface = MyPaintGegl.TiledSurface() s = surface.interface() print surface.get_buffer() for x, y in [(0.0, 0.0), (100.0, 100.0), (100.0, 200.0)]: dtime = 0.1 # XXX: Important to set correctly for speed calculations s.begin_atomic() brush.stroke_to(s, x, y, pressure=1.0, xtilt=0.0, ytilt=0.0, dtime=dtime) rect = s.end_atomic() print rect.x, rect.y, rect.width, rect.height Gegl.exit()