[gimp] app, plug-ins: move brush pipe saving from the file-gih plug-in to the core



commit cc7e07fecbee37a7698af90f206fd6f414fefa4b
Author: Michael Natterer <mitch gimp org>
Date:   Sun Mar 3 19:42:22 2019 +0100

    app, plug-ins: move brush pipe saving from the file-gih plug-in to the core
    
    As with .gbr and .pat, only the actual saving code, not the export
    logic and GUI.

 app/file-data/file-data-gih.c | 185 +++++++++++-----------
 app/file-data/file-data.c     | 101 +++++++++++-
 plug-ins/common/file-gih.c    | 351 +++++++++---------------------------------
 3 files changed, 254 insertions(+), 383 deletions(-)
---
diff --git a/app/file-data/file-data-gih.c b/app/file-data/file-data-gih.c
index b07b57d743..039491add6 100644
--- a/app/file-data/file-data-gih.c
+++ b/app/file-data/file-data-gih.c
@@ -50,9 +50,9 @@
 static GimpImage     * file_gih_pipe_to_image (Gimp          *gimp,
                                                GimpBrushPipe *pipe);
 static GimpBrushPipe * file_gih_image_to_pipe (GimpImage     *image,
-                                               GimpDrawable  *drawable,
                                                const gchar   *name,
-                                               gdouble        spacing);
+                                               gdouble        spacing,
+                                               const gchar   *paramstring);
 
 
 /*  public functions  */
@@ -125,25 +125,25 @@ file_gih_save_invoker (GimpProcedure         *procedure,
 {
   GimpValueArray *return_vals;
   GimpImage      *image;
-  GimpDrawable   *drawable;
   GimpBrushPipe  *pipe;
   const gchar    *uri;
   const gchar    *name;
+  const gchar    *params;
   GFile          *file;
   gint            spacing;
   gboolean        success;
 
   gimp_set_busy (gimp);
 
-  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));
+  image   = gimp_value_get_image (gimp_value_array_index (args, 1), 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));
+  params  = g_value_get_string (gimp_value_array_index (args, 7));
 
   file = g_file_new_for_uri (uri);
 
-  pipe = file_gih_image_to_pipe (image, drawable, name, spacing);
+  pipe = file_gih_image_to_pipe (image, name, spacing, params);
 
   gimp_data_set_file (GIMP_DATA (pipe), file, TRUE, TRUE);
 
@@ -235,109 +235,102 @@ file_gih_pipe_to_image (Gimp          *gimp,
 }
 
 static GimpBrushPipe *
