[CinePaint] rawphoto plugin and newer dcraw

[email protected]
Newsgroups gmane.comp.video.cinepaint.user
Message-ID <[email protected]>
I have recently been recompiling a lot of packages for one of the computers at 
home and discovered that the rawphoto plugin was broken in my fresh 
installation of Cinepaint-0.21. After a little digging the culprit turned out 
to be dcraw, which has changed command line options for color balance. 
Specifically, rather than using -r -l -b -k those options are now rolled into 
one, so you now need to pass the program -r followed by four values. I'm not 
sure when Dave Coffin made this change but my old dcraw binary (7.94) is 
still command line compatible with the cinepaint plugin.

The easy answer would be to just use the old version of dcraw, but with added 
support for newer model cameras and the ability to output in TIFF format 
running a newer version is pretty desireable now. I've attached my dirty hack 
to get it working, problem is that this version won't be compatible with 
older versions of dcraw.

Nathan

-------------------------------------------------------------------------
Using Tomcat but need to do more? Need to support web services, security?
Get stuff done quickly with pre-integrated technology to make your job easier
Download IBM WebSphere Application Server v.1.0.1 based on Apache Geronimo
http://sel.as-us.falkag.net/sel?cmd=lnk&kid=120709&bid=263057&dat=121642

_______________________________________________
Cinepaint-users mailing list
Cinepaint-users-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f@public.gmane.org
https://lists.sourceforge.net/lists/listinfo/cinepaint-users
rawphoto.c (text/x-csrc, 10.7 KB)
/*
   Raw photo loader plugin for The GIMP
   by Dave Coffin at cybercom dot net, user dcoffin
   http://www.cybercom.net/~dcoffin/

   $Revision: 1.6 $
   $Date: 2006/04/06 11:12:36 $

   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 <math.h>

#include <gtk/gtk.h>

#ifdef GIMP_VERSION
#error "NOT HERE"
#else
#include <lib/plugin_main.h>
#include <lib/ui.h>
#include <libgimp/stdplugins-intl.h>
#include <lib/dialog.h>
#include <lib/widgets.h>
#endif

#define PLUG_IN_VERSION  "1.1.5-cp-0.1 - 19 April 2004 (cp 10.Mai 2004)"

static void query(void);
static void run(gchar *name,
		gint nparams,
		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[7];
  gfloat    spin_val[4];
  int      used_bits;
  gchar  i_profile[1024];         /* input profile */
  gchar  o_profile[1024];         /* output profile */
} cfg = {
  { FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, FALSE },
  { 2.2, 1.0, 1.0, 1.0 },
  16
};

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 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",
    "bay,bmq,cr2,crw,cs1,dc2,dcr,dng,fff,jpg,k25,kdc,mos,mrw,nef,orf,pef,raf,raw,rdc,srf,sti,tif,tiff,x3f", "");
}

static void run (gchar *name,
		gint nparams,
		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;

  INIT_I18N_UI();

  *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;
}

#define byteswap(c) do { t=(c)[0]; (c)[0]=(c)[1]; (c)[1]=t; } while(0)

