Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
GEGL kaleidoscope
#1
I looked at the gegl command.py
and I have no clue how to make it so that I can call kaleidoscope... from python fu for GIMP 2.10
any help available?
Reply
#2
(Yesterday, 01:24 AM)trandoductin Wrote: I looked at the gegl command.py
and I have no clue how to make it so that I can call kaleidoscope... from python fu for GIMP 2.10
any help available?

I've used the kaleidoscope fine with gegl command in 2.10.

The command is called mirrors.
You can see the parameters it takes and their types here:
https://gegl.org/operations/gegl-mirrors.html

You make a string something like this (this example hasn't got all the parameters but their types are all straightforward double / int / boolean):
    mirrors n-segs=6 input-scale=100.00 o-x=0.04 clip=true

However when I did it some time ago I thought  offset and centre were mixed up. It may not be the case anymore but worth keeping a lookout for. The above link says:

Offset X name: c-x
Offset Y name: c-y
Center X name: o-x
Center Y name: o-y

You call gegl command with parameters image, layer, gegl_string.
Reply
#3
Thanks teapot.
Do you have an example of how you call gegl command?

I tried using the below found code but it's breaking for me.
def use_gegl_graph(image, drawable, gegl_graph_string):
class GeglBuffer(Structure):
pass
drawable_id = drawable.ID

gegl = load_library ('libgegl-0.4')
sucess = gegl.gegl_init (None, None)
gimp.gimp_drawable_get_shadow_buffer.restype = POINTER (GeglBuffer)
gimp.gimp_drawable_get_buffer.restype = POINTER (GeglBuffer)

x = c_int (); y = c_int (); w = c_int (); h = c_int ()
non_empty,x,y,w,h = pdb.gimp_drawable_mask_intersect (drawable)
args = [b"string", c_char_p (gegl_graph_string), c_void_p ()]

if non_empty:
source = gimp.gimp_drawable_get_buffer (drawable_id)
target = gimp.gimp_drawable_get_shadow_buffer (drawable_id)
sucess = gegl.gegl_render_op (source, target, "gegl:gegl", *args)
gegl.gegl_buffer_flush (target)
gimp.gimp_drawable_merge_shadow (drawable_id, PushUndo = True)
gimp.gimp_drawable_update (drawable_id, x, y, w, h)
gimp.gimp_displays_flush ()
Reply
#4
(Yesterday, 07:36 AM)trandoductin Wrote: Thanks teapot.
Do you have an example of how you call gegl command?

Tricky, there are several versions floating around. I believe the original was by paynekj, Kevin Payne.  I use the one below but I cannot remember where I got it.

In my plugin I import it:

import gegl_command

and call it:

gegl_command.gegl_command(image, layer, gegl_string)

You can call it via the pdb but that's much slower:

pdb.python_gegl(image, new_layer, gegl_string)

EDIT: Do not use this version, see post #8.

Code:
#!/usr/bin/env python
# -*- coding: utf-8 -*-

print 'gegl_command.py: __name__', __name__

import sys
import ctypes
import gimpfu

def load_library(lib):
   pl = sys.platform

   if pl == 'linux' or pl == 'linux2':
       return ctypes.CDLL(lib + '.so.0')

   if pl == 'win32':
       return ctypes.CDLL(ctypes.util.find_library(lib + '-0'))

   raise BaseException('TODO:' + pl)

gimp = load_library('libgimp-2.0')
gegl = load_library('libgegl-0.4')

gegl.gegl_init(None, None)
print 'gegl_command.py: gegl done'

def gegl_command(image, drawable, gegl_graph_string):
   overlap, x, y, w, h = gimpfu.pdb.gimp_drawable_mask_intersect(drawable)
   if not overlap:
       return

   class GeglBuffer(ctypes.Structure):
       pass
   GeglBufferPtr = ctypes.POINTER(GeglBuffer)

   gimp.gimp_drawable_get_shadow_buffer.restype = GeglBufferPtr
   gimp.gimp_drawable_get_buffer.restype = GeglBufferPtr
   gegl.gegl_render_op.restype = None

   drawable_id = drawable.ID
   source = gimp.gimp_drawable_get_buffer(drawable_id)
   target = gimp.gimp_drawable_get_shadow_buffer(drawable_id)
   gegl.gegl_render_op(source, target, 'gegl:gegl',
           'string', ctypes.c_char_p(gegl_graph_string),
           ctypes.c_void_p()
       )
   print 'source=', source, 'target=', target

   gegl.gegl_buffer_flush.restype = None
   gimp.gimp_drawable_merge_shadow.restype = ctypes.c_bool
   gimp.gimp_drawable_update.restype = ctypes.c_bool

   gegl.gegl_buffer_flush(target)
   okay = gimp.gimp_drawable_merge_shadow(drawable_id, PushUndo=True)
   print 'merge okay=', okay
   okay = gimp.gimp_drawable_update(drawable_id, x, y, w, h)
   print 'update okay=', okay

   # gimp_displays_flush takes approximately 1/6th second.
   # gimp.gimp_displays_flush()

def init():
   print 'gegl_command.py: registering python_gegl'
   gimpfu.register(
       'python_gegl',          # name
       'Gegl Command',         # blurb
       'Gegl Command . . .',   # help
       'paynekj',              # author
       'paynekj',              # copyright
       '2021',                 # date
       'Gegl Command',         # menu name
       'RGB,RGBA',             # image types
       [
           (gimpfu.PF_IMAGE,    'image',             'Input image',       None),
           (gimpfu.PF_DRAWABLE, 'drawable',          'Input drawable',    None),
           (gimpfu.PF_TEXT,     'gegl_graph_string', 'Graph',             ''),
       ],
       [],
       gegl_command,
       menu='<Image>/Python-Fu' # menu path
   )

if __name__ == '__main__':
   init()
   gimpfu.main()
Reply
#5
There must be something wrong with windows.
I can't get it to work

on windows I had to do
import ctypes
from ctypes.util import find_library # This is the correct import
if pl == 'win32':
return ctypes.CDLL(find_library(lib + '-0'))

This is now successful.
Reply
#6
Well, as a non-coder, using Kevin's plugin gegl_command.py and a little shell script to call it, for_gegl.py That works in Windows 10 (VM) / Gimp 2.10.38


Attached Files
.zip   for_gegl.zip (Size: 1.33 KB / Downloads: 11)
Reply
#7
Thanks to Kevin and teapot I was able to fulfill a request for client now just waiting to hear back from them.
Maybe Windows 10 VM understood the ctypes.util, on mine it was complaining that there is not util attribute in ctypes and I asked chatGPT and chatGPT gave me that from ctypes.util import find_library code which works
Not sure why it would blow up on me i mean it's the same thing (to me).
Ah I noticed you attached a file rich and looked at it and for windows it's also doing the from ctypes.util import find_library so that would work (strange how that is to me).
Reply
#8
(Yesterday, 01:28 PM)trandoductin Wrote: Thanks to Kevin and teapot I was able to fulfill a request for client now just waiting to hear back from them.
Maybe Windows 10 VM understood the ctypes.util, on mine it was complaining that there is not util attribute in ctypes and I asked chatGPT and chatGPT gave me that from ctypes.util import find_library code which works
Not sure why it would blow up on me i mean it's the same thing (to me).
Ah I noticed you attached a file rich and looked at it and for windows it's also doing the from ctypes.util import find_library so that would work (strange how that is to me).

There is a problem with the version I put in post #4, I only have Linux so didn't realise.  I think changing just the import statement should fix it. If any Windows users could try the one below and say if it works that would be helpful. Thanks.

Code:
#!/usr/bin/env python
# -*- coding: utf-8 -*-

# print 'gegl_command.py: __name__', __name__

import sys
import ctypes.util
import gimpfu

def load_library(lib):
    pl = sys.platform

    if pl == 'linux' or pl == 'linux2':
        return ctypes.CDLL(lib + '.so.0')

    if pl == 'win32':
        return ctypes.CDLL(ctypes.util.find_library(lib + '-0'))

    raise BaseException('TODO:' + pl)

gimp = load_library('libgimp-2.0')
gegl = load_library('libgegl-0.4')

gegl.gegl_init(None, None)
# print 'gegl_command.py: gegl done'

def gegl_command(image, drawable, gegl_graph_string):
    overlap, x, y, w, h = gimpfu.pdb.gimp_drawable_mask_intersect(drawable)
    if not overlap:
        return

    class GeglBuffer(ctypes.Structure):
        pass
    GeglBufferPtr = ctypes.POINTER(GeglBuffer)

    gimp.gimp_drawable_get_shadow_buffer.restype = GeglBufferPtr
    gimp.gimp_drawable_get_buffer.restype = GeglBufferPtr
    gegl.gegl_render_op.restype = None

    drawable_id = drawable.ID
    source = gimp.gimp_drawable_get_buffer(drawable_id)
    target = gimp.gimp_drawable_get_shadow_buffer(drawable_id)
    gegl.gegl_render_op(source, target, 'gegl:gegl',
            'string', ctypes.c_char_p(gegl_graph_string),
            ctypes.c_void_p()
        )
    # print 'source=', source, 'target=', target

    gegl.gegl_buffer_flush.restype = None
    gimp.gimp_drawable_merge_shadow.restype = ctypes.c_bool
    gimp.gimp_drawable_update.restype = ctypes.c_bool

    gegl.gegl_buffer_flush(target)
    okay = gimp.gimp_drawable_merge_shadow(drawable_id, PushUndo=True)
    # print 'merge okay=', okay
    okay = gimp.gimp_drawable_update(drawable_id, x, y, w, h)
    # print 'update okay=', okay

    # gimp_displays_flush takes approximately 1/6th second.
    # gimp.gimp_displays_flush()

def init():
    # print 'gegl_command.py: registering python_gegl'
    gimpfu.register(
        'python_gegl',          # name
        'Gegl Command',         # blurb
        'Gegl Command . . .',   # help
        'paynekj',              # author
        'paynekj',              # copyright
        '2021',                 # date
        'Gegl Command',         # menu name
        'RGB,RGBA',             # image types
        [
            (gimpfu.PF_IMAGE,    'image',             'Input image',       None),
            (gimpfu.PF_DRAWABLE, 'drawable',          'Input drawable',    None),
            (gimpfu.PF_TEXT,     'gegl_graph_string', 'Graph',             ''),
        ],
        [],
        gegl_command,
        menu='<Image>/Python-Fu' # menu path
    )

if __name__ == '__main__':
    init()
    gimpfu.main()
Reply
#9
rich's attachment already tested in Windows 10 VM that works so
yeah it is the import statement
Tested post #8 - also successful on Windows 11
Reply


Forum Jump: