[gimp/gimp-2-10] app, plug-ins: move brush (gbr) saving to the core



commit a04e24ce3e050a29c4b374097deb1f40adca0c24
Author: Michael Natterer <mitch gimp org>
Date:   Sat Feb 16 19:00:04 2019 +0100

    app, plug-ins: move brush (gbr) saving to the core
    
    just the export logic remains in the plug-in, just as for patterns.
    
    (cherry picked from commit 90164c4951222349b712d33ea043c870c9b0b44f)

 app/file-data/file-data-gbr.c | 129 ++++++++++++++++++++++++++---
 app/file-data/file-data.c     |  87 +++++++++++++++++++-
 plug-ins/common/file-gbr.c    | 184 ++++++------------------------------------
 3 files changed, 229 insertions(+), 171 deletions(-)
---
diff --git a/app/file-data/file-data-gbr.c b/app/file-data/file-data-gbr.c
index b4eb1bd2b8..2c434d388c 100644
--- a/app/file-data/file-data-gbr.c
+++ b/app/file-data/file-data-gbr.c
@@ -17,16 +17,19 @@
 
 #include "config.h"
 
+#include <cairo.h>
 #include <gdk-pixbuf/gdk-pixbuf.h>
 #include <gegl.h>
 
 #include "libgimpbase/gimpbase.h"
+#include "libgimpcolor/gimpcolor.h"
 
 #include "core/core-types.h"
 
 #include "core/gimp.h"
 #include "core/gimpbrush.h"
 #include "core/gimpbrush-load.h"
+#include "core/gimpbrush-private.h"
 #include "core/gimpdrawable.h"
 #include "core/gimpimage.h"
 #include "core/gimplayer-new.h"
@@ -42,9 +45,12 @@
 
 /*  local function prototypes  */
 
-static GimpImage * file_gbr_brush_to_image (Gimp      *gimp,
-                                            GimpBrush *brush);
-static GimpBrush * file_gbr_image_to_brush (GimpImage *image);
+static GimpImage * file_gbr_brush_to_image (Gimp         *gimp,
+                                            GimpBrush    *brush);
+static GimpBrush * file_gbr_image_to_brush (GimpImage    *image,
+                                            GimpDrawable *drawable,
+                                            const gchar  *name,
+                                            gdouble       spacing);
 
 
 /*  public functions  */
@@ -113,18 +119,25 @@ file_gbr_save_invoker (GimpProcedure         *procedure,
 {
   GimpValueArray *return_vals;
   GimpImage      *image;
+  GimpDrawable   *drawable;
   GimpBrush      *brush;
   const gchar    *uri;
+  const gchar    *name;
   GFile          *file;
+  gint            spacing;
   gboolean        success;
 
   gimp_set_busy (gimp);
 
-  image = gimp_value_get_image (gimp_value_array_index (args, 1), gimp);
-  uri   = g_value_get_string (gimp_value_array_index (args, 3));
-  file  = g_file_new_for_uri (uri);
+  image    = gimp_value_get_image (gimp_value_array_index (args, 1), gimp);
+  drawable = gimp_value_get_drawable (gimp_value_array_index (args, 2), gimp);
+  uri      = g_value_get_string (gimp_value_array_index (args, 3));
+  spacing  = g_value_get_int (gimp_value_array_index (args, 5));
+  name     = g_value_get_string (gimp_value_array_index (args, 6));
 
-  brush = file_gbr_image_to_brush (image);
+  file = g_file_new_for_uri (uri);
+
+  brush = file_gbr_image_to_brush (image, drawable, name, spacing);
 
   gimp_data_set_file (GIMP_DATA (brush), file, TRUE, TRUE);
 
@@ -234,7 +247,105 @@ file_gbr_brush_to_image (Gimp      *gimp,
 }
 
 static GimpBrush *
-file_gbr_image_to_brush (GimpImage *image)
+file_gbr_image_to_brush (GimpImage    *image,
+                         GimpDrawable *drawable,
+                         const gchar  *name,
+                         gdouble       spacing)
 {
-  return NULL;
+  GimpBrush   *brush;
+  GeglBuffer  *buffer;
+  GimpTempBuf *mask;
+  GimpTempBuf *pixmap = NULL;
+  gint         width;
+  gint         height;
+
+  buffer = gimp_drawable_get_buffer (drawable);
+  width  = gimp_item_get_width  (GIMP_ITEM (drawable));
+  height = gimp_item_get_height (GIMP_ITEM (drawable));
+
+  brush = g_object_new (GIMP_TYPE_BRUSH,
+                        "name",      name,
+                        "mime-type", "image/x-gimp-gbr",
+                        "spacing",   spacing,
+                        NULL);
+
+  mask = gimp_temp_buf_new (width, height, babl_format ("Y u8"));
+
+  if (gimp_drawable_is_gray (drawable))
+    {
+      guchar *m = gimp_temp_buf_get_data (mask);
+      gint    i;
+
+      if (gimp_drawable_has_alpha (drawable))
+        {
+          GeglBufferIterator *iter;
+          GimpRGB             white;
+
+          gimp_rgba_set_uchar (&white, 255, 255, 255, 255);
+
+          iter = gegl_buffer_iterator_new (buffer, NULL, 0,
+                                           babl_format ("Y'A u8"),
+                                           GEGL_ACCESS_READ, GEGL_ABYSS_NONE,
+                                           1);
+
+          while (gegl_buffer_iterator_next (iter))
+            {
+              guint8 *data = (guint8 *) iter->items[0].data;
+              gint    j;
+
+              for (j = 0; j < iter->length; j++)
+                {
+                  GimpRGB gray;
+                  gint    x, y;
+                  gint    dest;
+
+                  gimp_rgba_set_uchar (&gray,
+                                       data[0], data[0], data[0],
+                                       data[1]);
+
+                  gimp_rgb_composite (&gray, &white,
+                                      GIMP_RGB_COMPOSITE_BEHIND);
+
+                  x = iter->items[0].roi.x + j % iter->items[0].roi.width;
+                  y = iter->items[0].roi.y + j / iter->items[0].roi.width;
+
+                  dest = y * width + x;
+
+                  gimp_rgba_get_uchar (&gray, &m[dest], NULL, NULL, NULL);
+
+                  data += 2;
+                }
+            }
+        }
+      else
+        {
+          gegl_buffer_get (buffer, GEGL_RECTANGLE (0, 0, width, height), 1.0,
+                           babl_format ("Y' u8"), m,
+                           GEGL_AUTO_ROWSTRIDE, GEGL_ABYSS_NONE);
+        }
+
+      /*  invert  */
+      for (i = 0; i < width * height; i++)
+        m[i] = 255 - m[i];
+    }
+  else
+    {
+      pixmap = gimp_temp_buf_new (width, height, babl_format ("R'G'B' u8"));
+
+      gegl_buffer_get (buffer, GEGL_RECTANGLE (0, 0, width, height), 1.0,
+                       babl_format ("R'G'B' u8"),
+                       gimp_temp_buf_get_data (pixmap),
+                       GEGL_AUTO_ROWSTRIDE, GEGL_ABYSS_NONE);
+
+      gegl_buffer_get (buffer, GEGL_RECTANGLE (0, 0, width, height), 1.0,
+                       babl_format ("A u8"),
+                       gimp_temp_buf_get_data (mask),
+                       GEGL_AUTO_ROWSTRIDE, GEGL_ABYSS_NONE);
+    }
+
+
+  brush->priv->mask   = mask;
+  brush->priv->pixmap = pixmap;
+
+  return brush;
 }
diff --git a/app/file-data/file-data.c b/app/file-data/file-data.c
index fc4eecca1b..e425813cf8 100644
--- a/app/file-data/file-data.c
+++ b/app/file-data/file-data.c
@@ -111,6 +111,92 @@ file_data_init (Gimp *gimp)
   gimp_plug_in_manager_add_procedure (gimp->plug_in_manager, proc);
   g_object_unref (procedure);
 
+  /*  file-gbr-save-internal  */
+  file = g_file_new_for_path ("file-gbr-save-internal");
+  procedure = gimp_plug_in_procedure_new (GIMP_PLUGIN, file);
+  g_object_unref (file);
+
+  procedure->proc_type    = GIMP_INTERNAL;
+  procedure->marshal_func = file_gbr_save_invoker;
+
+  proc = GIMP_PLUG_IN_PROCEDURE (procedure);
+  proc->menu_label = g_strdup (N_("GIMP brush"));
+  gimp_plug_in_procedure_set_icon (proc, GIMP_ICON_TYPE_ICON_NAME,
+                                   (const guint8 *) "gimp-brush",
+                                   strlen ("gimp-brush") + 1);
+
+#if 0
+  /* do not register as file procedure */
+  gimp_plug_in_procedure_set_image_types (proc, "RGB*, GRAY*, INDEXED*");
+  gimp_plug_in_procedure_set_file_proc (proc, "gbr", "", NULL);
+  gimp_plug_in_procedure_set_mime_types (proc, "image/x-gimp-gbr");
+  gimp_plug_in_procedure_set_handles_uri (proc);
+#endif
+
+  gimp_object_set_static_name (GIMP_OBJECT (procedure),
+                               "file-gbr-save-internal");
+  gimp_procedure_set_static_strings (procedure,
+                                     "file-gbr-save-internal",
+                                     "Exports Gimp brush file (.GBR)",
+                                     "Exports Gimp brush file (.GBR)",
+                                     "Tim Newsome, Michael Natterer",
+                                     "Tim Newsome, Michael Natterer",
+                                     "1995-2019",
+                                     NULL);
+
+  gimp_procedure_add_argument (procedure,
+                               gimp_param_spec_int32 ("dummy-param",
+                                                      "Dummy Param",
+                                                      "Dummy parameter",
+                                                      G_MININT32, G_MAXINT32, 0,
+                                                      GIMP_PARAM_READWRITE));
+  gimp_procedure_add_argument (procedure,
+                               gimp_param_spec_image_id ("image",
+                                                         "Image",
+                                                         "Input image",
+                                                         gimp, FALSE,
+                                                         GIMP_PARAM_READWRITE));
+  gimp_procedure_add_argument (procedure,
+                               gimp_param_spec_drawable_id ("drawable",
+                                                            "Drawable",
+                                                            "Active drawable "
+                                                            "of input image",
+                                                            gimp, FALSE,
+                                                            GIMP_PARAM_READWRITE));
+  gimp_procedure_add_argument (procedure,
+                               gimp_param_spec_string ("uri",
+                                                       "URI",
+                                                       "The URI of the file "
+                                                       "to export",
+                                                       FALSE, FALSE, TRUE,
+                                                       NULL,
+                                                       GIMP_PARAM_READWRITE));
+  gimp_procedure_add_argument (procedure,
+                               gimp_param_spec_string ("raw-uri",
+                                                       "Raw URI",
+                                                       "The URI of the file "
+                                                       "to export",
+                                                       FALSE, FALSE, TRUE,
+                                                       NULL,
+                                                       GIMP_PARAM_READWRITE));
+  gimp_procedure_add_argument (procedure,
+                               gimp_param_spec_int32 ("spacing",
+                                                      "spacing",
+                                                      "Spacing of the brush",
+                                                      1, 1000, 10,
+                                                      GIMP_PARAM_READWRITE));
+  gimp_procedure_add_argument (procedure,
+                               gimp_param_spec_string ("name",
+                                                       "name",
+                                                       "The name of the "
+                                                       "brush",
+                                                       FALSE, FALSE, TRUE,
+                                                       "GIMP Brush",
+                                                       GIMP_PARAM_READWRITE));
+
+  gimp_plug_in_manager_add_procedure (gimp->plug_in_manager, proc);
+  g_object_unref (procedure);
+
   /*  file-pat-load  */
   file = g_file_new_for_path ("file-pat-load");
   procedure = gimp_plug_in_procedure_new (GIMP_PLUGIN, file);
@@ -162,7 +248,6 @@ file_data_init (Gimp *gimp)
                                                        TRUE, FALSE, TRUE,
                                                        NULL,
                                                        GIMP_PARAM_READWRITE));