static gint32 load_image (gchar *filename)
{
  int		tile_height, width, height, row, nrows, depth;
  int           bpp_gimp, bpp_ppm, px;
  FILE		*pfp;
  gint32	image, layer;
  GimpDrawable	*drawable;
  GimpPixelRgn	pixel_region;
  guchar	*pixel;
  char		*command, nl;
  guchar        t;
  guint16       *val;

  /*setlocale (LC_NUMERIC, "C");*/
  command = g_malloc (strlen(filename)+100);
  if (!command) return -1;
  /* gamma now is handled internally - Kai-Uwe */
  sprintf (command,
	"dcraw -4 -v -c%s%s%s%s%s%s%s "/*-g %0.2f*/ "-b %0.2f -r %0.2f %0.2f %0.2f %0.2f '%s'\n",
	cfg.check_val[0] ? " -q 0 -n":"",
	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.check_val[6] ? "":" -m",
	/*cfg.spin_val[0],*/ cfg.spin_val[1], cfg.spin_val[2], cfg.spin_val[3],
	filename );
  fputs (command, stderr);

  pfp = popen (command, "r");
  g_free (command);
  if (!pfp) {
    perror ("dcraw");
    return -1;
  }

  if (fscanf (pfp, "P6 %d %d %d%c", &width, &height, &depth, &nl) != 4) {
    pclose (pfp);
    g_message ("Not a raw digital camera image.%d %d %d %d\n",width,height,depth,nl);
    return -1;
  }

  if(depth < 256) { bpp_ppm = 3; } else { bpp_ppm = 6; }

  image = gimp_image_new (width, height, bpp_ppm == 3 ? RGB : U16_RGB);
  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,
			  bpp_ppm == 3 ? RGB_IMAGE : U16_RGB_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);
  bpp_gimp = pixel_region.bpp;

  if(bpp_gimp != bpp_ppm) {
    pclose (pfp);
    g_message ("Wrong depth for new image.\n");
    return -1;
  }

  /* Temporary buffers... */
  tile_height = get_lib_tile_height();
  pixel = g_new (guchar, tile_height * width * bpp_gimp);

  /* Load the image... */
  for (row = 0; row < height; row += tile_height) {
    nrows = height - row;
    if (nrows > tile_height)
	nrows = tile_height;
    fread (pixel, width * bpp_ppm, nrows, pfp);
    if(bpp_ppm == 6) for(px = 0; px < width * nrows * 3; px++) {
#if G_BYTE_ORDER == G_LITTLE_ENDIAN
	byteswap(pixel + 2*px);
#endif
        /* changed brightness / gamma handling - Kai-Uwe */
        val = ((guint16*) &(pixel [2*px]));
        /* doing an simple bitshift here is is better undoable */
        if (cfg.used_bits < 16)
          *val = *val << (16 - cfg.used_bits);
        /* gamma */
        *val = pow ((float)*val/65535.0, 1.0/cfg.spin_val[0]) * 65535.0;
    }
    printf (".");
    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;
}

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

#define NCHECK (sizeof cfg.check_val / sizeof (gboolean))

#include <gdk/gdkkeysyms.h>

gint load_dialog (gchar * name)
{
  GtkWidget *dialog;
  GtkWidget *table;
  GtkObject *adj;
  GtkWidget *widget;
  int i;
  static const char *label[11];

  label[0] = _("Quick interpolation");
  label[1] = _("Half-size interpolation");
  label[2] = _("Four color interpolation");
  label[3] = _("Grayscale document");
  label[4] = _("Automatic white balance");
  label[5] = _("Camera white balance");
  label[6] = _("Convert to sRGB");
  label[7] = _("Gamma");
  label[8] = _("Brightness");
  label[9] = _("Red Multiplier");
  label[10] = _("Blue Multiplier");


  if (!strcasecmp (name + strlen(name) - 4, ".dng"))
    cfg.used_bits = 16;

  gimp_ui_init ("rawphoto", TRUE);

  dialog = gimp_dialog_new (_("Raw Photo Loader 1.0"), "rawphoto",
			gimp_standard_help_func, "",
			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);

  table = gtk_table_new (8, 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);
  }
# if 0
  for (i=NCHECK; i < NCHECK+4; 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);
    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);
  }

  /* look in lib/widgets.h Kai-Uwe */
  adj = gimp_scale_entry_new (GTK_TABLE (table), 0, 11,
                              _("bit depth:"), 100, 0,
                              cfg.used_bits, 8, 16, 1, 1, 0,
                              TRUE, 0, 0,
                              NULL, NULL);
  gtk_signal_connect (GTK_OBJECT (adj), "value_changed",
                      GTK_SIGNAL_FUNC (gimp_int_adjustment_update),
                      &cfg.used_bits);
# endif


  gtk_widget_show (dialog);

  gtk_main();
  gdk_flush();

  return result;
}
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.