From 088418e004033088315ce2a1ca8a9cba6aaf3e9b Mon Sep 17 00:00:00 2001 From: Michael Natterer Date: Tue, 19 Feb 2019 23:27:28 +0100 Subject: [PATCH] app, plug-ins: move file-gih-load from the file-gih plug-in to the core (cherry picked from commit 52adaa1963431e0638f4cf44693b39726437ef0c) --- app/file-data/Makefile.am | 2 + app/file-data/file-data-gih.c | 343 ++++++++++++++++++++++++++++ app/file-data/file-data-gih.h | 37 +++ app/file-data/file-data.c | 65 ++++++ plug-ins/common/file-gih.c | 418 +--------------------------------- po/POTFILES.in | 1 + 6 files changed, 449 insertions(+), 417 deletions(-) create mode 100644 app/file-data/file-data-gih.c create mode 100644 app/file-data/file-data-gih.h diff --git a/app/file-data/Makefile.am b/app/file-data/Makefile.am index 9c79dae1df..ba0fd577f2 100644 --- a/app/file-data/Makefile.am +++ b/app/file-data/Makefile.am @@ -18,5 +18,7 @@ libappfile_data_a_SOURCES = \ file-data.h \ file-data-gbr.c \ file-data-gbr.h \ + file-data-gih.c \ + file-data-gih.h \ file-data-pat.c \ file-data-pat.h diff --git a/app/file-data/file-data-gih.c b/app/file-data/file-data-gih.c new file mode 100644 index 0000000000..8bf66a630b --- /dev/null +++ b/app/file-data/file-data-gih.c @@ -0,0 +1,343 @@ +/* GIMP - The GNU Image Manipulation Program + * Copyright (C) 1995 Spencer Kimball and Peter Mattis + * + * 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 3 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, see . + */ + +#include "config.h" + +#include +#include +#include + +#include "libgimpbase/gimpbase.h" +#include "libgimpbase/gimpparasiteio.h" +#include "libgimpcolor/gimpcolor.h" + +#include "core/core-types.h" + +#include "core/gimp.h" +#include "core/gimpbrushpipe.h" +#include "core/gimpbrushpipe-load.h" +#include "core/gimpbrush-private.h" +#include "core/gimpdrawable.h" +#include "core/gimpimage.h" +#include "core/gimplayer-new.h" +#include "core/gimpparamspecs.h" +#include "core/gimptempbuf.h" + +#include "pdb/gimpprocedure.h" + +#include "file-data-gbr.h" +#include "file-data-gih.h" + +#include "gimp-intl.h" + + +/* local function prototypes */ + +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); + + +/* public functions */ + +GimpValueArray * +file_gih_load_invoker (GimpProcedure *procedure, + Gimp *gimp, + GimpContext *context, + GimpProgress *progress, + const GimpValueArray *args, + GError **error) +{ + GimpValueArray *return_vals; + GimpImage *image = NULL; + const gchar *uri; + GFile *file; + GInputStream *input; + GError *my_error = NULL; + + gimp_set_busy (gimp); + + uri = g_value_get_string (gimp_value_array_index (args, 1)); + file = g_file_new_for_uri (uri); + + input = G_INPUT_STREAM (g_file_read (file, NULL, &my_error)); + + if (input) + { + GList *list = gimp_brush_pipe_load (context, file, input, error); + + if (list) + { + GimpBrushPipe *pipe = list->data; + + g_list_free (list); + + image = file_gih_pipe_to_image (gimp, pipe); + g_object_unref (pipe); + } + + g_object_unref (input); + } + else + { + g_propagate_prefixed_error (error, my_error, + _("Could not open '%s' for reading: "), + gimp_file_get_utf8_name (file)); + } + + g_object_unref (file); + + return_vals = gimp_procedure_get_return_values (procedure, image != NULL, + error ? *error : NULL); + + if (image) + gimp_value_set_image (gimp_value_array_index (return_vals, 1), image); + + gimp_unset_busy (gimp); + + return return_vals; +} + +GimpValueArray * +file_gih_save_invoker (GimpProcedure *procedure, + Gimp *gimp, + GimpContext *context, + GimpProgress *progress, + const GimpValueArray *args, + GError **error) +{ + GimpValueArray *return_vals; + GimpImage *image; + GimpDrawable *drawable; + GimpBrushPipe *pipe; + 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); + 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)); + + file = g_file_new_for_uri (uri); + + pipe = file_gih_image_to_pipe (image, drawable, name, spacing); + + gimp_data_set_file (GIMP_DATA (pipe), file, TRUE, TRUE); + + success = gimp_data_save (GIMP_DATA (pipe), error); + + g_object_unref (pipe); + g_object_unref (file); + + return_vals = gimp_procedure_get_return_values (procedure, success, + error ? *error : NULL); + + gimp_unset_busy (gimp); + + return return_vals; +} + + +/* private functions */ + +static GimpImage * +file_gih_pipe_to_image (Gimp *gimp, + GimpBrushPipe *pipe) +{ + GimpImage *image; + const gchar *name; + GimpImageBaseType base_type; + GimpParasite *parasite; + gint i; + + if (gimp_brush_get_pixmap (pipe->current)) + base_type = GIMP_RGB; + else + base_type = GIMP_GRAY; + + name = gimp_object_get_name (pipe); + + image = gimp_image_new (gimp, 1, 1, base_type, + GIMP_PRECISION_U8_GAMMA); + + parasite = gimp_parasite_new ("gimp-brush-pipe-name", + GIMP_PARASITE_PERSISTENT, + strlen (name) + 1, name); + gimp_image_parasite_attach (image, parasite); + gimp_parasite_free (parasite); + + for (i = 0; i < pipe->n_brushes; i++) + { + GimpLayer *layer; + + layer = file_gbr_brush_to_layer (image, pipe->brushes[i]); + gimp_image_add_layer (image, layer, NULL, i, FALSE); + } + + if (pipe->params) + { + GimpPixPipeParams params; + gchar *paramstring; + + /* Since we do not (yet) load the pipe as described in the + * header, but use one layer per brush, we have to alter the + * paramstring before attaching it as a parasite. + * + * (this comment copied over from file-gih, whatever "as + * described in the header" means) -- mitch + */ + + gimp_pixpipe_params_init (¶ms); + gimp_pixpipe_params_parse (pipe->params, ¶ms); + + params.cellwidth = gimp_image_get_width (image); + params.cellheight = gimp_image_get_height (image); + params.cols = 1; + params.rows = 1; + + paramstring = gimp_pixpipe_params_build (¶ms); + if (paramstring) + { + parasite = gimp_parasite_new ("gimp-brush-pipe-parameters", + GIMP_PARASITE_PERSISTENT, + strlen (paramstring) + 1, + paramstring); + gimp_image_parasite_attach (image, parasite); + gimp_parasite_free (parasite); + g_free (paramstring); + } + } + + return image; +} + +static GimpBrushPipe * +file_gih_image_to_pipe (GimpImage *image, + GimpDrawable *drawable, + const gchar *name, + gdouble spacing) +{ +#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); + + 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; +#endif + + return NULL; +} diff --git a/app/file-data/file-data-gih.h b/app/file-data/file-data-gih.h new file mode 100644 index 0000000000..877e4a53eb --- /dev/null +++ b/app/file-data/file-data-gih.h @@ -0,0 +1,37 @@ +/* GIMP - The GNU Image Manipulation Program + * Copyright (C) 1995 Spencer Kimball and Peter Mattis + * + * 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 3 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, see . + */ + +#ifndef __FILE_DATA_GIH_H__ +#define __FILE_DATA_GIH_H__ + + +GimpValueArray * file_gih_load_invoker (GimpProcedure *procedure, + Gimp *gimp, + GimpContext *context, + GimpProgress *progress, + const GimpValueArray *args, + GError **error); + +GimpValueArray * file_gih_save_invoker (GimpProcedure *procedure, + Gimp *gimp, + GimpContext *context, + GimpProgress *progress, + const GimpValueArray *args, + GError **error); + + +#endif /* __FILE_DATA_GIH_H__ */ diff --git a/app/file-data/file-data.c b/app/file-data/file-data.c index e425813cf8..9468cc0855 100644 --- a/app/file-data/file-data.c +++ b/app/file-data/file-data.c @@ -32,6 +32,7 @@ #include "file-data.h" #include "file-data-gbr.h" +#include "file-data-gih.h" #include "file-data-pat.h" #include "gimp-intl.h" @@ -197,6 +198,70 @@ file_data_init (Gimp *gimp) gimp_plug_in_manager_add_procedure (gimp->plug_in_manager, proc); g_object_unref (procedure); + /* file-gih-load */ + file = g_file_new_for_path ("file-gih-load"); + procedure = gimp_plug_in_procedure_new (GIMP_PLUGIN, file); + g_object_unref (file); + + procedure->proc_type = GIMP_INTERNAL; + procedure->marshal_func = file_gih_load_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); + gimp_plug_in_procedure_set_image_types (proc, NULL); + gimp_plug_in_procedure_set_file_proc (proc, "gih", "", ""); + gimp_plug_in_procedure_set_mime_types (proc, "image/gimp-x-gih"); + gimp_plug_in_procedure_set_handles_uri (proc); + + gimp_object_set_static_name (GIMP_OBJECT (procedure), "file-gih-load"); + gimp_procedure_set_static_strings (procedure, + "file-gih-load", + "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", + 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_string ("uri", + "URI", + "The URI of the file " + "to load", + TRUE, 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 load", + TRUE, FALSE, TRUE, + NULL, + GIMP_PARAM_READWRITE)); + + gimp_procedure_add_return_value (procedure, + gimp_param_spec_image_id ("image", + "Image", + "Output image", + gimp, FALSE, + 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 a8f4698e96..d37cd1b045 100644 --- a/plug-ins/common/file-gih.c +++ b/plug-ins/common/file-gih.c @@ -53,7 +53,6 @@ #include "libgimp/stdplugins-intl.h" -#define LOAD_PROC "file-gih-load" #define SAVE_PROC "file-gih-save" #define PLUG_IN_BINARY "file-gih" #define PLUG_IN_ROLE "gimp-file-gih" @@ -96,12 +95,6 @@ static void run (const gchar *name, gint *nreturn_vals, GimpParam **return_vals); -static gint32 gih_load_image (GFile *file, - GError **error); -static gboolean gih_load_one_brush (GInputStream *input, - gint32 image_ID, - GError **error); - static gboolean gih_save_dialog (gint32 image_ID); static gboolean gih_save_one_brush (GOutputStream *output, gint32 drawable_ID, @@ -169,36 +162,6 @@ query (void) { GIMP_PDB_STRINGARRAY, "sel", "Selection modes" } }; - static const GimpParamDef gih_load_args[] = - { - { GIMP_PDB_INT32, "run-mode", "The run mode { RUN-INTERACTIVE (0), RUN-NONINTERACTIVE (1) }" }, - { GIMP_PDB_STRING, "uri", "The name of the file to load" }, - { GIMP_PDB_STRING, "raw-uri", "The name of the file to load" } - }; - static const GimpParamDef gih_load_return_vals[] = - { - { GIMP_PDB_IMAGE, "image", "Output image" } - }; - - gimp_install_procedure (LOAD_PROC, - "loads images in GIMP brush pipe format", - "This plug-in loads a GIMP brush pipe as an image.", - "Jens Lautenbacher, Sven Neumann", - "Jens Lautenbacher, Sven Neumann", - "2000", - N_("GIMP brush (animated)"), - NULL, - GIMP_PLUGIN, - G_N_ELEMENTS (gih_load_args), - G_N_ELEMENTS (gih_load_return_vals), - gih_load_args, gih_load_return_vals); - - gimp_plugin_icon_register (LOAD_PROC, GIMP_ICON_TYPE_ICON_NAME, - (const guint8 *) GIMP_ICON_BRUSH); - gimp_register_file_handler_mime (LOAD_PROC, "image/x-gimp-gih"); - gimp_register_file_handler_uri (LOAD_PROC); - gimp_register_magic_load_handler (LOAD_PROC, "gih", "", ""); - gimp_install_procedure (SAVE_PROC, "exports images in GIMP brush pipe format", "This plug-in exports an image in the GIMP brush pipe " @@ -250,23 +213,7 @@ run (const gchar *name, values[0].type = GIMP_PDB_STATUS; values[0].data.d_status = GIMP_PDB_EXECUTION_ERROR; - if (strcmp (name, LOAD_PROC) == 0) - { - image_ID = gih_load_image (g_file_new_for_uri (param[1].data.d_string), - &error); - - if (image_ID != -1) - { - *nreturn_vals = 2; - values[1].type = GIMP_PDB_IMAGE; - values[1].data.d_image = image_ID; - } - else - { - status = GIMP_PDB_EXECUTION_ERROR; - } - } - else if (strcmp (name, SAVE_PROC) == 0) + if (strcmp (name, SAVE_PROC) == 0) { GFile *file; GimpParasite *name_parasite; @@ -445,369 +392,6 @@ run (const gchar *name, } -/* load routines */ - -static gboolean -gih_load_one_brush (GInputStream *input, - gint32 image_ID, - GError **error) -{ - gchar *name = NULL; - GimpBrushHeader bh; - guchar *brush_buf = NULL; - gint32 layer_ID; - gsize size; - GimpImageType image_type; - gint width, height; - gint new_width, new_height; - gsize bytes_read; - - if (! g_input_stream_read_all (input, &bh, sizeof (bh), - &bytes_read, NULL, error) || - bytes_read != sizeof (bh)) - { - return FALSE; - } - - /* rearrange the bytes in each unsigned int */ - bh.header_size = g_ntohl (bh.header_size); - bh.version = g_ntohl (bh.version); - bh.width = g_ntohl (bh.width); - bh.height = g_ntohl (bh.height); - bh.bytes = g_ntohl (bh.bytes); - bh.magic_number = g_ntohl (bh.magic_number); - bh.spacing = g_ntohl (bh.spacing); - - /* Sanitize values */ - if ((bh.width == 0) || (bh.width > GIMP_BRUSH_MAX_SIZE) || - (bh.height == 0) || (bh.height > GIMP_BRUSH_MAX_SIZE) || - ((bh.bytes != 1) && (bh.bytes != 4)) || - (G_MAXSIZE / bh.width / bh.height / bh.bytes < 1)) - { - return FALSE; - } - - if ((bh.magic_number != GIMP_BRUSH_MAGIC || - bh.version != 2) || - bh.header_size <= sizeof (bh)) - { - return FALSE; - } - - if ((size = (bh.header_size - sizeof (bh))) > 0) - { - if (size > GIMP_BRUSH_MAX_NAME) - { - g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_FAILED, - _("Brush name is too long: %lu"), - (gulong) size); - return FALSE; - } - - name = g_new0 (gchar, size + 1); - - if (! g_input_stream_read_all (input, name, size, - &bytes_read, NULL, error) || - bytes_read != size) - { - g_free (name); - return FALSE; - } - } - else - { - name = g_strdup (_("Unnamed")); - } - - /* Now there's just raw data left. */ - - size = (gsize) bh.width * bh.height * bh.bytes; - brush_buf = g_malloc (size); - - if (! g_input_stream_read_all (input, brush_buf, size, - &bytes_read, NULL, error) || - bytes_read != size) - { - g_free (brush_buf); - g_free (name); - return FALSE; - } - - if (bh.bytes == 1) - { - GimpPatternHeader ph; - - /* For backwards-compatibility, check if a pattern follows. - * The obsolete .gpb format did it this way. - */ - - if (g_input_stream_read_all (input, &ph, sizeof (GimpPatternHeader), - &bytes_read, NULL, error) && - bytes_read == sizeof (GimpPatternHeader)) - { - /* rearrange the bytes in each unsigned int */ - ph.header_size = g_ntohl (ph.header_size); - ph.version = g_ntohl (ph.version); - ph.width = g_ntohl (ph.width); - ph.height = g_ntohl (ph.height); - ph.bytes = g_ntohl (ph.bytes); - ph.magic_number = g_ntohl (ph.magic_number); - - if (ph.magic_number == GIMP_PATTERN_MAGIC && - ph.version == 1 && - ph.header_size > sizeof (GimpPatternHeader) && - ph.bytes == 3 && - ph.width == bh.width && - ph.height == bh.height && - g_input_stream_skip (input, - ph.header_size - sizeof (GimpPatternHeader), - NULL, NULL) == - ph.header_size - sizeof (GimpPatternHeader)) - { - guchar *plain_brush = brush_buf; - gint i; - - bh.bytes = 4; - brush_buf = g_malloc ((gsize) bh.width * bh.height * 4); - - for (i = 0; i < ph.width * ph.height; i++) - { - if (! g_input_stream_read_all (input, - brush_buf + i * 4, 3, - &bytes_read, NULL, error) || - bytes_read != 3) - { - g_free (name); - g_free (plain_brush); - g_free (brush_buf); - return FALSE; - } - - brush_buf[i * 4 + 3] = plain_brush[i]; - } - - g_free (plain_brush); - } - else if (! g_seekable_seek (G_SEEKABLE (input), - - sizeof (GimpPatternHeader), G_SEEK_CUR, - NULL, NULL)) - { - g_message (_("GIMP brush file appears to be corrupted.")); - g_free (name); - g_free (brush_buf); - return FALSE; - } - } - } - - /* - * Create a new layer of the proper size. - */ - - switch (bh.bytes) - { - case 1: - image_type = GIMP_GRAY_IMAGE; - break; - - case 4: - image_type = GIMP_RGBA_IMAGE; - if (gimp_image_base_type (image_ID) == GIMP_GRAY) - gimp_image_convert_rgb (image_ID); - break; - - default: - g_message ("Unsupported brush depth: %d\n" - "GIMP Brushes must be GRAY or RGBA\n", - bh.bytes); - g_free (name); - return FALSE; - } - - new_width = width = gimp_image_width (image_ID); - new_height = height = gimp_image_height (image_ID); - - if (bh.width > width || bh.height > height) - { - new_width = MAX (width, bh.width); - new_height = MAX (height, bh.height); - gimp_image_resize (image_ID, - new_width, new_height, - (new_width - width) / 2, (new_height - height) / 2); - } - - layer_ID = gimp_layer_new (image_ID, name, - bh.width, bh.height, - image_type, - 100, - gimp_image_get_default_new_layer_mode (image_ID)); - g_free (name); - - if (layer_ID != -1) - { - GeglBuffer *buffer; - gint i; - - gimp_image_insert_layer (image_ID, layer_ID, -1, num_layers++); - gimp_layer_set_offsets (layer_ID, - (new_width - bh.width) / 2, - (new_height - bh.height) / 2); - - buffer = gimp_drawable_get_buffer (layer_ID); - - /* invert */ - if (image_type == GIMP_GRAY_IMAGE) - for (i = 0; i < bh.width * bh.height; i++) - brush_buf[i] = 255 - brush_buf[i]; - - gegl_buffer_set (buffer, GEGL_RECTANGLE (0, 0, bh.width, bh.height), 0, - NULL, brush_buf, GEGL_AUTO_ROWSTRIDE); - - g_object_unref (buffer); - } - - g_free (brush_buf); - - return TRUE; -} - -static gint32 -gih_load_image (GFile *file, - GError **error) -{ - GInputStream *input; - gint i; - gint32 image_ID; - GString *buffer; - gchar c; - gchar *name = NULL; - gint num_of_brushes = 0; - gchar *paramstring; - GimpParasite *name_parasite; - GimpParasite *pipe_parasite; - gsize bytes_read; - - gimp_progress_init_printf (_("Opening '%s'"), - g_file_get_parse_name (file)); - - input = G_INPUT_STREAM (g_file_read (file, NULL, error)); - if (! input) - return -1; - - /* The file format starts with a painfully simple text header */ - - /* get the name */ - buffer = g_string_new (NULL); - while (g_input_stream_read_all (input, &c, 1, - &bytes_read, NULL, error) && - bytes_read == 1 && - c != '\n' && - buffer->len < 1024) - { - g_string_append_c (buffer, c); - } - - if (buffer->len > 0 && buffer->len < 1024) - name = buffer->str; - - g_string_free (buffer, FALSE); - - if (! name) - { - g_message ("Couldn't read name for brush pipe from '%s'", - g_file_get_parse_name (file)); - g_object_unref (input); - return -1; - } - - /* get the number of brushes */ - buffer = g_string_new (NULL); - while (g_input_stream_read_all (input, &c, 1, - &bytes_read, NULL, error) && - bytes_read == 1 && - c != '\n' && - buffer->len < 1024) - { - g_string_append_c (buffer, c); - } - - if (buffer->len > 0 && buffer->len < 1024) - { - num_of_brushes = strtol (buffer->str, ¶mstring, 10); - } - - if (num_of_brushes < 1) - { - g_message ("Brush pipes should have at least one brush."); - g_object_unref (input); - g_free (name); - g_string_free (buffer, TRUE); - return -1; - } - - image_ID = gimp_image_new (1, 1, GIMP_GRAY); - gimp_image_set_filename (image_ID, g_file_get_uri (file)); - - for (i = 0; i < num_of_brushes; i++) - { - if (! gih_load_one_brush (input, image_ID, error)) - { - g_object_unref (input); - g_free (name); - g_string_free (buffer, TRUE); - return -1; - } - - gimp_progress_update ((gdouble) i / (gdouble) num_of_brushes); - } - - g_object_unref (input); - - /* Attaching name as a parasite */ - name_parasite = gimp_parasite_new ("gimp-brush-pipe-name", - GIMP_PARASITE_PERSISTENT, - strlen (name) + 1, - name); - gimp_image_attach_parasite (image_ID, name_parasite); - gimp_parasite_free (name_parasite); - - while (*paramstring && g_ascii_isspace (*paramstring)) - paramstring++; - - /* Since we do not (yet) load the pipe as described in the header, - but use one layer per brush, we have to alter the paramstring - before attaching it as a parasite. - */ - - if (*paramstring) - { - gimp_pixpipe_params_parse (paramstring, &gihparams); - - gihparams.cellwidth = gimp_image_width (image_ID); - gihparams.cellheight = gimp_image_height (image_ID); - gihparams.cols = 1; - gihparams.rows = 1; - - paramstring = gimp_pixpipe_params_build (&gihparams); - if (paramstring) - { - pipe_parasite = gimp_parasite_new ("gimp-brush-pipe-parameters", - GIMP_PARASITE_PERSISTENT, - strlen (paramstring) + 1, - paramstring); - gimp_image_attach_parasite (image_ID, pipe_parasite); - gimp_parasite_free (pipe_parasite); - g_free (paramstring); - } - } - - g_string_free (buffer, TRUE); - - gimp_progress_update (1.0); - - return image_ID; -} - /* save routines */ static void diff --git a/po/POTFILES.in b/po/POTFILES.in index 8511a6ba6d..866aa089b7 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -276,6 +276,7 @@ app/file/file-save.c app/file/file-utils.c app/file-data/file-data-gbr.c +app/file-data/file-data-gih.c app/file-data/file-data-pat.c app/file-data/file-data.c