美文网首页
如何编写GIMP插件合集

如何编写GIMP插件合集

作者: 寽虎非虫003 | 来源:发表于2022-02-09 18:25 被阅读0次

    C版本

    其实不用严格限制为CC++也行。
    注意,要测试之类的最好先安装GIMPgimptool-2.0,两者都要。

    sudo apt install gimp libgimp2.0-dev
    

    然后,由于三篇原文已经由人翻译了,我这儿就只给出官方链接和翻译文章的的链接。
    对了,这些教程只对2.0~2.10版本有用,对于库上最新的2.99或3.x版本没用。

    官方链接:

    How to write a GIMP plug-in
    How to write a GIMP plug-in, part II
    How to write a GIMP plug-in, part III

    API参考

    GIMP Reference Manuals

    翻译文章链接:

    [翻译]如何编写GIMP插件(一)

    [翻译]如何编写GIMP插件(二)

    如何编写GIMP插件(三)

    python版本和scheme版本

    官方ppt:

    GIMP Scripts and Plug-ins 2011

    GIMP Scripts and Plug-ins 2010

    python

    也是分成主函数,运行函数和注册数据三大步。其中自然也报错位于菜单的哪一项。

    #!/usr/bin/env python
    
    # Hello World in GIMP Python
    
    from gimpfu import *
    
    def hello_world(initstr, font, size, color) :
        # First do a quick sanity check on the font
        if font == 'Comic Sans MS' :
            initstr = "Comic Sans? Are you sure?"
    
        # Make a new image. Size 10x10 for now -- we'll resize later.
        img = gimp.Image(1, 1, RGB)
    
        # Save the current foreground color:
        pdb.gimp_context_push()
    
        # Set the text color
        gimp.set_foreground(color)
    
        # Create a new text layer (-1 for the layer means create a new layer)
        layer = pdb.gimp_text_fontname(img, None, 0, 0, initstr, 10,
                                       True, size, PIXELS, font)
    
        # Resize the image to the size of the layer
        img.resize(layer.width, layer.height, 0, 0)
    
        # Background layer.
        # Can't add this first because we don't know the size of the text layer.
        background = gimp.Layer(img, "Background", layer.width, layer.height,
                                RGB_IMAGE, 100, NORMAL_MODE)
        background.fill(BACKGROUND_FILL)
        img.add_layer(background, 1)
    
        # Create a new image window
        gimp.Display(img)
        # Show the new image window
        gimp.displays_flush()
    
        # Restore the old foreground color:
        pdb.gimp_context_pop()
    
    register(
        "python_fu_hello_world",
        "Hello world image",
        "Create a new image with your text string",
        "Akkana Peck",
        "Akkana Peck",
        "2010",
        "Hello world (Py)...",
        "",      # Create a new image, don't work on an existing one
        [
            (PF_STRING, "string", "Text string", 'Hello, world!'),
            (PF_FONT, "font", "Font face", "Sans"),
            (PF_SPINNER, "size", "Font size", 50, (1, 3000, 1)),
            (PF_COLOR, "color", "Text color", (1.0, 0.0, 0.0))
        ],
        [],
        hello_world, menu="<Image>/File/Create")
    
    main()
    

    scheme版本

    同样也是3大步,但是菜单注册单独出来了, main消失了,看起来像是直接执行定义的函数。

    ; "Hello, World" Test
    ;
    ; Creates an image with the text "Hello, World!"
    
    ; Copyright 2010, Akkana Peck
    ; 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.
    ;
    ; You should have received a copy of the GNU General Public License
    ; along with this program; if not, write to the Free Software
    ; Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
    
    (define (script-fu-helloworld text font size colour)
      (gimp-context-push)
      (gimp-context-set-foreground colour)
      (let* (
            ; initial image size is 10x10 -- we'll resize it later
            (img (car (gimp-image-new 10 10 RGB)))
            (dummy (gimp-image-undo-disable img))
            (text-layer (car (gimp-text-fontname img -1 0 0 text 10
                                                 TRUE size PIXELS font)))
            (width (car (gimp-drawable-width text-layer)))
            (height (car (gimp-drawable-height text-layer)))
            )
        (gimp-image-resize img width height 0 0)
    
        (gimp-image-undo-enable img)
        (gimp-display-new img)
        (gimp-context-pop)
    ))
    
    (script-fu-register "script-fu-helloworld"
        "_Hello World (SF)..."
        "Creates an image with a user specified text string."
        "Akkana Peck <akkana@shallowsky.com>"
        "Akkana Peck"
        "May, 2010"
        ""
        SF-STRING     "Text string"         "Hello, World!"
        SF-FONT       "Font"                "Sans"
        SF-ADJUSTMENT "Font size (pixels)"  '(100 2 1000 1 10 0 1)
        SF-COLOR      "Color"               '(255 0 0)
    )
    
    (script-fu-menu-register "script-fu-helloworld"
                             "<Image>/File/Create")
    

    源码阅读,关于MAIN宏

    #  define MAIN()                                        \
       int                                                  \
       main (int argc, char *argv[])                        \
       {                                                    \
         return gimp_main (&PLUG_IN_INFO, argc, argv);      \
       }
    
    gint           gimp_main                (const GimpPlugInInfo *info,
                                             gint                  argc,
                                             gchar                *argv[]);
    

    具体的函数定义:

    gint
    gimp_main (const GimpPlugInInfo *info,
               gint                  argc,
               gchar                *argv[])
    {
      enum
      {
        ARG_PROGNAME,
        ARG_GIMP,
        ARG_READ_FD,
        ARG_WRITE_FD,
        ARG_MODE,
        ARG_STACK_TRACE_MODE,
    
        N_ARGS
      };
    
      gchar       *basename;
      const gchar *env_string;
      gchar       *debug_string;
    
    #ifdef G_OS_WIN32
      gint i, j, k;
    
      /* Reduce risks */
      {
        typedef BOOL (WINAPI *t_SetDllDirectoryA) (LPCSTR lpPathName);
        t_SetDllDirectoryA p_SetDllDirectoryA;
    
        p_SetDllDirectoryA = (t_SetDllDirectoryA) GetProcAddress (GetModuleHandle ("kernel32.dll"),
                                                                  "SetDllDirectoryA");
        if (p_SetDllDirectoryA)
          (*p_SetDllDirectoryA) ("");
      }
    
      /* On Windows, set DLL search path to $INSTALLDIR/bin so that GEGL
         file operations can find their respective file library DLLs (such
         as jasper, etc.) without needing to set external PATH. */
      {
        const gchar *install_dir;
        gchar       *bin_dir;
        LPWSTR       w_bin_dir;
        int          n;
    
        w_bin_dir = NULL;
        install_dir = gimp_installation_directory ();
        bin_dir = g_build_filename (install_dir, "bin", NULL);
    
        n = MultiByteToWideChar (CP_UTF8, MB_ERR_INVALID_CHARS,
                                 bin_dir, -1, NULL, 0);
        if (n == 0)
          goto out;
    
        w_bin_dir = g_malloc_n (n + 1, sizeof (wchar_t));
        n = MultiByteToWideChar (CP_UTF8, MB_ERR_INVALID_CHARS,
                                 bin_dir, -1,
                                 w_bin_dir, (n + 1) * sizeof (wchar_t));
        if (n == 0)
          goto out;
    
        SetDllDirectoryW (w_bin_dir);
    
      out:
        if (w_bin_dir)
          g_free (w_bin_dir);
        g_free (bin_dir);
      }
    
    #ifdef HAVE_EXCHNDL
      /* Use Dr. Mingw (dumps backtrace on crash) if it is available. */
      {
        time_t  t;
        gchar  *filename;
        gchar  *dir;
    
        /* This has to be the non-roaming directory (i.e., the local
           directory) as backtraces correspond to the binaries on this
           system. */
        dir = g_build_filename (g_get_user_data_dir (),
                                GIMPDIR, GIMP_USER_VERSION, "CrashLog",
                                NULL);
        /* Ensure the path exists. */
        g_mkdir_with_parents (dir, 0700);
    
        time (&t);
        filename = g_strdup_printf ("%s-crash-%" G_GUINT64_FORMAT ".txt",
                                    g_get_prgname(), t);
        plug_in_backtrace_path = g_build_filename (dir, filename, NULL);
        g_free (filename);
        g_free (dir);
    
        /* Similar to core crash handling in app/signals.c, the order here
         * is very important!
         */
        if (! _prevExceptionFilter)
          _prevExceptionFilter = SetUnhandledExceptionFilter (gimp_plugin_sigfatal_handler);
    
        ExcHndlInit ();
        ExcHndlSetLogFileNameA (plug_in_backtrace_path);
      }
    #endif
    
    #ifndef _WIN64
      {
        typedef BOOL (WINAPI *t_SetProcessDEPPolicy) (DWORD dwFlags);
        t_SetProcessDEPPolicy p_SetProcessDEPPolicy;
    
        p_SetProcessDEPPolicy = GetProcAddress (GetModuleHandle ("kernel32.dll"),
                                                "SetProcessDEPPolicy");
        if (p_SetProcessDEPPolicy)
          (*p_SetProcessDEPPolicy) (PROCESS_DEP_ENABLE|PROCESS_DEP_DISABLE_ATL_THUNK_EMULATION);
      }
    #endif
    
      /* Group all our windows together on the taskbar */
      {
        typedef HRESULT (WINAPI *t_SetCurrentProcessExplicitAppUserModelID) (PCWSTR lpPathName);
        t_SetCurrentProcessExplicitAppUserModelID p_SetCurrentProcessExplicitAppUserModelID;
    
        p_SetCurrentProcessExplicitAppUserModelID = (t_SetCurrentProcessExplicitAppUserModelID) GetProcAddress (GetModuleHandle ("shell32.dll"),
                                                                                                                "SetCurrentProcessExplicitAppUserModelID");
        if (p_SetCurrentProcessExplicitAppUserModelID)
          (*p_SetCurrentProcessExplicitAppUserModelID) (L"gimp.GimpApplication");
      }
    
      /* Check for exe file name with spaces in the path having been split up
       * by buggy NT C runtime, or something. I don't know why this happens
       * on NT (including w2k), but not on w95/98.
       */
    
      for (i = 1; i < argc; i++)
        {
          k = strlen (argv[i]);
    
          if (k > 10)
            {
              if (g_ascii_strcasecmp (argv[i] + k - 4, ".exe") == 0)
                {
                  /* Found the end of the executable name, most probably.
                   * Splice the parts of the name back together.
                   */
                  GString *s;
    
                  s = g_string_new (argv[ARG_PROGNAME]);
    
                  for (j = 1; j <= i; j++)
                    {
                      s = g_string_append_c (s, ' ');
                      s = g_string_append (s, argv[j]);
                    }
    
                  argv[ARG_PROGNAME] = s->str;
    
                  /* Move rest of argv down */
                  for (j = 1; j < argc - i; j++)
                    argv[j] = argv[j + i];
    
                  argv[argc - i] = NULL;
                  argc -= i;
    
                  break;
              }
           }
        }
    #endif
    
      g_assert (info != NULL);
    
      PLUG_IN_INFO = *info;
    
      if ((argc != N_ARGS) || (strcmp (argv[ARG_GIMP], "-gimp") != 0))
        {
          g_printerr ("%s is a GIMP plug-in and must be run by GIMP to be used\n",
                      argv[ARG_PROGNAME]);
          return 1;
        }
    
      gimp_env_init (TRUE);
    
      progname = argv[ARG_PROGNAME];
    
      basename = g_path_get_basename (progname);
    
      g_set_prgname (basename);
    
      env_string = g_getenv ("GIMP_PLUGIN_DEBUG");
    
      if (env_string)
        {
          const gchar *debug_messages;
    
          debug_string = strchr (env_string, ',');
    
          if (debug_string)
            {
              gint len = debug_string - env_string;
    
              if ((strlen (basename) == len) &&
                  (strncmp (basename, env_string, len) == 0))
                {
                  gimp_debug_flags =
                    g_parse_debug_string (debug_string + 1,
                                          gimp_debug_keys,
                                          G_N_ELEMENTS (gimp_debug_keys));
                }
            }
          else if (strcmp (env_string, basename) == 0)
            {
              gimp_debug_flags = GIMP_DEBUG_DEFAULT;
            }
    
          /*  make debug output visible by setting G_MESSAGES_DEBUG  */
          debug_messages = g_getenv ("G_MESSAGES_DEBUG");
    
          if (debug_messages)
            {
              gchar *tmp = g_strconcat (debug_messages, ",LibGimp", NULL);
              g_setenv ("G_MESSAGES_DEBUG", tmp, TRUE);
              g_free (tmp);
            }
          else
            {
              g_setenv ("G_MESSAGES_DEBUG", "LibGimp", TRUE);
            }
        }
    
      g_free (basename);
    
      stack_trace_mode = (GimpStackTraceMode) CLAMP (atoi (argv[ARG_STACK_TRACE_MODE]),
                                                     GIMP_STACK_TRACE_NEVER,
                                                     GIMP_STACK_TRACE_ALWAYS);
    
    #ifndef G_OS_WIN32
      /* No use catching these on Win32, the user won't get any meaningful
       * stack trace from glib anyhow. It's better to let Windows inform
       * about the program error, and offer debugging if the plug-in
       * has been built with MSVC, and the user has MSVC installed.
       */
      gimp_signal_private (SIGHUP,  gimp_plugin_sigfatal_handler, 0);
      gimp_signal_private (SIGINT,  gimp_plugin_sigfatal_handler, 0);
      gimp_signal_private (SIGQUIT, gimp_plugin_sigfatal_handler, 0);
      gimp_signal_private (SIGTERM, gimp_plugin_sigfatal_handler, 0);
    
      gimp_signal_private (SIGABRT, gimp_plugin_sigfatal_handler, 0);
      gimp_signal_private (SIGBUS,  gimp_plugin_sigfatal_handler, 0);
      gimp_signal_private (SIGSEGV, gimp_plugin_sigfatal_handler, 0);
      gimp_signal_private (SIGFPE,  gimp_plugin_sigfatal_handler, 0);
    
      /* Ignore SIGPIPE from crashing Gimp */
      gimp_signal_private (SIGPIPE, SIG_IGN, 0);
    
      /* Restart syscalls interrupted by SIGCHLD */
      gimp_signal_private (SIGCHLD, SIG_DFL, SA_RESTART);
    #endif
    
    #ifdef G_OS_WIN32
      _readchannel  = g_io_channel_win32_new_fd (atoi (argv[ARG_READ_FD]));
      _writechannel = g_io_channel_win32_new_fd (atoi (argv[ARG_WRITE_FD]));
    #else
      _readchannel  = g_io_channel_unix_new (atoi (argv[ARG_READ_FD]));
      _writechannel = g_io_channel_unix_new (atoi (argv[ARG_WRITE_FD]));
    #endif
    
      g_io_channel_set_encoding (_readchannel, NULL, NULL);
      g_io_channel_set_encoding (_writechannel, NULL, NULL);
    
      g_io_channel_set_buffered (_readchannel, FALSE);
      g_io_channel_set_buffered (_writechannel, FALSE);
    
      g_io_channel_set_close_on_unref (_readchannel, TRUE);
      g_io_channel_set_close_on_unref (_writechannel, TRUE);
    
      gp_init ();
    
      gimp_wire_set_writer (gimp_write);
      gimp_wire_set_flusher (gimp_flush);
    
      gimp_enums_init ();
    
      /*  initialize units  */
      {
        GimpUnitVtable vtable;
    
        vtable.unit_get_number_of_units = _gimp_unit_cache_get_number_of_units;
        vtable.unit_get_number_of_built_in_units =
          _gimp_unit_cache_get_number_of_built_in_units;
        vtable.unit_new                 = _gimp_unit_cache_new;
        vtable.unit_get_deletion_flag   = _gimp_unit_cache_get_deletion_flag;
        vtable.unit_set_deletion_flag   = _gimp_unit_cache_set_deletion_flag;
        vtable.unit_get_factor          = _gimp_unit_cache_get_factor;
        vtable.unit_get_digits          = _gimp_unit_cache_get_digits;
        vtable.unit_get_identifier      = _gimp_unit_cache_get_identifier;
        vtable.unit_get_symbol          = _gimp_unit_cache_get_symbol;
        vtable.unit_get_abbreviation    = _gimp_unit_cache_get_abbreviation;
        vtable.unit_get_singular        = _gimp_unit_cache_get_singular;
        vtable.unit_get_plural          = _gimp_unit_cache_get_plural;
    
        gimp_base_init (&vtable);
      }
    
      /* initialize i18n support */
    
      setlocale (LC_ALL, "");
    
      bindtextdomain (GETTEXT_PACKAGE"-libgimp", gimp_locale_directory ());
    #ifdef HAVE_BIND_TEXTDOMAIN_CODESET
      bind_textdomain_codeset (GETTEXT_PACKAGE"-libgimp", "UTF-8");
    #endif
    
    
      /* set handler both for the "LibGimp" and "" domains */
      {
        const gchar * const log_domains[] =
        {
          "LibGimp",
          "LibGimpBase",
          "LibGimpColor",
          "LibGimpConfig",
          "LibGimpMath",
          "LibGimpModule",
          "LibGimpThumb",
          "LibGimpWidgets"
        };
        gint i;
    
        for (i = 0; i < G_N_ELEMENTS (log_domains); i++)
          g_log_set_handler (log_domains[i],
                             G_LOG_LEVEL_MESSAGE,
                             gimp_message_func,
                             NULL);
    
        g_log_set_handler (NULL,
                           G_LOG_LEVEL_MESSAGE,
                           gimp_message_func,
                           NULL);
      }
    
      if (gimp_debug_flags & GIMP_DEBUG_FATAL_WARNINGS)
        {
          GLogLevelFlags fatal_mask;
    
          fatal_mask = g_log_set_always_fatal (G_LOG_FATAL_MASK);
          fatal_mask |= G_LOG_LEVEL_WARNING | G_LOG_LEVEL_CRITICAL;
          g_log_set_always_fatal (fatal_mask);
    
          g_log_set_handler (NULL,
                             G_LOG_LEVEL_WARNING | G_LOG_LEVEL_CRITICAL |
                             G_LOG_LEVEL_ERROR | G_LOG_FLAG_FATAL,
                             gimp_fatal_func, NULL);
        }
      else
        {
          g_log_set_handler (NULL,
                             G_LOG_LEVEL_ERROR | G_LOG_FLAG_FATAL,
                             gimp_fatal_func, NULL);
        }
    
      if (strcmp (argv[ARG_MODE], "-query") == 0)
        {
          if (PLUG_IN_INFO.init_proc)
            gp_has_init_write (_writechannel, NULL);
    
          if (gimp_debug_flags & GIMP_DEBUG_QUERY)
            gimp_debug_stop ();
    
          if (PLUG_IN_INFO.query_proc)
            (* PLUG_IN_INFO.query_proc) ();
    
          gimp_close ();
    
          return EXIT_SUCCESS;
        }
    
      if (strcmp (argv[ARG_MODE], "-init") == 0)
        {
          if (gimp_debug_flags & GIMP_DEBUG_INIT)
            gimp_debug_stop ();
    
          if (PLUG_IN_INFO.init_proc)
            (* PLUG_IN_INFO.init_proc) ();
    
          gimp_close ();
    
          return EXIT_SUCCESS;
        }
    
      if (gimp_debug_flags & GIMP_DEBUG_RUN)
        gimp_debug_stop ();
      else if (gimp_debug_flags & GIMP_DEBUG_PID)
        g_log (G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, "Here I am!");
    
      temp_proc_ht = g_hash_table_new (g_str_hash, g_str_equal);
    
      g_io_add_watch (_readchannel,
                      G_IO_ERR | G_IO_HUP,
                      gimp_plugin_io_error_handler,
                      NULL);
    
      gimp_loop ();
    
      return EXIT_SUCCESS;
    }
    

    相关文章

      网友评论

          本文标题:如何编写GIMP插件合集

          本文链接:https://www.haomeiwen.com/subject/bfxgkrtx.html