diff options
Diffstat (limited to 'plug-ins/common/file-gegl.c')
-rw-r--r-- | plug-ins/common/file-gegl.c | 492 |
1 files changed, 492 insertions, 0 deletions
diff --git a/plug-ins/common/file-gegl.c b/plug-ins/common/file-gegl.c new file mode 100644 index 0000000..978c7e7 --- /dev/null +++ b/plug-ins/common/file-gegl.c @@ -0,0 +1,492 @@ +/* GIMP - The GNU Image Manipulation Program + * Copyright (C) 1995 Spencer Kimball and Peter Mattis + * + * file-gegl.c -- GEGL based file format plug-in + * Copyright (C) 2012 Simon Budig <simon@gimp.org> + * + * 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 <https://www.gnu.org/licenses/>. + */ + +#include "config.h" + +#include <stdlib.h> +#include <errno.h> + +#include <glib/gstdio.h> + +#include <libgimp/gimp.h> +#include <libgimp/gimpui.h> + +#include "libgimp/stdplugins-intl.h" + + +#define PLUG_IN_BINARY "file-gegl" + + +typedef struct _FileFormat FileFormat; + +struct _FileFormat +{ + const gchar *file_type; + const gchar *mime_type; + const gchar *extensions; + const gchar *magic; + + const gchar *load_proc; + const gchar *load_blurb; + const gchar *load_help; + const gchar *load_op; + + const gchar *save_proc; + const gchar *save_blurb; + const gchar *save_help; + const gchar *save_op; +}; + + +static void query (void); +static void run (const gchar *name, + gint nparams, + const GimpParam *param, + gint *nreturn_vals, + GimpParam **return_vals); +static gint32 load_image (const gchar *filename, + const gchar *gegl_op, + GError **error); +static gboolean save_image (const gchar *filename, + const gchar *gegl_op, + gint32 image_ID, + gint32 drawable_ID, + GError **error); + + +static const FileFormat file_formats[] = +{ + { + N_("Radiance RGBE"), + "image/vnd.radiance", + "hdr", + "0,string,#?", + + "file-load-rgbe", + "Load files in the RGBE file format", + "This procedure loads images in the RGBE format, using gegl:rgbe-load", + "gegl:rgbe-load", + + "file-save-rgbe", + "Saves files in the RGBE file format", + "This procedure exports images in the RGBE format, using gegl:rgbe-save", + "gegl:rgbe-save", + }, + { + N_("OpenEXR image"), + "image/x-exr", + "exr", + "0,lelong,20000630", + + /* no EXR loading (implemented in native GIMP plug-in) */ + NULL, NULL, NULL, NULL, + + "file-exr-save", + "Saves files in the OpenEXR file format", + "This procedure saves images in the OpenEXR format, using gegl:exr-save", + "gegl:exr-save" + } +}; + + +const GimpPlugInInfo PLUG_IN_INFO = +{ + NULL, /* init_proc */ + NULL, /* quit_proc */ + query, /* query proc */ + run, /* run_proc */ +}; + +MAIN () + +static void +query (void) +{ + static const GimpParamDef load_args[] = + { + { GIMP_PDB_INT32, "run-mode", "The run mode { RUN-INTERACTIVE (0), RUN-NONINTERACTIVE (1) }" }, + { GIMP_PDB_STRING, "filename", "The name of the file to load." }, + { GIMP_PDB_STRING, "raw-filename", "The name entered" }, + }; + + static const GimpParamDef load_return_vals[] = + { + { GIMP_PDB_IMAGE, "image", "Output image" } + }; + + static const GimpParamDef save_args[] = + { + { GIMP_PDB_INT32, "run-mode", "The run mode { RUN-INTERACTIVE (0), RUN-NONINTERACTIVE (1) }" }, + { GIMP_PDB_IMAGE, "image", "Input image" }, + { GIMP_PDB_DRAWABLE, "drawable", "Drawable to save" }, + { GIMP_PDB_STRING, "filename", "The name of the file to save the image in" }, + { GIMP_PDB_STRING, "raw-filename", "The name of the file to save the image in" } + }; + + gint i; + + for (i = 0; i < G_N_ELEMENTS (file_formats); i++) + { + const FileFormat *format = &file_formats[i]; + + if (format->load_proc) + { + gimp_install_procedure (format->load_proc, + format->load_blurb, + format->load_help, + "Simon Budig", + "Simon Budig", + "2012", + format->file_type, + NULL, + GIMP_PLUGIN, + G_N_ELEMENTS (load_args), + G_N_ELEMENTS (load_return_vals), + load_args, load_return_vals); + + gimp_register_file_handler_mime (format->load_proc, + format->mime_type); + gimp_register_magic_load_handler (format->load_proc, + format->extensions, + "", + format->magic); + } + + if (format->save_proc) + { + gimp_install_procedure (format->save_proc, + format->save_blurb, + format->save_help, + "Simon Budig", + "Simon Budig", + "2012", + format->file_type, + "*", + GIMP_PLUGIN, + G_N_ELEMENTS (save_args), 0, + save_args, NULL); + + gimp_register_file_handler_mime (format->save_proc, + format->mime_type); + gimp_register_save_handler (format->save_proc, + format->extensions, ""); + } + } +} + +static void +run (const gchar *name, + gint nparams, + const GimpParam *param, + gint *nreturn_vals, + GimpParam **return_vals) +{ + static GimpParam values[2]; + GimpPDBStatusType status = GIMP_PDB_SUCCESS; + GimpRunMode run_mode; + gint image_ID; + gint drawable_ID; + GError *error = NULL; + gint i; + + INIT_I18N (); + gegl_init (NULL, NULL); + + run_mode = param[0].data.d_int32; + + *nreturn_vals = 1; + *return_vals = values; + + values[0].type = GIMP_PDB_STATUS; + values[0].data.d_status = GIMP_PDB_EXECUTION_ERROR; + + for (i = 0; i < G_N_ELEMENTS (file_formats); i++) + { + const FileFormat *format = &file_formats[i]; + + if (format->load_proc && !strcmp (name, format->load_proc)) + { + image_ID = load_image (param[1].data.d_string, format->load_op, &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; + } + + break; + } + else if (format->save_proc && !strcmp (name, format->save_proc)) + { + GimpExportReturn export = GIMP_EXPORT_CANCEL; + + image_ID = param[1].data.d_int32; + drawable_ID = param[2].data.d_int32; + + /* eventually export the image */ + switch (run_mode) + { + case GIMP_RUN_INTERACTIVE: + case GIMP_RUN_WITH_LAST_VALS: + gimp_ui_init (PLUG_IN_BINARY, FALSE); + + export = gimp_export_image (&image_ID, &drawable_ID, "GEGL", + GIMP_EXPORT_CAN_HANDLE_RGB | + GIMP_EXPORT_CAN_HANDLE_GRAY | + GIMP_EXPORT_CAN_HANDLE_INDEXED | + GIMP_EXPORT_CAN_HANDLE_ALPHA); + + if (export == GIMP_EXPORT_CANCEL) + { + *nreturn_vals = 1; + values[0].data.d_status = GIMP_PDB_CANCEL; + return; + } + break; + + default: + break; + } + + if (! save_image (param[3].data.d_string, + format->save_op, + image_ID, drawable_ID, + &error)) + { + status = GIMP_PDB_EXECUTION_ERROR; + } + + if (export == GIMP_EXPORT_EXPORT) + gimp_image_delete (image_ID); + + break; + } + } + + if (i == G_N_ELEMENTS (file_formats)) + status = GIMP_PDB_CALLING_ERROR; + + if (status != GIMP_PDB_SUCCESS && error) + { + *nreturn_vals = 2; + values[1].type = GIMP_PDB_STRING; + values[1].data.d_string = error->message; + } + + values[0].data.d_status = status; + + gegl_exit (); +} + +static gint32 +load_image (const gchar *filename, + const gchar *gegl_op, + GError **error) +{ + gint32 image_ID = -1; + gint32 layer_ID; + GimpImageType image_type; + GimpImageBaseType base_type; + GimpPrecision precision; + gint width; + gint height; + GeglNode *graph; + GeglNode *sink; + GeglNode *source; + GeglBuffer *src_buf = NULL; + GeglBuffer *dest_buf = NULL; + const Babl *format; + + gimp_progress_init_printf (_("Opening '%s'"), + gimp_filename_to_utf8 (filename)); + + graph = gegl_node_new (); + + source = gegl_node_new_child (graph, + "operation", gegl_op, + "path", filename, + NULL); + sink = gegl_node_new_child (graph, + "operation", "gegl:buffer-sink", + "buffer", &src_buf, + NULL); + + gegl_node_connect_to (source, "output", + sink, "input"); + + gegl_node_process (sink); + + g_object_unref (graph); + + if (! src_buf) + { + g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_FAILED, + _("Could not open '%s'"), + gimp_filename_to_utf8 (filename)); + return -1; + } + + gimp_progress_update (0.33); + + width = gegl_buffer_get_width (src_buf); + height = gegl_buffer_get_height (src_buf); + format = gegl_buffer_get_format (src_buf); + + if (babl_format_is_palette (format)) + { + base_type = GIMP_INDEXED; + + if (babl_format_has_alpha (format)) + image_type = GIMP_INDEXEDA_IMAGE; + else + image_type = GIMP_INDEXED_IMAGE; + + precision = GIMP_PRECISION_U8_GAMMA; + } + else + { + const Babl *model = babl_format_get_model (format); + const Babl *type = babl_format_get_type (format, 0); + gboolean linear = TRUE; + + if (model == babl_model ("Y") || + model == babl_model ("Y'") || + model == babl_model ("YA") || + model == babl_model ("Y'A")) + { + base_type = GIMP_GRAY; + + if (babl_format_has_alpha (format)) + image_type = GIMP_GRAYA_IMAGE; + else + image_type = GIMP_GRAY_IMAGE; + + if (model == babl_model ("Y'") || + model == babl_model ("Y'A")) + linear = FALSE; + } + else + { + base_type = GIMP_RGB; + + if (babl_format_has_alpha (format)) + image_type = GIMP_RGBA_IMAGE; + else + image_type = GIMP_RGB_IMAGE; + + if (model == babl_model ("R'G'B'") || + model == babl_model ("R'G'B'A")) + linear = FALSE; + } + + if (linear) + { + if (type == babl_type ("u8")) + precision = GIMP_PRECISION_U8_LINEAR; + else if (type == babl_type ("u16")) + precision = GIMP_PRECISION_U16_LINEAR; + else if (type == babl_type ("u32")) + precision = GIMP_PRECISION_U32_LINEAR; + else if (type == babl_type ("half")) + precision = GIMP_PRECISION_HALF_LINEAR; + else + precision = GIMP_PRECISION_FLOAT_LINEAR; + } + else + { + if (type == babl_type ("u8")) + precision = GIMP_PRECISION_U8_GAMMA; + else if (type == babl_type ("u16")) + precision = GIMP_PRECISION_U16_GAMMA; + else if (type == babl_type ("u32")) + precision = GIMP_PRECISION_U32_GAMMA; + else if (type == babl_type ("half")) + precision = GIMP_PRECISION_HALF_GAMMA; + else + precision = GIMP_PRECISION_FLOAT_GAMMA; + } + } + + + image_ID = gimp_image_new_with_precision (width, height, + base_type, precision); + gimp_image_set_filename (image_ID, filename); + + layer_ID = gimp_layer_new (image_ID, + _("Background"), + width, height, + image_type, + 100, + gimp_image_get_default_new_layer_mode (image_ID)); + gimp_image_insert_layer (image_ID, layer_ID, -1, 0); + dest_buf = gimp_drawable_get_buffer (layer_ID); + + gimp_progress_update (0.66); + + gegl_buffer_copy (src_buf, NULL, GEGL_ABYSS_NONE, dest_buf, NULL); + + g_object_unref (src_buf); + g_object_unref (dest_buf); + + gimp_progress_update (1.0); + + return image_ID; +} + +static gboolean +save_image (const gchar *filename, + const gchar *gegl_op, + gint32 image_ID, + gint32 drawable_ID, + GError **error) +{ + GeglNode *graph; + GeglNode *source; + GeglNode *sink; + GeglBuffer *src_buf; + + src_buf = gimp_drawable_get_buffer (drawable_ID); + + graph = gegl_node_new (); + + source = gegl_node_new_child (graph, + "operation", "gegl:buffer-source", + "buffer", src_buf, + NULL); + sink = gegl_node_new_child (graph, + "operation", gegl_op, + "path", filename, + NULL); + + gegl_node_connect_to (source, "output", + sink, "input"); + + gegl_node_process (sink); + + g_object_unref (graph); + g_object_unref (src_buf); + + return TRUE; +} |