-
   gimp_procedure_add_return_value (procedure,
                                    gimp_param_spec_image_id ("image",
                                                              "Image",
diff --git a/plug-ins/common/file-gbr.c b/plug-ins/common/file-gbr.c
index d345ce3d76..a8319508c0 100644
--- a/plug-ins/common/file-gbr.c
+++ b/plug-ins/common/file-gbr.c
@@ -37,9 +37,6 @@
 #include <libgimp/gimp.h>
 #include <libgimp/gimpui.h>
 
-#include "app/core/gimpbrush-header.h"
-#include "app/core/gimppattern-header.h"
-
 #include "libgimp/stdplugins-intl.h"
 
 
@@ -64,11 +61,6 @@ static void       run            (const gchar      *name,
                                   gint             *nreturn_vals,
                                   GimpParam       **return_vals);
 
-static gboolean   save_image     (GFile            *file,
-                                  gint32            image_ID,
-                                  gint32            drawable_ID,
-                                  GError          **error);
-
 static gboolean   save_dialog    (void);
 static void       entry_callback (GtkWidget        *widget,
                                   gpointer          data);
@@ -143,7 +135,6 @@ run (const gchar      *name,
   GError            *error  = NULL;
 
   INIT_I18N ();
-  gegl_init (NULL, NULL);
 
   run_mode = param[0].data.d_int32;
 
@@ -246,14 +237,36 @@ run (const gchar      *name,
 
       if (status == GIMP_PDB_SUCCESS)
         {
-          if (save_image (file, image_ID, drawable_ID, &error))
+          GimpParam *save_retvals;
+          gint       n_save_retvals;
+
+          save_retvals =
+            gimp_run_procedure ("file-gbr-save-internal",
+                                &n_save_retvals,
+                                GIMP_PDB_INT32,    GIMP_RUN_NONINTERACTIVE,
+                                GIMP_PDB_IMAGE,    image_ID,
+                                GIMP_PDB_DRAWABLE, drawable_ID,
+                                GIMP_PDB_STRING,   param[3].data.d_string,
+                                GIMP_PDB_STRING,   param[4].data.d_string,
+                                GIMP_PDB_INT32,    info.spacing,
+                                GIMP_PDB_STRING,   info.description,
+                                GIMP_PDB_END);
+
+          if (save_retvals[0].data.d_status == GIMP_PDB_SUCCESS)
             {
               gimp_set_data (SAVE_PROC, &info, sizeof (info));
             }
           else
             {
+              g_set_error (&error, 0, 0,
+                           "Running procedure 'file-gbr-save-internal' "
+                           "failed: %s",
+                           gimp_get_pdb_error ());
+
               status = GIMP_PDB_EXECUTION_ERROR;
             }
+
+          gimp_destroy_params (save_retvals, n_save_retvals);
         }
 
       if (export == GIMP_EXPORT_EXPORT)
@@ -290,157 +303,6 @@ run (const gchar      *name,
   values[0].data.d_status = status;
 }
 
-static gboolean
-save_image (GFile   *file,
-            gint32   image_ID,
-            gint32   drawable_ID,
-            GError **error)
-{
-  GOutputStream   *output;
-  GimpBrushHeader  bh;
-  guchar          *brush_buf;
-  GeglBuffer      *buffer;
-  const Babl      *format;
-  gint             line;
-  gint             x;
-  gint             bpp;
-  gint             file_bpp;
-  gint             width;
-  gint             height;
-  GimpRGB          gray, white;
-
-  gimp_rgba_set_uchar (&white, 255, 255, 255, 255);
-
-  switch (gimp_drawable_type (drawable_ID))
-    {
-    case GIMP_GRAY_IMAGE:
-      file_bpp = 1;
-      format = babl_format ("Y' u8");
-      break;
-
-    case GIMP_GRAYA_IMAGE:
-      file_bpp = 1;
-      format = babl_format ("Y'A u8");
-      break;
-
-    default:
-      file_bpp = 4;
-      format = babl_format ("R'G'B'A u8");
-      break;
-    }
-
-  bpp = babl_format_get_bytes_per_pixel (format);
-
-  gimp_progress_init_printf (_("Exporting '%s'"),
-                             g_file_get_parse_name (file));
-
-  output = G_OUTPUT_STREAM (g_file_replace (file,
-                                            NULL, FALSE, G_FILE_CREATE_NONE,
-                                            NULL, error));
-  if (! output)
-    return FALSE;
-
-  buffer = gimp_drawable_get_buffer (drawable_ID);
-
-  width  = gimp_drawable_width  (drawable_ID);
-  height = gimp_drawable_height (drawable_ID);
-
-  bh.header_size  = g_htonl (sizeof (GimpBrushHeader) +
-                             strlen (info.description) + 1);
-  bh.version      = g_htonl (2);
-  bh.width        = g_htonl (width);
-  bh.height       = g_htonl (height);
-  bh.bytes        = g_htonl (file_bpp);
-  bh.magic_number = g_htonl (GIMP_BRUSH_MAGIC);
-  bh.spacing      = g_htonl (info.spacing);
-
-  if (! g_output_stream_write_all (output, &bh, sizeof (GimpBrushHeader),
-                                   NULL, NULL, error))
-    {
-      GCancellable *cancellable = g_cancellable_new ();
-
-      g_cancellable_cancel (cancellable);
-      g_output_stream_close (output, cancellable, NULL);
-      g_object_unref (cancellable);
-
-      g_object_unref (output);
-      return FALSE;
-    }
-
-  if (! g_output_stream_write_all (output,
-                                   info.description,
-                                   strlen (info.description) + 1,
-                                   NULL, NULL, error))
-    {
-      GCancellable *cancellable = g_cancellable_new ();
-
-      g_cancellable_cancel (cancellable);
-      g_output_stream_close (output, cancellable, NULL);
-      g_object_unref (cancellable);
-
-      g_object_unref (output);
-      return FALSE;
-    }
-
-  brush_buf = g_new (guchar, width * bpp);
-
-  for (line = 0; line < height; line++)
-    {
-      gegl_buffer_get (buffer, GEGL_RECTANGLE (0, line, width, 1), 1.0,
-                       format, brush_buf,
-                       GEGL_AUTO_ROWSTRIDE, GEGL_ABYSS_NONE);
-
-      switch (bpp)
-        {
-        case 1:
-          /*  invert  */
-          for (x = 0; x < width; x++)
-            brush_buf[x] = 255 - brush_buf[x];
-          break;
-
-        case 2:
-          for (x = 0; x < width; x++)
-            {
-              /*  apply alpha channel  */
-              gimp_rgba_set_uchar (&gray,
-                                   brush_buf[2 * x],
-                                   brush_buf[2 * x],
-                                   brush_buf[2 * x],
-                                   brush_buf[2 * x + 1]);
-              gimp_rgb_composite (&gray, &white, GIMP_RGB_COMPOSITE_BEHIND);
-              gimp_rgba_get_uchar (&gray, &brush_buf[x], NULL, NULL, NULL);
-              /* invert */
-              brush_buf[x] = 255 - brush_buf[x];
-            }
-          break;
-        }
-
-      if (! g_output_stream_write_all (output, brush_buf, width * file_bpp,
-                                       NULL, NULL, error))
-        {
-          GCancellable *cancellable = g_cancellable_new ();
-
-          g_cancellable_cancel (cancellable);
-          g_output_stream_close (output, cancellable, NULL);
-          g_object_unref (cancellable);
-
-          g_free (brush_buf);
-          g_object_unref (output);
-          return FALSE;
-        }
-
-      gimp_progress_update ((gdouble) line / (gdouble) height);
-    }
-
-  g_free (brush_buf);
-  g_object_unref (buffer);
-  g_object_unref (output);
-
-  gimp_progress_update (1.0);
-
-  return TRUE;
-}
-
 static gboolean
 save_dialog (void)
 {


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]