diff options
Diffstat (limited to 'graphics/dcraw/rawphoto.c')
-rw-r--r-- | graphics/dcraw/rawphoto.c | 355 |
1 files changed, 355 insertions, 0 deletions
diff --git a/graphics/dcraw/rawphoto.c b/graphics/dcraw/rawphoto.c new file mode 100644 index 0000000000..753e167bdf --- /dev/null +++ b/graphics/dcraw/rawphoto.c @@ -0,0 +1,355 @@ +/* + Raw photo loader plugin for The GIMP + by Dave Coffin at cybercom dot net, user dcoffin + http://www.cybercom.net/~dcoffin/ + + $Revision: 1.30 $ + $Date: 2007/04/28 23:46:57 $ + + This code is licensed under the same terms as The GIMP. + To simplify maintenance, it calls my command-line "dcraw" + program to do the actual decoding. + + To install locally: + gimptool --install rawphoto.c + + To install globally: + gimptool --install-admin rawphoto.c + + To build without installing: + gcc -o rawphoto rawphoto.c `gtk-config --cflags --libs` -lgimp -lgimpui + */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include <gtk/gtk.h> + +#include <libgimp/gimp.h> +#include <libgimp/gimpui.h> + +#if GIMP_CHECK_VERSION(1,3,2) +#define GimpRunModeType GimpRunMode +#endif + +#if GIMP_CHECK_VERSION(1,3,17) +#define RAWPHOTO_CONST const +#else +#define RAWPHOTO_CONST +#endif + +#include <locale.h> +#include <libintl.h> +#define _(String) gettext(String) + +#define PLUG_IN_VERSION "1.1.18 - 28 April 2007" + +static void query(void); +static void run(RAWPHOTO_CONST gchar *name, + gint nparams, + RAWPHOTO_CONST GimpParam *param, + gint *nreturn_vals, + GimpParam **return_vals); + +static gint load_dialog (gchar *name); +static gint32 load_image (gchar *filename); + +GimpPlugInInfo PLUG_IN_INFO = +{ + NULL, /* init_procedure */ + NULL, /* quit_procedure */ + query, /* query_procedure */ + run, /* run_procedure */ +}; + +static struct { + gboolean check_val[6]; + gfloat spin_val[2]; +} cfg = { + { FALSE, FALSE, FALSE, FALSE, FALSE, FALSE }, + { 1, 0 } +}; + +MAIN () + +static void query (void) +{ + static GimpParamDef load_args[] = + { + { GIMP_PDB_INT32, "run_mode", "Interactive, non-interactive" }, + { GIMP_PDB_STRING, "filename", "The name of the file to load" }, + { GIMP_PDB_STRING, "raw_filename", "The name of the file to load" }, + }; + static GimpParamDef load_return_vals[] = + { + { GIMP_PDB_IMAGE, "image", "Output image" }, + }; + + static gint num_load_args = + sizeof load_args / sizeof load_args[0]; + static gint num_load_return_vals = + sizeof load_return_vals / sizeof load_return_vals[0]; + + gimp_install_procedure ("file_rawphoto_load", + "Loads raw digital camera files", + "This plug-in loads raw digital camera files.", + "Dave Coffin at cybercom dot net, user dcoffin", + "Copyright 2003-2007 by Dave Coffin", + PLUG_IN_VERSION, + "<Load>/rawphoto", + NULL, + GIMP_PLUGIN, + num_load_args, + num_load_return_vals, + load_args, + load_return_vals); + + gimp_register_load_handler ("file_rawphoto_load", + "arw,bay,bmq,cr2,crw,cs1,dc2,dcr,dng,erf,fff,hdr,ia,jpg,k25,kc2,kdc,mdc,mef,mos,mrw,nef,orf,pef,pxn,qtk,raf,raw,rdc,sr2,srf,sti,tif,x3f", ""); +} + +static void run (RAWPHOTO_CONST gchar *name, + gint nparams, + RAWPHOTO_CONST GimpParam *param, + gint *nreturn_vals, + GimpParam **return_vals) +{ + static GimpParam values[2]; + GimpRunModeType run_mode; + GimpPDBStatusType status; + gint32 image_id = -1; + gchar *command, *fname; + int stat; + + *nreturn_vals = 1; + *return_vals = values; + + status = GIMP_PDB_CALLING_ERROR; + if (strcmp (name, "file_rawphoto_load")) goto done; + + status = GIMP_PDB_EXECUTION_ERROR; + fname = param[1].data.d_string; + command = g_malloc (strlen(fname)+20); + if (!command) goto done; +/* + Is the file really a raw photo? If not, try loading it + as a regular JPEG or TIFF. + */ + sprintf (command, "dcraw -i '%s'\n",fname); + fputs (command, stderr); + stat = system (command); + g_free (command); + if (stat) { + if (stat > 0x200) + g_message (_("The \"rawphoto\" plugin won't work because " + "there is no \"dcraw\" executable in your path.")); + if (!strcasecmp (fname + strlen(fname) - 4, ".jpg")) + *return_vals = gimp_run_procedure2 + ("file_jpeg_load", nreturn_vals, nparams, param); + else + *return_vals = gimp_run_procedure2 + ("file_tiff_load", nreturn_vals, nparams, param); + return; + } + gimp_get_data ("plug_in_rawphoto", &cfg); + status = GIMP_PDB_CANCEL; + run_mode = param[0].data.d_int32; + if (run_mode == GIMP_RUN_INTERACTIVE) + if (!load_dialog (param[1].data.d_string)) goto done; + + status = GIMP_PDB_EXECUTION_ERROR; + image_id = load_image (param[1].data.d_string); + if (image_id == -1) goto done; + + *nreturn_vals = 2; + values[1].type = GIMP_PDB_IMAGE; + values[1].data.d_image = image_id; + status = GIMP_PDB_SUCCESS; + gimp_set_data ("plug_in_rawphoto", &cfg, sizeof cfg); + +done: + values[0].type = GIMP_PDB_STATUS; + values[0].data.d_status = status; +} + +static gint32 load_image (gchar *filename) +{ + int tile_height, depth, width, height, row, nrows; + FILE *pfp; + gint32 image, layer; + GimpDrawable *drawable; + GimpPixelRgn pixel_region; + guchar *pixel; + char *command, nl; + + setlocale (LC_NUMERIC, "C"); + command = g_malloc (strlen(filename)+100); + if (!command) return -1; + sprintf (command, + "dcraw -c%s%s%s%s%s%s -b %0.2f -H %d '%s'\n", + cfg.check_val[0] ? " -q 0":"", + cfg.check_val[1] ? " -h":"", + cfg.check_val[2] ? " -f":"", + cfg.check_val[3] ? " -d":"", + cfg.check_val[4] ? " -a":"", + cfg.check_val[5] ? " -w":"", + cfg.spin_val[0], (int) cfg.spin_val[1], + filename ); + fputs (command, stderr); + pfp = popen (command, "r"); + g_free (command); + if (!pfp) { + perror ("dcraw"); + return -1; + } + + if (fscanf (pfp, "P%d %d %d 255%c", &depth, &width, &height, &nl) != 4 + || (depth-5)/2 ) { + pclose (pfp); + g_message ("Not a raw digital camera image.\n"); + return -1; + } + + depth = depth*2 - 9; + image = gimp_image_new (width, height, depth == 3 ? GIMP_RGB : GIMP_GRAY); + if (image == -1) { + pclose (pfp); + g_message ("Can't allocate new image.\n"); + return -1; + } + + gimp_image_set_filename (image, filename); + + /* Create the "background" layer to hold the image... */ + layer = gimp_layer_new (image, "Background", width, height, + depth == 3 ? GIMP_RGB_IMAGE : GIMP_GRAY_IMAGE, + 100, GIMP_NORMAL_MODE); + gimp_image_add_layer (image, layer, 0); + + /* Get the drawable and set the pixel region for our load... */ + drawable = gimp_drawable_get (layer); + gimp_pixel_rgn_init (&pixel_region, drawable, 0, 0, drawable->width, + drawable->height, TRUE, FALSE); + + /* Temporary buffers... */ + tile_height = gimp_tile_height(); + pixel = g_new (guchar, tile_height * width * depth); + + /* Load the image... */ + for (row = 0; row < height; row += tile_height) { + nrows = height - row; + if (nrows > tile_height) + nrows = tile_height; + fread (pixel, width * depth, nrows, pfp); + gimp_pixel_rgn_set_rect (&pixel_region, pixel, 0, row, width, nrows); + } + + pclose (pfp); + g_free (pixel); + + gimp_drawable_flush (drawable); + gimp_drawable_detach (drawable); + + return image; +} + +#if !GIMP_CHECK_VERSION(1,3,23) +/* this is set to true after OK click in any dialog */ +gboolean result = FALSE; + +static void callback_ok (GtkWidget * widget, gpointer data) +{ + result = TRUE; + gtk_widget_destroy (GTK_WIDGET (data)); +} +#endif + +#define NCHECK (sizeof cfg.check_val / sizeof (gboolean)) + +gint load_dialog (gchar * name) +{ + GtkWidget *dialog; + GtkWidget *table; + GtkObject *adj; + GtkWidget *widget; + int i; + static const char *label[9] = + { "Quick interpolation", "Half-size interpolation", + "Four color interpolation", "Grayscale document", + "Automatic white balance", "Camera white balance", + "Brightness", "Highlight mode" }; + + gimp_ui_init ("rawphoto", TRUE); + + dialog = gimp_dialog_new (_("Raw Photo Loader " PLUG_IN_VERSION), "rawphoto", +#if !GIMP_CHECK_VERSION(1,3,23) + gimp_standard_help_func, "rawphoto", + GTK_WIN_POS_MOUSE, + FALSE, TRUE, FALSE, + _("OK"), callback_ok, NULL, NULL, NULL, TRUE, + FALSE, _("Cancel"), gtk_widget_destroy, NULL, + 1, NULL, FALSE, TRUE, NULL); + gtk_signal_connect + (GTK_OBJECT(dialog), "destroy", GTK_SIGNAL_FUNC(gtk_main_quit), NULL); +#else + NULL, 0, + gimp_standard_help_func, "rawphoto", + GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, + GTK_STOCK_OK, GTK_RESPONSE_OK, + NULL); +#endif + + table = gtk_table_new (9, 2, FALSE); + gtk_container_set_border_width (GTK_CONTAINER(table), 6); + gtk_box_pack_start + (GTK_BOX(GTK_DIALOG(dialog)->vbox), table, FALSE, FALSE, 0); + gtk_widget_show (table); + + for (i=0; i < NCHECK; i++) { + widget = gtk_check_button_new_with_label + (_(label[i])); + gtk_toggle_button_set_active + (GTK_TOGGLE_BUTTON (widget), cfg.check_val[i]); + gtk_table_attach + (GTK_TABLE(table), widget, 0, 2, i, i+1, GTK_FILL, GTK_FILL, 0, 0); + gtk_signal_connect (GTK_OBJECT (widget), "toggled", + GTK_SIGNAL_FUNC (gimp_toggle_button_update), + &cfg.check_val[i]); + gtk_widget_show (widget); + } + + for (i=NCHECK; i < NCHECK+2; i++) { + widget = gtk_label_new (_(label[i])); + gtk_misc_set_alignment (GTK_MISC (widget), 1.0, 0.5); + gtk_misc_set_padding (GTK_MISC (widget), 10, 0); + gtk_table_attach + (GTK_TABLE(table), widget, 0, 1, i, i+1, GTK_FILL, GTK_FILL, 0, 0); + gtk_widget_show (widget); + if (i == NCHECK+1) + widget = gimp_spin_button_new + (&adj, cfg.spin_val[i-NCHECK], 0, 9, 1, 9, 1, 1, 0); + else + widget = gimp_spin_button_new + (&adj, cfg.spin_val[i-NCHECK], 0.01, 4.0, 0.01, 0.1, 0.1, 0.1, 2); + gtk_table_attach + (GTK_TABLE(table), widget, 1, 2, i, i+1, GTK_FILL, GTK_FILL, 0, 0); + gtk_signal_connect (GTK_OBJECT (adj), "value_changed", + GTK_SIGNAL_FUNC (gimp_float_adjustment_update), + &cfg.spin_val[i-NCHECK]); + gtk_widget_show (widget); + } + + gtk_widget_show (dialog); + +#if !GIMP_CHECK_VERSION(1,3,23) + gtk_main(); + gdk_flush(); + + return result; +#else + i = gimp_dialog_run (GIMP_DIALOG (dialog)); + gtk_widget_destroy (dialog); + return i == GTK_RESPONSE_OK; +#endif +} |