From 90659deb827281b63043dcccee6ebebc2033b1ce Mon Sep 17 00:00:00 2001 From: Alberto Griggio Date: Tue, 27 Jun 2017 20:21:34 +0200 Subject: [PATCH] Bug 784228 - Add RawTherapee plugin to GIMP sources and installers Copy of files from RawTherapee official repository, as of today: https://github.com/Beep6581/RawTherapee/tree/dev/tools/gimp-plugin Based off file-darktable plugin. --- plug-ins/file-rawtherapee/file-formats.h | 316 ++++++++++++++ plug-ins/file-rawtherapee/file-rawtherapee.c | 424 +++++++++++++++++++ 2 files changed, 740 insertions(+) create mode 100644 plug-ins/file-rawtherapee/file-formats.h create mode 100644 plug-ins/file-rawtherapee/file-rawtherapee.c diff --git a/plug-ins/file-rawtherapee/file-formats.h b/plug-ins/file-rawtherapee/file-formats.h new file mode 100644 index 0000000000..b967c7cbe2 --- /dev/null +++ b/plug-ins/file-rawtherapee/file-formats.h @@ -0,0 +1,316 @@ +/* GIMP - The GNU Image Manipulation Program + * Copyright (C) 1995 Spencer Kimball and Peter Mattis + * + * file-rawtherapee.c -- raw file format plug-in that uses rawtherapee + * Copyright (C) 2016 Tobias Ellinghaus + * Copyright (C) 2017 Alberto Griggio + * + * 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 . + */ + +/* These are the raw formats that file-rawtherapee will register */ + +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; +}; + +#define N_(s) s +#define _(s) s + +static const FileFormat file_formats[] = +{ + { + N_("Raw Canon"), + "image/x-canon-cr2,image/x-canon-crw", + "cr2,crw", + NULL, + + "file-rawtherapee-canon-load", + "Load files in the Canon raw formats via rawtherapee", + "This plug-in loads files in Canon's raw formats by calling rawtherapee." + }, + + { + N_("Raw Nikon"), + "image/x-nikon-nef,image/x-nikon-nrw", + "nef,nrw", + NULL, + + "file-rawtherapee-nikon-load", + "Load files in the Nikon raw formats via rawtherapee", + "This plug-in loads files in Nikon's raw formats by calling rawtherapee." + }, + + { + N_("Raw Hasselblad"), + "image/x-hasselblad-3fr,image/x-hasselblad-fff", + "3fr,fff", + NULL, + + "file-rawtherapee-hasselblad-load", + "Load files in the Hasselblad raw formats via rawtherapee", + "This plug-in loads files in Hasselblad's raw formats by calling rawtherapee." + }, + + { + N_("Raw Sony"), + "image/x-sony-arw,image/x-sony-srf,image/x-sony-sr2", + "arw,srf,sr2", + NULL, + + "file-rawtherapee-sony-load", + "Load files in the Sony raw formats via rawtherapee", + "This plug-in loads files in Sony's raw formats by calling rawtherapee." + }, + + { + N_("Raw Casio BAY"), + "image/x-casio-bay", + "bay", + NULL, + + "file-rawtherapee-bay-load", + "Load files in the BAY raw format via rawtherapee", + "This plug-in loads files in Casio's raw BAY format by calling rawtherapee." + }, + + { + N_("Raw Phantom Software CINE"), + "", /* FIXME: find a mime type */ + "cine,cin", + NULL, + + "file-rawtherapee-cine-load", + "Load files in the CINE raw format via rawtherapee", + "This plug-in loads files in Phantom Software's raw CINE format by calling rawtherapee." + }, + + { + N_("Raw Sinar"), + "", /* FIXME: find a mime type */ + "cs1,ia,sti", + NULL, + + "file-rawtherapee-sinar-load", + "Load files in the Sinar raw formats via rawtherapee", + "This plug-in loads files in Sinar's raw formats by calling rawtherapee." + }, + + { + N_("Raw Kodak"), + "image/x-kodak-dc2,image/x-kodak-dcr,image/x-kodak-kdc,image/x-kodak-k25,image/x-kodak-kc2", + "dc2,dcr,kdc,k25,kc2", + NULL, + + "file-rawtherapee-kodak-load", + "Load files in the Kodak raw formats via rawtherapee", + "This plug-in loads files in Kodak's raw formats by calling rawtherapee." + }, + + { + N_("Raw Adobe DNG Digital Negative"), + "image/x-adobe-dng", + "dng", + NULL, + + "file-rawtherapee-dng-load", + "Load files in the DNG raw format via rawtherapee", + "This plug-in loads files in the Adobe Digital Negative DNG format by calling rawtherapee." + }, + + { + N_("Raw Epson ERF"), + "image/x-epson-erf", + "erf", + NULL, + + "file-rawtherapee-erf-load", + "Load files in the ERF raw format via rawtherapee", + "This plug-in loads files in Epson's raw ERF format by calling rawtherapee." + }, + + { + N_("Raw Phase One"), + "image/x-phaseone-cap,image/x-phaseone-iiq", + "cap,iiq", + NULL, + + "file-rawtherapee-phaseone-load", + "Load files in the Phase One raw formats via rawtherapee", + "This plug-in loads files in Phase One's raw formats by calling rawtherapee." + }, + + { + N_("Raw Minolta"), + "image/x-minolta-mdc,image/x-minolta-mrw", + "mdc,mrw", + NULL, + + "file-rawtherapee-minolta-load", + "Load files in the Minolta raw formats via rawtherapee", + "This plug-in loads files in Minolta's raw formats by calling rawtherapee." + }, + + { + N_("Raw Mamiya MEF"), + "image/x-mamiya-mef", + "mef", NULL, + + "file-rawtherapee-mef-load", + "Load files in the MEF raw format via rawtherapee", + "This plug-in loads files in Mamiya's raw MEF format by calling rawtherapee." + }, + + { + N_("Raw Leaf MOS"), + "image/x-leaf-mos", + "mos", + NULL, + + "file-rawtherapee-mos-load", + "Load files in the MOS raw format via rawtherapee", + "This plug-in loads files in Leaf's raw MOS format by calling rawtherapee." + }, + + { + N_("Raw Olympus ORF"), + "image/x-olympus-orf", + "orf", + NULL, + + "file-rawtherapee-orf-load", + "Load files in the ORF raw format via rawtherapee", + "This plug-in loads files in Olympus' raw ORF format by calling rawtherapee." + }, + + { + N_("Raw Pentax PEF"), + "image/x-pentax-pef,image/x-pentax-raw", + "pef,raw", + NULL, + + "file-rawtherapee-pef-load", + "Load files in the PEF raw format via rawtherapee", + "This plug-in loads files in Pentax' raw PEF format by calling rawtherapee." + }, + + { + N_("Raw Logitech PXN"), + "image/x-pxn", /* FIXME: is that the correct mime type? */ + "pxn", + NULL, + + "file-rawtherapee-pxn-load", + "Load files in the PXN raw format via rawtherapee", + "This plug-in loads files in Logitech's raw PXN format by calling rawtherapee." + }, + + { + N_("Raw Apple QuickTake QTK"), + "", /* FIXME: find a mime type */ + "qtk", + NULL, + + "file-rawtherapee-qtk-load", + "Load files in the QTK raw format via rawtherapee", + "This plug-in loads files in Apple's QuickTake QTK raw format by calling rawtherapee." + }, + + { + N_("Raw Fujifilm RAF"), + "image/x-fuji-raf", + "raf", + NULL, + + "file-rawtherapee-raf-load", + "Load files in the RAF raw format via rawtherapee", + "This plug-in loads files in Fujifilm's raw RAF format by calling rawtherapee." + }, + + { + N_("Raw Panasonic"), + "image/x-panasonic-raw,image/x-panasonic-rw2", + "raw,rw2", + NULL, + + "file-rawtherapee-panasonic-load", + "Load files in the Panasonic raw formats via rawtherapee", + "This plug-in loads files in Panasonic's raw formats by calling rawtherapee." + }, + + { + N_("Raw Digital Foto Maker RDC"), + "", /* FIXME: find a mime type */ + "rdc", + NULL, + + "file-rawtherapee-rdc-load", + "Load files in the RDC raw format via rawtherapee", + "This plug-in loads files in Digital Foto Maker's raw RDC format by calling rawtherapee." + }, + + { + N_("Raw Leica RWL"), + "image/x-leica-rwl", + "rwl", + NULL, + + "file-rawtherapee-rwl-load", + "Load files in the RWL raw format via rawtherapee", + "This plug-in loads files in Leica's raw RWL format by calling rawtherapee." + }, + + { + N_("Raw Samsung SRW"), + "image/x-samsung-srw", + "srw", + NULL, + + "file-rawtherapee-srw-load", + "Load files in the SRW raw format via rawtherapee", + "This plug-in loads files in Samsung's raw SRW format by calling rawtherapee." + }, + + { + N_("Raw Sigma X3F"), + "image/x-sigma-x3f", + "x3f", + NULL, + + "file-rawtherapee-x3f-load", + "Load files in the X3F raw format via rawtherapee", + "This plug-in loads files in Sigma's raw X3F format by calling rawtherapee." + }, + + { + N_("Raw Arriflex ARI"), + "", + "ari", + NULL, + + "file-rawtherapee-ari-load", + "Load files in the ARI raw format via rawtherapee", + "This plug-in loads files in Arriflex' raw ARI format by calling rawtherapee." + } +}; diff --git a/plug-ins/file-rawtherapee/file-rawtherapee.c b/plug-ins/file-rawtherapee/file-rawtherapee.c new file mode 100644 index 0000000000..92ce40f9fd --- /dev/null +++ b/plug-ins/file-rawtherapee/file-rawtherapee.c @@ -0,0 +1,424 @@ +/* GIMP - The GNU Image Manipulation Program + * Copyright (C) 1995 Spencer Kimball and Peter Mattis + * + * file-rawtherapee.c -- raw file format plug-in that uses RawTherapee + * Copyright (C) 2012 Simon Budig + * Copyright (C) 2016 Tobias Ellinghaus + * Copyright (C) 2017 Alberto Griggio + * + * 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 + +//#include "libgimp/stdplugins-intl.h" + +#include "file-formats.h" + + +#define LOAD_THUMB_PROC "file-rawtherapee-load-thumb" + + +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, + GimpRunMode run_mode, + GError **error); + +static gint32 load_thumbnail_image (const gchar *filename, + gint thumb_size, + GError **error); + +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 thumb_args[] = + { + { GIMP_PDB_STRING, "filename", "The name of the file to load" }, + { GIMP_PDB_INT32, "thumb-size", "Preferred thumbnail size" } + }; + + static const GimpParamDef thumb_return_vals[] = + { + { GIMP_PDB_IMAGE, "image", "Thumbnail image" } + }; + + /* check if rawtherapee is installed + * TODO: allow setting the location of the executable in preferences + */ + gchar *argv[] = { "rawtherapee", "-v", NULL }; + gchar *rawtherapee_stdout = NULL; + gboolean have_rawtherapee = FALSE; + gint i; + + if (g_spawn_sync (NULL, + argv, + NULL, + G_SPAWN_STDERR_TO_DEV_NULL | + G_SPAWN_SEARCH_PATH, + NULL, + NULL, + &rawtherapee_stdout, + NULL, + NULL, + NULL)) + { + char *rtversion = NULL; + + if (sscanf (rawtherapee_stdout, + "RawTherapee, version %ms", + &rtversion) == 1) + { + have_rawtherapee = TRUE; + free(rtversion); + } + + g_free (rawtherapee_stdout); + } + + if (! have_rawtherapee) + return; + + gimp_install_procedure (LOAD_THUMB_PROC, + "Load thumbnail from a raw image via rawtherapee", + "This plug-in loads a thumbnail from a raw image by calling rawtherapee-cli.", + "Alberto Griggio", + "Alberto Griggio", + "2017", + NULL, + NULL, + GIMP_PLUGIN, + G_N_ELEMENTS (thumb_args), + G_N_ELEMENTS (thumb_return_vals), + thumb_args, thumb_return_vals); + + for (i = 0; i < G_N_ELEMENTS (file_formats); i++) + { + const FileFormat *format = &file_formats[i]; + + gimp_install_procedure (format->load_proc, + format->load_blurb, + format->load_help, + "Alberto Griggio", + "Alberto Griggio", + "2017", + 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_file_handler_raw (format->load_proc); + gimp_register_magic_load_handler (format->load_proc, + format->extensions, + "", + format->magic); + + gimp_register_thumbnail_loader (format->load_proc, LOAD_THUMB_PROC); + } +} + +static void +run (const gchar *name, + gint nparams, + const GimpParam *param, + gint *nreturn_vals, + GimpParam **return_vals) +{ + static GimpParam values[6]; + GimpPDBStatusType status = GIMP_PDB_SUCCESS; + GimpRunMode run_mode; + gint image_ID; + GError *error = NULL; + gint i; + +// INIT_I18N (); + + 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; + + /* check if the format passed is actually supported & load */ + 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, run_mode, &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 (! strcmp (name, LOAD_THUMB_PROC)) + { + image_ID = load_thumbnail_image (param[0].data.d_string, + param[1].data.d_int32, + &error); + + if (image_ID != -1) + { + *nreturn_vals = 4; + values[1].type = GIMP_PDB_IMAGE; + values[1].data.d_image = image_ID; + values[4].type = GIMP_PDB_INT32; + values[4].data.d_int32 = GIMP_RGB_IMAGE; + values[5].type = GIMP_PDB_INT32; + values[5].data.d_int32 = 1; /* num_layers */ + } + else + { + status = GIMP_PDB_EXECUTION_ERROR; + } + + 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; +} + +static gint32 +load_image (const gchar *filename, + GimpRunMode run_mode, + GError **error) +{ + gint32 image_ID = -1; + gchar *filename_out = gimp_temp_name ("tif"); + + gchar *rawtherapee_stdout = NULL; + + /* linear sRGB for now as GIMP uses that internally in many places anyway */ + gchar *argv[] = + { + "rawtherapee", + "-gimp", + (gchar *) filename, + filename_out, + NULL + }; + + gimp_progress_init_printf (_("Opening '%s'"), + gimp_filename_to_utf8 (filename)); + + if (g_spawn_sync (NULL, + argv, + NULL, +// G_SPAWN_STDOUT_TO_DEV_NULL | + G_SPAWN_STDERR_TO_DEV_NULL | + G_SPAWN_SEARCH_PATH, + NULL, + NULL, + &rawtherapee_stdout, + NULL, + NULL, + error)) + { + image_ID = gimp_file_load (run_mode, filename_out, filename_out); + if (image_ID != -1) + gimp_image_set_filename (image_ID, filename); + } + +// if (rawtherapee_stdout) printf ("%s\n", rawtherapee_stdout); + g_free(rawtherapee_stdout); + + g_unlink (filename_out); + g_free (filename_out); + + gimp_progress_update (1.0); + + return image_ID; +} + +static gint32 +load_thumbnail_image (const gchar *filename, + gint thumb_size, + GError **error) +{ + gint32 image_ID = -1; + gchar *filename_out = gimp_temp_name ("jpg"); + gchar *thumb_pp3 = gimp_temp_name ("pp3"); + gchar *size = g_strdup_printf ("%d", thumb_size); + FILE *thumb_pp3_f = fopen(thumb_pp3, "w"); + gboolean pp3_ok = FALSE; + gchar *rawtherapee_stdout = NULL; + const char *pp3_content = + "[Version]\n" + "AppVersion=5.0\n" + "Version=326\n" + "\n" + "[Resize]\n" + "Enabled=true\n" + "AppliesTo=Cropped area\n" + "Method=Lanczos\n" + "Width=%d\n" + "Height=%d\n" + "\n" + "[Sharpening]\n" + "Enabled=false\n" + "\n" + "[SharpenEdge]\n" + "Enabled=false\n" + "\n" + "[SharpenMicro]\n" + "Enabled=false\n" + "\n" + "[Defringing]\n" + "Enabled=false\n" + "\n" + "[Directional Pyramid Equalizer]\n" + "Enabled=false\n" + "\n" + "[PostResizeSharpening]\n" + "Enabled=false\n" + "\n" + "[Directional Pyramid Denoising]\n" + "Enabled=false\n" + "\n" + "[Impulse Denoising]\n" + "Enabled=false\n" + "\n" + "[Wavelet]\n" + "Enabled=false\n" + "\n" + "[RAW Bayer]\n" + "Method=fast\n" + "\n" + "[RAW X-Trans]\n" + "Method=fast\n"; + + + gchar *argv[] = + { + "rawtherapee-cli", + "-o", filename_out, + "-d", + "-s", + "-j", + "-p", thumb_pp3, + "-f", + "-c", (char *) filename, + NULL + }; + + if (thumb_pp3_f) { + if (fprintf(thumb_pp3_f, pp3_content, thumb_size, thumb_size) < 0) { + fclose(thumb_pp3_f); + thumb_pp3_f = NULL; + } + } + + gimp_progress_init_printf (_("Opening thumbnail for '%s'"), + gimp_filename_to_utf8 (filename)); + + if (thumb_pp3_f && + g_spawn_sync (NULL, + argv, + NULL, + G_SPAWN_STDERR_TO_DEV_NULL | + G_SPAWN_SEARCH_PATH, + NULL, + NULL, + &rawtherapee_stdout, + NULL, + NULL, + error)) + { + gimp_progress_update (0.5); + + image_ID = gimp_file_load (GIMP_RUN_NONINTERACTIVE, + filename_out, + filename_out); + if (image_ID != -1) + { + /* is this needed for thumbnails? */ + gimp_image_set_filename (image_ID, filename); + } + } + + gimp_progress_update (1.0); + + if (thumb_pp3_f) { + fclose(thumb_pp3_f); + } + g_unlink (thumb_pp3); + g_free (filename_out); + g_free (thumb_pp3); + g_free (rawtherapee_stdout); + + return image_ID; +}