/* 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 * * 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 #include #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; }