-file_gih_image_to_pipe (GimpImage    *image,
-                        GimpDrawable *drawable,
-                        const gchar  *name,
-                        gdouble       spacing)
+file_gih_image_to_pipe (GimpImage   *image,
+                        const gchar *name,
+                        gdouble      spacing,
+                        const gchar *paramstring)
 {
-#if 0
-  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-gih",
-                        "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);
+  GimpBrushPipe     *pipe;
+  GimpPixPipeParams  params;
+  GList             *layers;
+  GList             *list;
+  GList             *brushes = NULL;
+  gint               image_width;
+  gint               image_height;
+  gint               i;
 
-          while (gegl_buffer_iterator_next (iter))
-            {
-              guint8 *data = (guint8 *) iter->items[0].data;
-              gint    j;
+  pipe = g_object_new (GIMP_TYPE_BRUSH_PIPE,
+                       "name",      name,
+                       "mime-type", "image/x-gimp-gih",
+                       "spacing",   spacing,
+                       NULL);
 
-              for (j = 0; j < iter->length; j++)
-                {
-                  GimpRGB gray;
-                  gint    x, y;
-                  gint    dest;
+  gimp_pixpipe_params_init (&params);
+  gimp_pixpipe_params_parse (paramstring, &params);
 
-                  gimp_rgba_set_uchar (&gray,
-                                       data[0], data[0], data[0],
-                                       data[1]);
+  image_width  = gimp_image_get_width  (image);
+  image_height = gimp_image_get_height (image);
 
-                  gimp_rgb_composite (&gray, &white,
-                                      GIMP_RGB_COMPOSITE_BEHIND);
+  layers = gimp_image_get_layer_iter (image);
 
-                  x = iter->items[0].roi.x + j % iter->items[0].roi.width;
-                  y = iter->items[0].roi.y + j / iter->items[0].roi.width;
+  for (list = layers; list; list = g_list_next (list))
+    {
+      GimpLayer *layer = list->data;
+      gint       width;
+      gint       height;
+      gint       offset_x;
+      gint       offset_y;
+      gint       row;
 
-                  dest = y * width + x;
+      width  = gimp_item_get_width  (GIMP_ITEM (layer));
+      height = gimp_item_get_height (GIMP_ITEM (layer));
 
-                  gimp_rgba_get_uchar (&gray, &m[dest], NULL, NULL, NULL);
+      gimp_item_get_offset (GIMP_ITEM (layer), &offset_x, &offset_y);
 
-                  data += 2;
-                }
-            }
-        }
-      else
+      for (row = 0; row < params.rows; row++)
         {
-          gegl_buffer_get (buffer, GEGL_RECTANGLE (0, 0, width, height), 1.0,
-                           babl_format ("Y' u8"), m,
-                           GEGL_AUTO_ROWSTRIDE, GEGL_ABYSS_NONE);
+          gint y, ynext;
+          gint thisy, thish;
+          gint col;
+
+          y     = (row * image_height) / params.rows;
+          ynext = ((row + 1) * image_height / params.rows);
+
+          /* Assume layer is offset to positive direction in x and y.
+           * That's reasonable, as otherwise all of the layer
+           * won't be visible.
+           * thisy and thisx are in the drawable's coordinate space.
+           */
+          thisy = MAX (0, y - offset_y);
+          thish = (ynext - offset_y) - thisy;
+          thish = MIN (thish, height - thisy);
+
+          for (col = 0; col < params.cols; col++)
+            {
+              GimpBrush *brush;
+              gint       x, xnext;
+              gint       thisx, thisw;
+
+              x     = (col * image_width / params.cols);
+              xnext = ((col + 1) * image_width / params.cols);
+              thisx = MAX (0, x - offset_x);
+              thisw = (xnext - offset_x) - thisx;
+              thisw = MIN (thisw, width - thisx);
+
+              brush = file_gbr_drawable_to_brush (GIMP_DRAWABLE (layer),
+                                                  GEGL_RECTANGLE (thisx, thisy,
+                                                                  thisw, thish),
+                                                  gimp_object_get_name (layer),
+                                                  spacing);
+
+              brushes = g_list_prepend (brushes, brush);
+            }
         }
-
-      /*  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);
+  brushes = g_list_reverse (brushes);
 
-      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);
-    }
+  pipe->n_brushes = g_list_length (brushes);
+  pipe->brushes   = g_new0 (GimpBrush *, pipe->n_brushes);
+
+  for (list = brushes, i = 0; list; list = g_list_next (list), i++)
+    pipe->brushes[i] = list->data;
 
+  g_list_free (brushes);
 
-  brush->priv->mask   = mask;
-  brush->priv->pixmap = pixmap;
+  gimp_pixpipe_params_free (&params);
 
-  return brush;
-#endif
+  gimp_brush_pipe_set_params (pipe, paramstring);
 
-  return NULL;
+  return pipe;
 }
diff --git a/app/file-data/file-data.c b/app/file-data/file-data.c
index 9468cc0855..411d2cadba 100644
--- a/app/file-data/file-data.c
+++ b/app/file-data/file-data.c
@@ -222,11 +222,9 @@ file_data_init (Gimp *gimp)
                                      "Loads GIMP animated brushes",
                                      "This procedure loads a GIMP brush "
                                      "pipe as an image.",
-                                     "Jens Lautenbacher, Sven Neumann, "
-                                     "Michael Natterer",
-                                     "Jens Lautenbacher, Sven Neumann, "
-                                     "Michael Natterer",
-                                     "1995-2019",
+                                     "Tor Lillqvist, Michael Natterer",
+                                     "Tor Lillqvist, Michael Natterer",
+                                     "1999-2019",
                                      NULL);
 
   gimp_procedure_add_argument (procedure,
@@ -262,6 +260,99 @@ file_data_init (Gimp *gimp)
   gimp_plug_in_manager_add_procedure (gimp->plug_in_manager, proc);
   g_object_unref (procedure);
 
+  /*  file-gih-save-internal  */
+  file = g_file_new_for_path ("file-gih-save-internal");
+  procedure = gimp_plug_in_procedure_new (GIMP_PLUGIN, file);
+  g_object_unref (file);
+
+  procedure->proc_type    = GIMP_INTERNAL;
+  procedure->marshal_func = file_gih_save_invoker;
+
+  proc = GIMP_PLUG_IN_PROCEDURE (procedure);
+  proc->menu_label = g_strdup (N_("GIMP brush (animated)"));
+  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, "gih", "", NULL);
+  gimp_plug_in_procedure_set_mime_types (proc, "image/x-gimp-gih");
+  gimp_plug_in_procedure_set_handles_uri (proc);
+#endif
+
+  gimp_object_set_static_name (GIMP_OBJECT (procedure),
+                               "file-gih-save-internal");
+  gimp_procedure_set_static_strings (procedure,
+                                     "file-gih-save-internal",
+                                     "Exports Gimp animated brush file (.gih)",
+                                     "Exports Gimp animated brush file (.gih)",
+                                     "Tor Lillqvist, Michael Natterer",
+                                     "Tor Lillqvist, Michael Natterer",
+                                     "1999-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_procedure_add_argument (procedure,
+                               gimp_param_spec_string ("params",
+                                                       "params",
+                                                       "The pipe's parameters",
+                                                       FALSE, FALSE, TRUE,
+                                                       NULL,
+                                                       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);
diff --git a/plug-ins/common/file-gih.c b/plug-ins/common/file-gih.c
index 26c31bf8ea..29ca08c8ed 100644
--- a/plug-ins/common/file-gih.c
+++ b/plug-ins/common/file-gih.c
@@ -41,15 +41,10 @@
 
 #include "config.h"
 
-#include <stdlib.h>
-
 #include <libgimp/gimp.h>
 #include <libgimp/gimpui.h>
 #include <libgimpbase/gimpparasiteio.h>
 
-#include "app/core/gimpbrush-header.h"
-#include "app/core/gimppattern-header.h"
-
 #include "libgimp/stdplugins-intl.h"
 
 
@@ -88,26 +83,18 @@ typedef struct
 
 /*  local function prototypes  */
 
-static void      query               (void);
-static void      run                 (const gchar      *name,
-                                      gint              nparams,
-                                      const GimpParam  *param,
-                                      gint             *nreturn_vals,
-                                      GimpParam       **return_vals);
-
-static gboolean  gih_save_dialog     (gint32            image_ID);
-static gboolean  gih_save_one_brush  (GOutputStream    *output,
-                                      gint32            drawable_ID,
-                                      GeglRectangle    *rect,
-                                      const gchar      *name,
-                                      GError          **error);
-static gboolean  gih_save_image      (GFile            *file,
-                                      gint32            image_ID,
-                                      gint32            orig_image_ID,
-                                      gint32            drawable_ID,
-                                      GError          **error);
+static void      query           (void);
+static void      run             (const gchar      *name,
+                                  gint              nparams,
+                                  const GimpParam  *param,
+                                  gint             *nreturn_vals,
+                                  GimpParam       **return_vals);
+
+static gboolean  gih_save_dialog (gint32            image_ID);
 
 
+/*  private variables  */
+
 const GimpPlugInInfo PLUG_IN_INFO =
 {
   NULL,  /* init_proc  */
@@ -116,9 +103,6 @@ const GimpPlugInInfo PLUG_IN_INFO =
   run,   /* run_proc   */
 };
 
-
-/*  private variables  */
-
 static BrushInfo info =
 {
   "GIMP Brush Pipe",
@@ -198,12 +182,11 @@ run (const gchar      *name,
   GimpPDBStatusType  status = GIMP_PDB_SUCCESS;
   gint32             image_ID;
   gint32             drawable_ID;
-  gint               i;
   GimpExportReturn   export = GIMP_EXPORT_CANCEL;
   GError            *error  = NULL;
+  gint               i;
 
   INIT_I18N();
-  gegl_init (NULL, NULL);
 
   run_mode = param[0].data.d_int32;
 
@@ -216,8 +199,7 @@ run (const gchar      *name,
   if (strcmp (name, SAVE_PROC) == 0)
     {
       GFile        *file;
-      GimpParasite *name_parasite;
-      GimpParasite *pipe_parasite;
+      GimpParasite *parasite;
       gint32        orig_image_ID;
 
       image_ID    = param[1].data.d_int32;
@@ -247,17 +229,17 @@ run (const gchar      *name,
           /*  Possibly retrieve data  */
           gimp_get_data (SAVE_PROC, &info);
 
-          name_parasite = gimp_image_get_parasite (orig_image_ID,
-                                                   "gimp-brush-pipe-name");
-          if (name_parasite)
+          parasite = gimp_image_get_parasite (orig_image_ID,
+                                              "gimp-brush-pipe-name");
+          if (parasite)
             {
               strncpy (info.description,
-                       gimp_parasite_data (name_parasite),
+                       gimp_parasite_data (parasite),
                        MIN (sizeof (info.description),
-                            gimp_parasite_data_size (name_parasite)));
+                            gimp_parasite_data_size (parasite)));
               info.description[sizeof (info.description) - 1] = '\0';
 
-              gimp_parasite_free (name_parasite);
+              gimp_parasite_free (parasite);
             }
           else
             {
@@ -292,13 +274,13 @@ run (const gchar      *name,
           gihparams.cellwidth  = gimp_image_width (image_ID)  / gihparams.cols;
           gihparams.cellheight = gimp_image_height (image_ID) / gihparams.rows;
 
-          pipe_parasite = gimp_image_get_parasite (orig_image_ID,
-                                                   "gimp-brush-pipe-parameters");
-          if (pipe_parasite)
+          parasite = gimp_image_get_parasite (orig_image_ID,
+                                              "gimp-brush-pipe-parameters");
+          if (parasite)
             {
-              gimp_pixpipe_params_parse (gimp_parasite_data (pipe_parasite),
+              gimp_pixpipe_params_parse (gimp_parasite_data (parasite),
                                          &gihparams);
-              gimp_parasite_free (pipe_parasite);
+              gimp_parasite_free (parasite);
             }
 
           /* Force default rank to same as number of cells if there is
@@ -347,28 +329,67 @@ run (const gchar      *name,
           break;
 
         case GIMP_RUN_WITH_LAST_VALS:
-          pipe_parasite = gimp_image_get_parasite (orig_image_ID,
-                                                   "gimp-brush-pipe-parameters");
-          if (pipe_parasite)
+          parasite = gimp_image_get_parasite (orig_image_ID,
+                                              "gimp-brush-pipe-parameters");
+          if (parasite)
             {
-              gimp_pixpipe_params_parse (gimp_parasite_data (pipe_parasite),
+              gimp_pixpipe_params_parse (gimp_parasite_data (parasite),
                                          &gihparams);
-              gimp_parasite_free (pipe_parasite);
+              gimp_parasite_free (parasite);
             }
           break;
         }
 
       if (status == GIMP_PDB_SUCCESS)
         {
-          if (gih_save_image (file, image_ID, orig_image_ID, drawable_ID,
-                              &error))
+          GimpParam *save_retvals;
+          gint       n_save_retvals;
+          gchar     *paramstring;
+
+          paramstring = gimp_pixpipe_params_build (&gihparams);
+
+          save_retvals =
+            gimp_run_procedure ("file-gih-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_STRING,   paramstring,
+                                GIMP_PDB_END);
+
+          if (save_retvals[0].data.d_status == GIMP_PDB_SUCCESS)
             {
               gimp_set_data (SAVE_PROC, &info, sizeof (info));
+
+              parasite = gimp_parasite_new ("gimp-brush-pipe-name",
+                                            GIMP_PARASITE_PERSISTENT,
+                                            strlen (info.description) + 1,
+                                            info.description);
+              gimp_image_attach_parasite (orig_image_ID, parasite);
+              gimp_parasite_free (parasite);
+
+              parasite = gimp_parasite_new ("gimp-brush-pipe-parameters",
+                                            GIMP_PARASITE_PERSISTENT,
+                                            strlen (paramstring) + 1,
+                                            paramstring);
+              gimp_image_attach_parasite (orig_image_ID, parasite);
+              gimp_parasite_free (parasite);
             }
           else
             {
+              g_set_error (&error, 0, 0,
+                           "Running procedure 'file-gih-save-internal' "
+                           "failed: %s",
+                           gimp_get_pdb_error ());
+
               status = GIMP_PDB_EXECUTION_ERROR;
             }
+
+          g_free (paramstring);
         }
 
       gimp_pixpipe_params_free (&gihparams);
@@ -771,237 +792,3 @@ gih_save_dialog (gint32 image_ID)
 
   return run;
 }
-
-static gboolean
-gih_save_one_brush (GOutputStream  *output,
-                    gint32          drawable_ID,
-                    GeglRectangle  *rect,
-                    const gchar    *name,
-                    GError        **error)
-{
-  GeglBuffer      *buffer;
-  const Babl      *format;
-  GimpBrushHeader  bh;
-  guchar          *data;
-  GimpImageType    drawable_type;
-  gint             bpp;
-  gint             y;
-
-  buffer = gimp_drawable_get_buffer (drawable_ID);
-
-  drawable_type = gimp_drawable_type (drawable_ID);
-
-  if (! name)
-    name = _("Unnamed");
-
-  switch (drawable_type)
-    {
-    case GIMP_GRAY_IMAGE:
-    case GIMP_GRAYA_IMAGE: /* alpha channel is ignored */
-      format = babl_format ("Y' u8");
-      break;
-
-    case GIMP_RGB_IMAGE: /* alpha channel is added */
-    case GIMP_RGBA_IMAGE:
-      format = babl_format ("R'G'B'A u8");
-      break;
-
-    default:
-      g_return_val_if_reached (FALSE);
-      break;
-    }
-
-  bpp = babl_format_get_bytes_per_pixel (format);
-
-  bh.header_size  = g_htonl (sizeof (bh) + strlen (name) + 1);
-  bh.version      = g_htonl (2);
-  bh.width        = g_htonl (rect->width);
-  bh.height       = g_htonl (rect->height);
-  bh.bytes        = g_htonl (bpp);
-  bh.magic_number = g_htonl (GIMP_BRUSH_MAGIC);
-  bh.spacing      = g_htonl (info.spacing);
-
-  if (! g_output_stream_write_all (output, &bh, sizeof (bh),
-                                   NULL, NULL, error))
-    {
-      return FALSE;
-    }
-
-  if (! g_output_stream_write_all (output, name, strlen (name) + 1,
-                                   NULL, NULL, error))
-    {
-      return FALSE;
-    }
-
-  data = g_malloc (rect->width * bpp);
-
-  for (y = 0; y < rect->height; y++)
-    {
-      gint x;
-
-      gegl_buffer_get (buffer,
-                       GEGL_RECTANGLE (rect->x, rect->y + y, rect->width, 1),
-                       1.0, format, data,
-                       GEGL_AUTO_ROWSTRIDE, GEGL_ABYSS_NONE);
-
-      switch (bpp)
-        {
-        case 1: /* GRAY */
-          for (x = 0; x < rect->width; x++)
-            data[x] = 255 - data[x];
-        }
-
-      if (! g_output_stream_write_all (output, data, rect->width * bpp,
-                                       NULL, NULL, error))
-        {
-          g_free (data);
-          return FALSE;
-        }
-    }
-
-  g_free (data);
-  g_object_unref (buffer);
-
-  return TRUE;
-}
-
-static gboolean
-gih_save_image (GFile    *file,
-                gint32    image_ID,
-                gint32    orig_image_ID,
-                gint32    drawable_ID,
-                GError  **error)
-{
-  GOutputStream *output;
-  GimpParasite  *name_parasite;
-  GimpParasite  *pipe_parasite;
-  gchar         *header;
-  gchar         *parstring;
-  gint32        *layer_ID;
-  gint           nlayers, layer;
-  gint           row, col;
-  gint           imagew, imageh;
-  gint           offsetx, offsety;
-  gint           k;
-
-  if (gihparams.ncells < 1)
-    return FALSE;
-
-  imagew = gimp_image_width (image_ID);
-  imageh = gimp_image_height (image_ID);
-
-  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;
-
-  parstring = gimp_pixpipe_params_build (&gihparams);
-
-  header = g_strdup_printf ("%s\n%d %s\n",
-                            info.description, gihparams.ncells, parstring);
-
-  if (! g_output_stream_write_all (output, header, strlen (header),
-                                   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 (parstring);
-      g_free (header);
-      g_object_unref (output);
-      return FALSE;
-    }
-
-  g_free (header);
-
-  name_parasite = gimp_parasite_new ("gimp-brush-pipe-name",
-                                     GIMP_PARASITE_PERSISTENT,
-                                     strlen (info.description) + 1,
-                                     info.description);
-  gimp_image_attach_parasite (orig_image_ID, name_parasite);
-  gimp_parasite_free (name_parasite);
-
-  pipe_parasite = gimp_parasite_new ("gimp-brush-pipe-parameters",
-                                     GIMP_PARASITE_PERSISTENT,
-                                     strlen (parstring) + 1, parstring);
-  gimp_image_attach_parasite (orig_image_ID, pipe_parasite);
-  gimp_parasite_free (pipe_parasite);
-
-  g_free (parstring);
-
-  layer_ID = gimp_image_get_layers (image_ID, &nlayers);
-
-  for (layer = 0, k = 0; layer < nlayers; layer++)
-    {
-      gchar *name   = gimp_item_get_name (layer_ID[layer]);
-      gint   width  = gimp_drawable_width (layer_ID[layer]);
-      gint   height = gimp_drawable_height (layer_ID[layer]);
-
-      gimp_drawable_offsets (layer_ID[layer], &offsetx, &offsety);
-
-      for (row = 0; row < gihparams.rows; row++)
-        {
-          gint y, ynext;
-          gint thisy, thish;
-
-          y = (row * imageh) / gihparams.rows;
-          ynext = ((row + 1) * imageh / gihparams.rows);
-
-          /* Assume layer is offset to positive direction in x and y.
-           * That's reasonable, as otherwise all of the layer
-           * won't be visible.
-           * thisy and thisx are in the drawable's coordinate space.
-           */
-          thisy = MAX (0, y - offsety);
-          thish = (ynext - offsety) - thisy;
-          thish = MIN (thish, height - thisy);
-
-          for (col = 0; col < gihparams.cols; col++)
-            {
-              gint x, xnext;
-              gint thisx, thisw;
-
-              x = (col * imagew / gihparams.cols);
-              xnext = ((col + 1) * imagew / gihparams.cols);
-              thisx = MAX (0, x - offsetx);
-              thisw = (xnext - offsetx) - thisx;
-              thisw = MIN (thisw, width - thisx);
-
-              if (! gih_save_one_brush (output, layer_ID[layer],
-                                        GEGL_RECTANGLE (thisx, thisy,
-                                                        thisw, thish),
-                                        name, 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;
-                }
-
-              k++;
-              gimp_progress_update ((gdouble) k / gihparams.ncells);
-            }
-        }
-
-      g_free (name);
-    }
-
-
-  g_free (layer_ID);
-  g_object_unref (output);
-
-  gimp_progress_update (1.0);
-
-  return TRUE;
-}


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