From 54b66b773682b9def8691b29e32b3da6f63af059 Mon Sep 17 00:00:00 2001 From: Alberto Griggio Date: Thu, 18 May 2017 15:59:56 +0200 Subject: [PATCH 1/4] Added support for using RawTherapee as a GIMP plugin for opening RAW files plugin code taken from Darktable --- rtgui/editorpanel.cc | 42 ++- rtgui/editorpanel.h | 2 + rtgui/filepanel.cc | 9 +- rtgui/main.cc | 54 +++- rtgui/options.h | 1 + rtgui/rtwindow.cc | 9 + tools/gimp-plugin/file-formats.h | 322 +++++++++++++++++++ tools/gimp-plugin/file-rawtherapee.c | 450 +++++++++++++++++++++++++++ 8 files changed, 876 insertions(+), 13 deletions(-) create mode 100644 tools/gimp-plugin/file-formats.h create mode 100644 tools/gimp-plugin/file-rawtherapee.c diff --git a/rtgui/editorpanel.cc b/rtgui/editorpanel.cc index 459abbe5b..b9c66f6e0 100644 --- a/rtgui/editorpanel.cc +++ b/rtgui/editorpanel.cc @@ -679,13 +679,17 @@ EditorPanel::EditorPanel (FilePanel* filePanel) iops->attach_next_to (*vsep2, Gtk::POS_LEFT, 1, 1); iops->attach_next_to (*progressLabel, Gtk::POS_LEFT, 1, 1); iops->attach_next_to (*vsep1, Gtk::POS_LEFT, 1, 1); - iops->attach_next_to (*sendtogimp, Gtk::POS_LEFT, 1, 1); + if (!gimpPlugin) { + iops->attach_next_to (*sendtogimp, Gtk::POS_LEFT, 1, 1); + } - if (!simpleEditor) { + if (!gimpPlugin) { iops->attach_next_to (*queueimg, Gtk::POS_LEFT, 1, 1); } - iops->attach_next_to (*saveimgas, Gtk::POS_LEFT, 1, 1); + if (!gimpPlugin) { + iops->attach_next_to (*saveimgas, Gtk::POS_LEFT, 1, 1); + } // Color management toolbar @@ -1577,7 +1581,9 @@ bool EditorPanel::handleShortcutKey (GdkEventKey* event) return true; case GDK_KEY_s: - saveAsPressed(); + if (!gimpPlugin) { + saveAsPressed(); + } return true; case GDK_KEY_b: @@ -1588,7 +1594,9 @@ bool EditorPanel::handleShortcutKey (GdkEventKey* event) return true; case GDK_KEY_e: - sendToGimpPressed(); + if (!gimpPlugin) { + sendToGimpPressed(); + } return true; case GDK_KEY_z: @@ -1885,6 +1893,30 @@ void EditorPanel::sendToGimpPressed () } +bool EditorPanel::saveImmediately(const Glib::ustring &filename, SaveFormat sf) +{ + rtengine::procparams::ProcParams pparams; + ipc->getParams (&pparams); + std::unique_ptr job(rtengine::ProcessingJob::create (ipc->getInitialImage(), pparams)); + + // save immediately + rtengine::IImage16 *img = rtengine::processImage(job.get(), err, nullptr, options.tunnelMetaData, false); + + int err = 0; + if (sf.format == "tif") { + err = img->saveAsTIFF(filename, sf.tiffBits, sf.tiffUncompressed); + } else if (sf.format == "png") { + err = img->saveAsPNG(filename, sf.pngCompression, sf.pngBits); + } else if (sf.format == "jpg") { + err = img->saveAsJPEG(filename, sf.jpegQuality, sf.jpegSubSamp); + } else { + err = 1; + } + img->free(); + return !err; +} + + void EditorPanel::openPreviousEditorImage() { if (!simpleEditor && fPanel && !fname.empty()) { diff --git a/rtgui/editorpanel.h b/rtgui/editorpanel.h index 6cfedb634..676395b4a 100644 --- a/rtgui/editorpanel.h +++ b/rtgui/editorpanel.h @@ -131,6 +131,8 @@ public: void defaultMonitorProfileChanged(const Glib::ustring &profile_name, bool auto_monitor_profile); + bool saveImmediately(const Glib::ustring &filename, SaveFormat sf); + Gtk::Paned* catalogPane; private: diff --git a/rtgui/filepanel.cc b/rtgui/filepanel.cc index a8c24e83d..035b4e2db 100644 --- a/rtgui/filepanel.cc +++ b/rtgui/filepanel.cc @@ -190,8 +190,13 @@ void FilePanel::init () dirBrowser->fillDirTree (); placesBrowser->refreshPlacesList (); - if (argv1 != "" && Glib::file_test (argv1, Glib::FILE_TEST_IS_DIR)) { - dirBrowser->open (argv1); + //if (argv1 != "" && Glib::file_test (argv1, Glib::FILE_TEST_IS_DIR)) { + if (!argv1.empty() && Glib::file_test (argv1, Glib::FILE_TEST_EXISTS)) { + Glib::ustring d(argv1); + if (!Glib::file_test(d, Glib::FILE_TEST_IS_DIR)) { + d = Glib::path_get_dirname(d); + } + dirBrowser->open(d); } else { if (options.startupDir == STARTUPDIR_HOME) { dirBrowser->open (PlacesBrowser::userPicturesDir ()); diff --git a/rtgui/main.cc b/rtgui/main.cc index 495374f50..e096e23dc 100644 --- a/rtgui/main.cc +++ b/rtgui/main.cc @@ -60,7 +60,9 @@ Glib::ustring argv0; Glib::ustring creditsPath; Glib::ustring licensePath; Glib::ustring argv1; -bool simpleEditor; +Glib::ustring argv2; +bool simpleEditor = false; +bool gimpPlugin = false; Glib::RefPtr cssForced; Glib::RefPtr cssRT; //Glib::Threads::Thread* mainThread; @@ -292,12 +294,23 @@ int main(int argc, char **argv) #endif - simpleEditor = false; + //simpleEditor = false; - if( !argv1.empty() ) + if (!argv1.empty()) { if( Glib::file_test(argv1, Glib::FILE_TEST_EXISTS) && !Glib::file_test(argv1, Glib::FILE_TEST_IS_DIR)) { simpleEditor = true; } + } + if (gimpPlugin) { + if (!Glib::file_test(argv1, Glib::FILE_TEST_EXISTS) || Glib::file_test(argv1, Glib::FILE_TEST_IS_DIR)) { + printf("Error: argv1 doesn't exist\n"); + return 1; + } + if (argv2.empty()) { + printf("Error: -gimp requires two arguments\n"); + return 1; + } + } Gtk::Main m(&argc, &argv); @@ -385,7 +398,18 @@ int main(int argc, char **argv) // opening the main window m.run(*rtWindow); + if (gimpPlugin && rtWindow->epanel && rtWindow->epanel->isRealized()) { + SaveFormat sf; + sf.format = "tif"; + sf.tiffBits = 16; + sf.tiffUncompressed = true; + sf.saveParams = true; + + rtWindow->epanel->saveImmediately(argv2, sf); + } + gdk_threads_leave (); + delete rtWindow; rtengine::cleanup(); @@ -429,6 +453,16 @@ int processLineParams( int argc, char **argv ) case 'w': // This case is handled outside this function break; #endif + case 'g': + if (currParam == "-gimp") { + simpleEditor = true; + gimpPlugin = true; + break; + } + // no break here on purpose + + case 'v': + return 0; case 'h': case '?': @@ -455,16 +489,24 @@ int processLineParams( int argc, char **argv ) #ifdef WIN32 std::cout << " -w Do not open the Windows console" << std::endl; #endif + std::cout << " -v Print RawTherapee version number and exit" << std::endl; std::cout << " -h -? Display this help message" << std::endl; return -1; } } } else { - argv1 = Glib::ustring(fname_to_utf8(argv[iArg])); + if (argv1.empty()) { + argv1 = Glib::ustring(fname_to_utf8(argv[iArg])); #if ECLIPSE_ARGS - argv1 = argv1.substr(1, argv1.length()-2); + argv1 = argv1.substr(1, argv1.length()-2); #endif - break; + } else if (gimpPlugin) { + argv2 = Glib::ustring(fname_to_utf8(argv[iArg])); + break; + } + if (!gimpPlugin) { + break; + } } } diff --git a/rtgui/options.h b/rtgui/options.h index f67175c43..46a6d67ee 100644 --- a/rtgui/options.h +++ b/rtgui/options.h @@ -358,6 +358,7 @@ extern Options options; extern Glib::ustring argv0; extern Glib::ustring argv1; extern bool simpleEditor; +extern bool gimpPlugin; extern Glib::ustring versionString; extern Glib::ustring paramFileExtension; diff --git a/rtgui/rtwindow.cc b/rtgui/rtwindow.cc index ccf0b26e2..6d23c0d26 100644 --- a/rtgui/rtwindow.cc +++ b/rtgui/rtwindow.cc @@ -282,6 +282,14 @@ RTWindow::RTWindow () show_all (); bpanel->init (this); + + if (!argv1.empty()) { + Thumbnail* thm = cacheMgr->getEntry(argv1); + if (thm) { + std::vector entries(1, thm); + fpanel->fileCatalog->openRequested(entries); + } + } } if (!isSingleTabMode() && !simpleEditor) { @@ -646,6 +654,7 @@ bool RTWindow::on_delete_event(GdkEventAny* event) Options::save (); hide(); + on_delete_has_run = true; return false; } diff --git a/tools/gimp-plugin/file-formats.h b/tools/gimp-plugin/file-formats.h new file mode 100644 index 000000000..0cbaea707 --- /dev/null +++ b/tools/gimp-plugin/file-formats.h @@ -0,0 +1,322 @@ +/* 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 + * + * 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 + +/* some magic numbers taken from + * http://www.garykessler.net/library/file_sigs.html + * + * see also + * http://fileformats.archiveteam.org/wiki/Cameras_and_Digital_Image_Sensors + */ +static const FileFormat file_formats[] = +{ + { + N_("Raw Canon"), + "image/x-canon-cr2,image/x-canon-crw", + "cr2,crw", + "0,string,II*\\0\\020\\0\\0\\0CR," /* cr2 */ + "0,string,II\\024\\0\\0\\0HEAPCCDR," /* crw */ + + "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", + "0,string,IIRO,0,string,MMOR,0,string,IIRS", + + "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", + "0,string,FUJIFILMCCD-RAW", + + "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", + "0,string,IIU\\0", + + "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", + "0,string,FOVb", + + "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/tools/gimp-plugin/file-rawtherapee.c b/tools/gimp-plugin/file-rawtherapee.c new file mode 100644 index 000000000..1177cb8be --- /dev/null +++ b/tools/gimp-plugin/file-rawtherapee.c @@ -0,0 +1,450 @@ +/* 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, + gint *width, + gint *height, + 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" }, + { GIMP_PDB_INT32, "image-width", "Width of full-sized image" }, + { GIMP_PDB_INT32, "image-height", "Height of full-sized 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)) + { + gint width = 0; + gint height = 0; + + image_ID = load_thumbnail_image (param[0].data.d_string, + param[1].data.d_int32, + &width, + &height, + &error); + + if (image_ID != -1) + { + *nreturn_vals = 6; + values[1].type = GIMP_PDB_IMAGE; + values[1].data.d_image = image_ID; + values[2].type = GIMP_PDB_INT32; + values[2].data.d_int32 = width; + values[3].type = GIMP_PDB_INT32; + values[3].data.d_int32 = height; + 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, + gint *width, + gint *height, + 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)); + + *width = *height = thumb_size; + + 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) + { + /* /\* the size reported by raw files isn't precise, */ + /* * but it should be close enough to get an idea. */ + /* *\/ */ + /* gchar *start_of_size = g_strstr_len (rawtherapee_stdout, */ + /* -1, */ + /* "[dt4gimp]"); */ + /* if (start_of_size) */ + /* sscanf (start_of_size, "[dt4gimp] %d %d", width, height); */ + + /* 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; +} From 3c26516699148980e2c9290b7ba691cc00767133 Mon Sep 17 00:00:00 2001 From: Alberto Griggio Date: Wed, 24 May 2017 13:48:47 +0200 Subject: [PATCH 2/4] use `gimp_register_file_handler_raw` to register the plugin as a RAW importer --- tools/gimp-plugin/file-formats.h | 1 + tools/gimp-plugin/file-rawtherapee.c | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/tools/gimp-plugin/file-formats.h b/tools/gimp-plugin/file-formats.h index 0cbaea707..f199b0ac0 100644 --- a/tools/gimp-plugin/file-formats.h +++ b/tools/gimp-plugin/file-formats.h @@ -3,6 +3,7 @@ * * 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 diff --git a/tools/gimp-plugin/file-rawtherapee.c b/tools/gimp-plugin/file-rawtherapee.c index 1177cb8be..69259ac1e 100644 --- a/tools/gimp-plugin/file-rawtherapee.c +++ b/tools/gimp-plugin/file-rawtherapee.c @@ -162,7 +162,7 @@ query (void) gimp_register_file_handler_mime (format->load_proc, format->mime_type); -// gimp_register_file_handler_raw (format->load_proc); + gimp_register_file_handler_raw (format->load_proc); gimp_register_magic_load_handler (format->load_proc, format->extensions, "", From 6b28671c4106dcb39f9401121c4c47035fdb78d5 Mon Sep 17 00:00:00 2001 From: Alberto Griggio Date: Mon, 19 Jun 2017 13:49:14 +0200 Subject: [PATCH 3/4] some code style fixes --- rtgui/editorpanel.cc | 2 +- rtgui/editorpanel.h | 2 +- rtgui/filepanel.cc | 1 - rtgui/main.cc | 2 -- rtgui/rtwindow.cc | 3 +-- 5 files changed, 3 insertions(+), 7 deletions(-) diff --git a/rtgui/editorpanel.cc b/rtgui/editorpanel.cc index b9c66f6e0..097ef2806 100644 --- a/rtgui/editorpanel.cc +++ b/rtgui/editorpanel.cc @@ -1893,7 +1893,7 @@ void EditorPanel::sendToGimpPressed () } -bool EditorPanel::saveImmediately(const Glib::ustring &filename, SaveFormat sf) +bool EditorPanel::saveImmediately(const Glib::ustring &filename, const SaveFormat &sf) { rtengine::procparams::ProcParams pparams; ipc->getParams (&pparams); diff --git a/rtgui/editorpanel.h b/rtgui/editorpanel.h index 676395b4a..050909d7d 100644 --- a/rtgui/editorpanel.h +++ b/rtgui/editorpanel.h @@ -131,7 +131,7 @@ public: void defaultMonitorProfileChanged(const Glib::ustring &profile_name, bool auto_monitor_profile); - bool saveImmediately(const Glib::ustring &filename, SaveFormat sf); + bool saveImmediately(const Glib::ustring &filename, const SaveFormat &sf); Gtk::Paned* catalogPane; diff --git a/rtgui/filepanel.cc b/rtgui/filepanel.cc index 035b4e2db..1ac4046b6 100644 --- a/rtgui/filepanel.cc +++ b/rtgui/filepanel.cc @@ -190,7 +190,6 @@ void FilePanel::init () dirBrowser->fillDirTree (); placesBrowser->refreshPlacesList (); - //if (argv1 != "" && Glib::file_test (argv1, Glib::FILE_TEST_IS_DIR)) { if (!argv1.empty() && Glib::file_test (argv1, Glib::FILE_TEST_EXISTS)) { Glib::ustring d(argv1); if (!Glib::file_test(d, Glib::FILE_TEST_IS_DIR)) { diff --git a/rtgui/main.cc b/rtgui/main.cc index e096e23dc..41891b995 100644 --- a/rtgui/main.cc +++ b/rtgui/main.cc @@ -294,8 +294,6 @@ int main(int argc, char **argv) #endif - //simpleEditor = false; - if (!argv1.empty()) { if( Glib::file_test(argv1, Glib::FILE_TEST_EXISTS) && !Glib::file_test(argv1, Glib::FILE_TEST_IS_DIR)) { simpleEditor = true; diff --git a/rtgui/rtwindow.cc b/rtgui/rtwindow.cc index a34843d38..e40d95f15 100644 --- a/rtgui/rtwindow.cc +++ b/rtgui/rtwindow.cc @@ -287,8 +287,7 @@ RTWindow::RTWindow () if (!argv1.empty()) { Thumbnail* thm = cacheMgr->getEntry(argv1); if (thm) { - std::vector entries(1, thm); - fpanel->fileCatalog->openRequested(entries); + fpanel->fileCatalog->openRequested({thm}); } } } From 3bfda08bcf9b923d0fb19d84b4db28a6a3763e56 Mon Sep 17 00:00:00 2001 From: Alberto Griggio Date: Mon, 19 Jun 2017 13:51:37 +0200 Subject: [PATCH 4/4] Gimp plugin: removed magic numbers from the file formats -- we rely only on file extensions --- tools/gimp-plugin/file-formats.h | 17 +++++----------- tools/gimp-plugin/file-rawtherapee.c | 30 ++-------------------------- 2 files changed, 7 insertions(+), 40 deletions(-) diff --git a/tools/gimp-plugin/file-formats.h b/tools/gimp-plugin/file-formats.h index f199b0ac0..b967c7cbe 100644 --- a/tools/gimp-plugin/file-formats.h +++ b/tools/gimp-plugin/file-formats.h @@ -38,20 +38,13 @@ struct _FileFormat #define N_(s) s #define _(s) s -/* some magic numbers taken from - * http://www.garykessler.net/library/file_sigs.html - * - * see also - * http://fileformats.archiveteam.org/wiki/Cameras_and_Digital_Image_Sensors - */ static const FileFormat file_formats[] = { { N_("Raw Canon"), "image/x-canon-cr2,image/x-canon-crw", "cr2,crw", - "0,string,II*\\0\\020\\0\\0\\0CR," /* cr2 */ - "0,string,II\\024\\0\\0\\0HEAPCCDR," /* crw */ + NULL, "file-rawtherapee-canon-load", "Load files in the Canon raw formats via rawtherapee", @@ -204,7 +197,7 @@ static const FileFormat file_formats[] = N_("Raw Olympus ORF"), "image/x-olympus-orf", "orf", - "0,string,IIRO,0,string,MMOR,0,string,IIRS", + NULL, "file-rawtherapee-orf-load", "Load files in the ORF raw format via rawtherapee", @@ -248,7 +241,7 @@ static const FileFormat file_formats[] = N_("Raw Fujifilm RAF"), "image/x-fuji-raf", "raf", - "0,string,FUJIFILMCCD-RAW", + NULL, "file-rawtherapee-raf-load", "Load files in the RAF raw format via rawtherapee", @@ -259,7 +252,7 @@ static const FileFormat file_formats[] = N_("Raw Panasonic"), "image/x-panasonic-raw,image/x-panasonic-rw2", "raw,rw2", - "0,string,IIU\\0", + NULL, "file-rawtherapee-panasonic-load", "Load files in the Panasonic raw formats via rawtherapee", @@ -303,7 +296,7 @@ static const FileFormat file_formats[] = N_("Raw Sigma X3F"), "image/x-sigma-x3f", "x3f", - "0,string,FOVb", + NULL, "file-rawtherapee-x3f-load", "Load files in the X3F raw format via rawtherapee", diff --git a/tools/gimp-plugin/file-rawtherapee.c b/tools/gimp-plugin/file-rawtherapee.c index 69259ac1e..92ce40f9f 100644 --- a/tools/gimp-plugin/file-rawtherapee.c +++ b/tools/gimp-plugin/file-rawtherapee.c @@ -51,8 +51,6 @@ static gint32 load_image (const gchar *filename, static gint32 load_thumbnail_image (const gchar *filename, gint thumb_size, - gint *width, - gint *height, GError **error); const GimpPlugInInfo PLUG_IN_INFO = @@ -89,9 +87,7 @@ query (void) static const GimpParamDef thumb_return_vals[] = { - { GIMP_PDB_IMAGE, "image", "Thumbnail image" }, - { GIMP_PDB_INT32, "image-width", "Width of full-sized image" }, - { GIMP_PDB_INT32, "image-height", "Height of full-sized image" } + { GIMP_PDB_IMAGE, "image", "Thumbnail image" } }; /* check if rawtherapee is installed @@ -220,24 +216,15 @@ run (const gchar *name, } else if (! strcmp (name, LOAD_THUMB_PROC)) { - gint width = 0; - gint height = 0; - image_ID = load_thumbnail_image (param[0].data.d_string, param[1].data.d_int32, - &width, - &height, &error); if (image_ID != -1) { - *nreturn_vals = 6; + *nreturn_vals = 4; values[1].type = GIMP_PDB_IMAGE; values[1].data.d_image = image_ID; - values[2].type = GIMP_PDB_INT32; - values[2].data.d_int32 = width; - values[3].type = GIMP_PDB_INT32; - values[3].data.d_int32 = height; values[4].type = GIMP_PDB_INT32; values[4].data.d_int32 = GIMP_RGB_IMAGE; values[5].type = GIMP_PDB_INT32; @@ -320,8 +307,6 @@ load_image (const gchar *filename, static gint32 load_thumbnail_image (const gchar *filename, gint thumb_size, - gint *width, - gint *height, GError **error) { gint32 image_ID = -1; @@ -400,8 +385,6 @@ load_thumbnail_image (const gchar *filename, gimp_progress_init_printf (_("Opening thumbnail for '%s'"), gimp_filename_to_utf8 (filename)); - *width = *height = thumb_size; - if (thumb_pp3_f && g_spawn_sync (NULL, argv, @@ -422,15 +405,6 @@ load_thumbnail_image (const gchar *filename, filename_out); if (image_ID != -1) { - /* /\* the size reported by raw files isn't precise, */ - /* * but it should be close enough to get an idea. */ - /* *\/ */ - /* gchar *start_of_size = g_strstr_len (rawtherapee_stdout, */ - /* -1, */ - /* "[dt4gimp]"); */ - /* if (start_of_size) */ - /* sscanf (start_of_size, "[dt4gimp] %d %d", width, height); */ - /* is this needed for thumbnails? */ gimp_image_set_filename (image_ID, filename); }