Update of /cvsroot/ufraw/ufraw
In directory ddv4jf1.ch3.sourceforge.com:/tmp/cvs-serv7805

Modified Files:
        ufraw.h ufraw_conf.c ufraw_preview.c ufraw_ufraw.c ufraw_ui.h 
Log Message:
Added a despeckling/denoising algorithm to solve issues with
images taken under very difficult lighting conditions, like deep sea diving.
It may be useful in other situations too.
Patch by Frank van Maarseveen.


Index: ufraw.h
===================================================================
RCS file: /cvsroot/ufraw/ufraw/ufraw.h,v
retrieving revision 1.134
retrieving revision 1.135
diff -u -d -r1.134 -r1.135
--- ufraw.h     8 Nov 2009 02:22:30 -0000       1.134
+++ ufraw.h     10 Nov 2009 03:33:55 -0000      1.135
@@ -194,6 +194,9 @@
     lightness_adjustment lightnessAdjustment[max_adjustments];
     int grayscaleMode;
     double grayscaleMixer[3];
+    double despeckleWindow[3];
+    double despeckleDecay[3];
+    double despecklePasses[3];
 
     /* SAVE options */
     char inputFilename[max_path], outputFilename[max_path],
@@ -292,6 +295,7 @@
     int hotpixels;
     gboolean mark_hotpixels;
     unsigned raw_multiplier;
+    int channel_select;
 } ufraw_data;
 
 extern const conf_data conf_default;
@@ -331,6 +335,7 @@
 void ufraw_invalidate_hotpixel_layer(ufraw_data *uf);
 void ufraw_invalidate_denoise_layer(ufraw_data *uf);
 void ufraw_invalidate_darkframe_layer(ufraw_data *uf);
+void ufraw_invalidate_despeckle_layer(ufraw_data *uf);
 void ufraw_invalidate_whitebalance_layer(ufraw_data *uf);
 void ufraw_invalidate_smoothing_layer(ufraw_data *uf);
 gboolean ufraw_invalidate_layer_event(ufraw_data *uf, UFRawPhase phase);

Index: ufraw_ui.h
===================================================================
RCS file: /cvsroot/ufraw/ufraw/ufraw_ui.h,v
retrieving revision 1.29
retrieving revision 1.30
diff -u -d -r1.29 -r1.30
--- ufraw_ui.h  6 Nov 2009 06:42:03 -0000       1.29
+++ ufraw_ui.h  10 Nov 2009 03:33:55 -0000      1.30
@@ -71,6 +71,7 @@
     GtkWidget *ResetContrastButton;
     GtkWidget *ResetBlackButton, *ResetBaseCurveButton, *ResetCurveButton;
     GtkWidget *ResetGrayscaleChannelMixerButton;
+    GtkWidget *ResetDespeckleButton;
     GtkWidget *SaveButton;
     GtkWidget *ControlButton[num_buttons];
     guint16 ButtonMnemonic[num_buttons];
@@ -111,6 +112,11 @@
     GtkAdjustment *RotationAdjustment;
     GtkWidget *ResetRotationAdjustment;
     GtkAdjustment *GrayscaleMixers[3];
+    GtkAdjustment *DespeckleWindowAdj[3];
+    GtkAdjustment *DespeckleDecayAdj[3];
+    GtkAdjustment *DespecklePassesAdj[3];
+    GtkToggleButton *DespeckleLockChannelsButton;
+    GtkToggleButton *ChannelSelectButton[3];
 #ifdef HAVE_LENSFUN
     /* The GtkEntry with camera maker/model name */
     GtkWidget *CameraModel;

Index: ufraw_conf.c
===================================================================
RCS file: /cvsroot/ufraw/ufraw/ufraw_conf.c,v
retrieving revision 1.152
retrieving revision 1.153
diff -u -d -r1.152 -r1.153
--- ufraw_conf.c        3 Nov 2009 07:10:08 -0000       1.152
+++ ufraw_conf.c        10 Nov 2009 03:33:55 -0000      1.153
@@ -87,6 +87,9 @@
     }, /* lightness adjustments */
     grayscale_none, /* grayscale mode */
     { 1.0, 1.0, 1.0 }, /* grayscale mixer */
+    { 0.0, 0.0, 0.0 }, /* despeckle window */
+    { 0.0, 0.0, 0.0 }, /* despeckle color decay */
+    { 1.0, 1.0, 1.0 }, /* despeckle passes */
     /* Save options */
     "", "", "", /* inputFilename, outputFilename, outputPath */
     "", "", /* inputURI, inputModTime */
@@ -670,6 +673,18 @@
         sscanf(temp, "%lf %lf %lf", &c->grayscaleMixer[0],
               &c->grayscaleMixer[1], &c->grayscaleMixer[2]);
     }
+    if ( strcmp("DespeckleWindow", element)==0 ) {
+        sscanf(temp, "%lf %lf %lf", &c->despeckleWindow[0],
+              &c->despeckleWindow[1], &c->despeckleWindow[2]);
+    }
+    if ( strcmp("DespeckleDecay", element)==0 ) {
+        sscanf(temp, "%lf %lf %lf", &c->despeckleDecay[0],
+              &c->despeckleDecay[1], &c->despeckleDecay[2]);
+    }
+    if ( strcmp("DespecklePasses", element)==0 ) {
+        sscanf(temp, "%lf %lf %lf", &c->despecklePasses[0],
+              &c->despecklePasses[1], &c->despecklePasses[2]);
+    }
     /* OutputIntent replaces Intent starting from ufraw-0.12. */
     if ( strcmp("OutputIntent", element)==0 )
        c->intent[out_profile] = conf_find_name(temp, intentNames,
@@ -972,6 +987,24 @@
                c->grayscaleMixer[1],
                c->grayscaleMixer[2]);
     }
+    if (c->despeckleWindow[0] != conf_default.despeckleWindow[0] ||
+        c->despeckleWindow[1] != conf_default.despeckleWindow[1] ||
+        c->despeckleWindow[2] != conf_default.despeckleWindow[2]) {
+       buf = uf_markup_buf(buf, "<DespeckleWindow>%f %f 
%f</DespeckleWindow>\n",
+               c->despeckleWindow[0], c->despeckleWindow[1], 
c->despeckleWindow[2]);
+    }
+    if (c->despeckleDecay[0] != conf_default.despeckleDecay[0] ||
+        c->despeckleDecay[1] != conf_default.despeckleDecay[1] ||
+        c->despeckleDecay[2] != conf_default.despeckleDecay[2]) {
+       buf = uf_markup_buf(buf, "<DespeckleDecay>%f %f %f</DespeckleDecay>\n",
+               c->despeckleDecay[0], c->despeckleDecay[1], 
c->despeckleDecay[2]);
+    }
+    if (c->despecklePasses[0] != conf_default.despecklePasses[0] ||
+        c->despecklePasses[1] != conf_default.despecklePasses[1] ||
+        c->despecklePasses[2] != conf_default.despecklePasses[2]) {
+       buf = uf_markup_buf(buf, "<DespecklePasses>%f %f 
%f</DespecklePasses>\n",
+               c->despecklePasses[0], c->despecklePasses[1], 
c->despecklePasses[2]);
+    }
     if (c->size!=conf_default.size)
        buf = uf_markup_buf(buf, "<Size>%d</Size>\n", c->size);
     if (c->shrink!=conf_default.shrink)
@@ -1216,6 +1249,9 @@
     dst->grayscaleMode = src->grayscaleMode;
     memcpy(dst->grayscaleMixer, src->grayscaleMixer,
           sizeof dst->grayscaleMixer);
+    memcpy(dst->despeckleWindow, src->despeckleWindow, sizeof 
(dst->despeckleWindow));
+    memcpy(dst->despeckleDecay, src->despeckleDecay, sizeof 
(dst->despeckleDecay));
+    memcpy(dst->despecklePasses, src->despecklePasses, sizeof 
(dst->despecklePasses));
     g_strlcpy(dst->darkframeFile, src->darkframeFile, max_path);
     /* We only copy the current BaseCurve */
     if (src->BaseCurveIndex<=camera_curve) {

Index: ufraw_ufraw.c
===================================================================
RCS file: /cvsroot/ufraw/ufraw/ufraw_ufraw.c,v
retrieving revision 1.211
retrieving revision 1.212
diff -u -d -r1.211 -r1.212
--- ufraw_ufraw.c       8 Nov 2009 02:22:30 -0000       1.211
+++ ufraw_ufraw.c       10 Nov 2009 03:33:55 -0000      1.212
@@ -251,6 +251,7 @@
     uf->modifier = NULL;
     uf->lanczos_func = NULL;
 #endif
+    uf->channel_select = -1;
     ufraw_message(UFRAW_SET_LOG, "ufraw_open: w:%d h:%d curvesize:%d\n",
            raw->width, raw->height, raw->toneCurveSize);
 
@@ -734,6 +735,7 @@
 int ufraw_convert_image(ufraw_data *uf)
 {
     uf->mark_hotpixels = FALSE;
+    uf->channel_select = -1;
     ufraw_developer_prepare(uf, file_developer);
     ufraw_convert_image_raw(uf, ufraw_raw_phase);
     ufraw_convert_image_first(uf, ufraw_first_phase);
@@ -977,6 +979,117 @@
     uf->hotpixels = count;
 }
 
+static void ufraw_despeckle_line(guint16 *base, int step, int size, int window,
+       double decay, int colors, int c)
+{
+    unsigned lum[size];
+    int i, j, start, end, next, v, cold, hot, coldj, hotj, fix;
+    guint16 *p;
+
+    if (colors == 4) {
+       for (i = 0; i < size; ++i) {
+           p = base + i * step;
+           lum[i] = (p[0] + p[1] + p[2] + p[3] - p[c]) / 3;
+       }
+    } else {
+       for (i = 0; i < size; ++i) {
+           p = base + i * step;
+           lum[i] = (p[0] + p[1] + p[2] - p[c]) / 2;
+       }
+    }
+    p = base + c;
+    for (i = 1 - window; i < size; i = next) {
+       start = i;
+       end = i + window;
+       if (start < 0)
+           start = 0;
+       if (end > size)
+           end = size;
+       cold = hot = p[start * step] - lum[start];
+       coldj = hotj = start;
+       for (j = start + 1; j < end; ++j) {
+           v = p[j * step] - lum[j];
+           if (v < cold) {
+               cold = v;
+               coldj = j;
+           }
+           else if (v > hot) {
+               hot = v;
+               hotj = j;
+           }
+       }
+       if (cold < 0 && hot > 0) {
+           fix = -cold;
+           if (fix > hot)
+               fix = hot;
+           p[coldj * step] += fix;
+           p[hotj * step] -= fix;
+           hot -= fix;
+       }
+       if (hot > 0 && decay)
+           p[hotj * step] -= hot * decay;
+       next = coldj < hotj ? coldj : hotj;
+       if (next == start)
+           ++next;
+    }
+}
+
+void ufraw_despeckle(ufraw_data *uf, UFRawPhase phase)
+{
+    ufraw_image_data *img = &uf->Images[phase];
+    const int depth = img->depth / 2, rowstride = img->rowstride / 2;
+    int passes[4], pass, maxpass;
+    int win[4], i, c, colors;
+    guint16 *base;
+    double decay[4];
+
+    ufraw_image_format(&colors, NULL, img, "68", G_STRFUNC);
+    maxpass = 0;
+    for (c = 0; c < colors; ++c) {
+       win[c] = uf->conf->despeckleWindow[c < 3 ? c : 1] + 0.01;
+       decay[c] = uf->conf->despeckleDecay[c < 3 ? c : 1];
+       passes[c] = uf->conf->despecklePasses[c < 3 ? c : 1] + 0.01;
+       if (!win[c])
+           passes[c] = 0;
+       if (passes[c] > maxpass)
+           maxpass = passes[c];
+    }
+    for (pass = maxpass - 1; pass >= 0; --pass) {
+       for (c = 0; c < colors; ++c) {
+           if (pass >= passes[c])
+               continue;
+#ifdef _OPENMP
+#pragma omp parallel for default(shared) private(i,base)
+#endif
+           for (i = 0; i < img->height; ++i) {
+               base = (guint16 *)img->buffer + i * rowstride;
+               ufraw_despeckle_line(base, depth, img->width, win[c],
+                       decay[c], colors, c);
+           }
+#ifdef _OPENMP
+#pragma omp parallel for default(shared) private(i,base)
+#endif
+           for (i = 0; i < img->width; ++i) {
+               base = (guint16 *)img->buffer + i * depth;
+               ufraw_despeckle_line(base, rowstride, img->height, win[c],
+                       decay[c], colors, c);
+           }
+       }
+    }
+}
+
+static gboolean ufraw_despeckle_active(ufraw_data *uf)
+{
+    int i;
+    gboolean active = FALSE;
+
+    for (i = 0; i < 3; ++i) {
+       if (uf->conf->despeckleWindow[i] && uf->conf->despecklePasses[i])
+           active = TRUE;
+    }
+    return active;
+}
+
 static void ufraw_convertshrink(ufraw_data *uf, dcraw_image_data *final, 
dcraw_data *raw)
 {
     int scale = 1;
@@ -1048,6 +1161,7 @@
     dcraw_wavelet_denoise(raw, uf->conf->threshold * sqrt(uf->raw_multiplier));
     dcraw_finalize_raw(raw, dark, uf->developer->rgbWB);
     raw->raw.image = rawimage;
+    ufraw_despeckle(uf, phase);
 }
 
 /*
@@ -1473,6 +1587,14 @@
             for (yy = 0; yy < area.height; yy++, dest += out->rowstride,
                                src += in->rowstride) {
                 develop(dest, (void *)src, uf->developer, 8, area.width);
+               if (uf->channel_select >= 0) {
+                   int xx;
+                   guint8 *p = dest;
+                   for (xx = 0; xx < area.width; xx++, p += out->depth) {
+                       guint8 px = p[uf->channel_select];
+                       p[0] = p[1] = p[2] = px;
+                   }
+               }
             }
             break;
 
@@ -1666,6 +1788,11 @@
     ufraw_invalidate_layer(uf, ufraw_raw_phase);
 }
 
+void ufraw_invalidate_despeckle_layer(ufraw_data *uf)
+{
+    ufraw_invalidate_layer(uf, ufraw_raw_phase);
+}
+
 /*
  * This one is special. The raw layer applies WB in preparation for optimal
  * interpolation but the first layer undoes it for develop() et.al. So, the
@@ -1679,6 +1806,9 @@
        uf->Images[ufraw_raw_phase].valid = 0;
        uf->Images[ufraw_raw_phase].invalidate_event = TRUE;
 //    }
+    /* Despeckling is sensitive for WB changes because it is nonlinear. */
+    if (ufraw_despeckle_active(uf))
+       ufraw_invalidate_despeckle_layer(uf);
 }
 
 /*

Index: ufraw_preview.c
===================================================================
RCS file: /cvsroot/ufraw/ufraw/ufraw_preview.c,v
retrieving revision 1.301
retrieving revision 1.302
diff -u -d -r1.301 -r1.302
--- ufraw_preview.c     8 Nov 2009 01:27:54 -0000       1.301
+++ ufraw_preview.c     10 Nov 2009 03:33:55 -0000      1.302
@@ -1366,6 +1366,7 @@
 }
 
 static void update_shrink_ranges(preview_data *data);
+static void despeckle_update_sensitive(preview_data *data);
 
 /* update the UI entries that could have changed automatically */
 static void update_scales(preview_data *data)
@@ -1453,6 +1454,14 @@
     for (i = 0; i < 3; ++i)
         gtk_adjustment_set_value(data->GrayscaleMixers[i],
                CFG->grayscaleMixer[i]);
+    for (i = 0; i < 3; ++i) {
+        gtk_adjustment_set_value(data->DespeckleWindowAdj[i],
+               CFG->despeckleWindow[i]);
+        gtk_adjustment_set_value(data->DespeckleDecayAdj[i],
+               CFG->despeckleDecay[i]);
+        gtk_adjustment_set_value(data->DespecklePassesAdj[i],
+               CFG->despecklePasses[i]);
+    }
     for (i = 0; i < CFG->lightnessAdjustmentCount; ++i) {
        gtk_adjustment_set_value(data->LightnessAdjustment[i],
            CFG->lightnessAdjustment[i].adjustment);
@@ -1465,6 +1474,7 @@
        || (CFG->grayscaleMixer[2] != conf_default.grayscaleMixer[2]));
     gtk_widget_set_sensitive(GTK_WIDGET(data->GrayscaleMixerTable),
            CFG->grayscaleMode == grayscale_mixer);
+    despeckle_update_sensitive(data);
 
     for (max = 1, i = 0; i < 3; ++i)
         max = MAX(max, CFG->grayscaleMixer[i]);
@@ -2602,6 +2612,15 @@
         CFG->grayscaleMixer[1] = conf_default.grayscaleMixer[1];
         CFG->grayscaleMixer[2] = conf_default.grayscaleMixer[2];
     }
+    if (button==data->ResetDespeckleButton) {
+       memcpy(CFG->despeckleWindow, conf_default.despeckleWindow,
+               sizeof (CFG->despeckleWindow));
+       memcpy(CFG->despeckleDecay, conf_default.despeckleDecay,
+               sizeof (CFG->despeckleDecay));
+       memcpy(CFG->despecklePasses, conf_default.despecklePasses,
+               sizeof (CFG->despecklePasses));
+       ufraw_invalidate_despeckle_layer(data->UF);
+    }
     for (i = 0; i < max_adjustments; ++i) {
        if (button == data->ResetLightnessAdjustmentButton[i]) {
            CFG->lightnessAdjustment[i].adjustment = 1.0;
@@ -2700,6 +2719,25 @@
             ufraw_invalidate_layer(data->UF, ufraw_develop_phase);
            update_scales(data);
        }
+    } else if (valuep==(void*)data->ChannelSelectButton) {
+       if (data->UF->channel_select >= -1) {
+           int i, b = 0;
+           while (data->ChannelSelectButton[b] != button)
+               ++b;
+           if (gtk_toggle_button_get_active(button)) {
+               /* ignore generated events, for render_preview() */
+               data->UF->channel_select = -2;
+               for (i = 0; i < data->UF->colors; ++i)
+                   if (i != b)
+                       gtk_toggle_button_set_active(
+                               data->ChannelSelectButton[i], FALSE);
+               data->UF->channel_select = b;
+           } else {
+               data->UF->channel_select = -1;
+           }
+           ufraw_invalidate_layer(data->UF, ufraw_develop_phase);
+           render_preview(data);
+       }
     } else {
        *valuep = gtk_toggle_button_get_active(button);
        if ( valuep==&CFG->overExp || valuep==&CFG->underExp ) {
@@ -2751,6 +2789,98 @@
     }
 }
 
+static void despeckle_update_sensitive(preview_data *data)
+{
+    conf_data *c = CFG;
+    gboolean b;
+    int i;
+
+    b = FALSE;
+    for (i = 0; i < 3; ++i) {
+       b |= fabs(c->despeckleWindow[i] - conf_default.despeckleWindow[i]) > 
0.1;
+       b |= fabs(c->despeckleDecay[i] - conf_default.despeckleDecay[i]) > 
0.001;
+       b |= fabs(c->despecklePasses[i] - conf_default.despecklePasses[i]) > 
0.1;
+    }
+    gtk_widget_set_sensitive(GTK_WIDGET(data->ResetDespeckleButton), b);
+    b = FALSE;
+    for (i = 1; i < 3; ++i) {
+       b |= c->despeckleWindow[0] != c->despeckleWindow[i];
+       b |= c->despeckleDecay[0] != c->despeckleDecay[i];
+       b |= c->despecklePasses[0] != c->despecklePasses[i];
+    }
+    gtk_widget_set_sensitive(GTK_WIDGET(data->DespeckleLockChannelsButton), 
!b);
+}
+
+/*
+ * passes > window makes no sense. Either the number of passes is
+ * ridiculously large or the same effect can be achieved by replacing
+ * decay by pow(decay, original_passes).
+ */
+static void despeckle_apply_constraints(preview_data *data,
+       GtkAdjustment **adjp, int ch)
+{
+    conf_data *c = CFG;
+    double value = gtk_adjustment_get_value(adjp[ch]);
+
+    ++data->FreezeDialog;
+    if (adjp == data->DespeckleWindowAdj &&
+           value < c->despecklePasses[ch] && value) {
+       c->despecklePasses[ch] = value;
+       gtk_adjustment_set_value(data->DespecklePassesAdj[ch], value);
+    }
+    if (adjp == data->DespecklePassesAdj &&
+           value > c->despeckleWindow[ch] && c->despeckleWindow[ch]) {
+       c->despeckleWindow[ch] = value;
+       gtk_adjustment_set_value(data->DespeckleWindowAdj[ch], value);
+    }
+    --data->FreezeDialog;
+}
+
+static gboolean despeckle_adjustment_update(preview_data *data, double *p)
+{
+    conf_data *c = CFG;
+    int i, j, match;
+    GtkAdjustment **adjp = NULL;
+
+    match = 0;
+    for (i = 0; i < 3; ++i) {
+       if (p == &c->despeckleWindow[i]) {
+           adjp = data->DespeckleWindowAdj;
+           match = c->despecklePasses[i] ? 1 : -1;
+           break;
+       }
+       if (p == &c->despeckleDecay[i]) {
+           adjp = data->DespeckleDecayAdj;
+           match = c->despeckleWindow[i] && c->despecklePasses[i] ? 1 : -1;
+           break;
+       }
+       if (p == &c->despecklePasses[i]) {
+           adjp = data->DespecklePassesAdj;
+           match = c->despeckleWindow[i] ? 1 : -1;
+           break;
+       }
+    }
+    if (match > 0)
+       despeckle_apply_constraints(data, adjp, i);
+    if (match) {
+       if (gtk_toggle_button_get_active(data->DespeckleLockChannelsButton)) {
+           ++data->FreezeDialog;
+           for (j = 0; j < 3; ++j) {
+               p[j - i] = *p;
+               gtk_adjustment_set_value(adjp[j], *p);
+               despeckle_apply_constraints(data, adjp, j);
+           }
+           --data->FreezeDialog;
+       }
+       despeckle_update_sensitive(data);
+    }
+    if (match > 0) {
+       ufraw_invalidate_despeckle_layer(data->UF);
+       render_preview(data);
+    }
+    return match ? TRUE : FALSE;
+}
+
 static void adjustment_update(GtkAdjustment *adj, double *valuep)
 {
     preview_data *data = get_preview_data(adj);
@@ -2804,6 +2934,8 @@
        ufraw_invalidate_denoise_layer(data->UF);
     } else if (valuep==&CFG->hotpixel) {
        ufraw_invalidate_hotpixel_layer(data->UF);
+    } else if (despeckle_adjustment_update(data, valuep)) {
+       return;
     } else {
         if (CFG->autoExposure==enabled_state) CFG->autoExposure = apply_state;
         if (CFG->autoBlack==enabled_state) CFG->autoBlack = apply_state;
@@ -4368,6 +4500,104 @@
     /* End of Grayscale page */
 }
 
+static void denoise_fill_interface(preview_data *data, GtkWidget *page)
+{
+    GtkWidget *button, *label, *icon;
+    GtkTable *table;
+    GtkBox *box;
+    int i;
+
+    table = GTK_TABLE(table_with_frame(page, NULL, TRUE));
+    icon = gtk_image_new_from_stock("gtk-help", GTK_ICON_SIZE_BUTTON);
+    gtk_table_attach(table, icon, 9, 10, 0, 1, 0, 0, 0, 0);
+    uf_widget_set_tooltip(icon, _(
+           "Despeckling is mainly useful when combining a high ISO number "
+           "with a high channel multiplier: when one channel has a very bad "
+           "signal to noise ratio. Try setting window size, color decay and "
+           "number of passes to 50,0,5 for that channel. When a channel "
+           "contains only noise then try 1,0.6,1.\n"
+           "Despeckling is off when window size or passes equals zero. When "
+           "on then window size cannot be smaller than the number of 
passes."));
+
+    /* buttons on the right */
+    box = GTK_BOX(gtk_vbox_new(FALSE, 0));
+    button = gtk_toggle_button_new();
+    gtk_container_add(GTK_CONTAINER(button), gtk_image_new_from_stock(
+           "object-lock", GTK_ICON_SIZE_BUTTON));
+    data->DespeckleLockChannelsButton = GTK_TOGGLE_BUTTON(button);
+    gtk_box_pack_start(box, button, FALSE, FALSE, 0);
+    gtk_table_attach(table, GTK_WIDGET(box), 9, 10, 1, 4, GTK_FILL, 0, 0, 0);
+    uf_widget_set_tooltip(button, _("Update channel parameters together"));
+    data->ResetDespeckleButton = reset_button(_("Reset despeckle parameters"),
+           G_CALLBACK(button_update), NULL);
+    gtk_box_pack_start(box, data->ResetDespeckleButton, FALSE, FALSE, 0);
+
+    /* channel to view */
+    label = gtk_label_new(_("View channel:"));
+    gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5);
+    gtk_table_attach(table, label, 0, 6, 0, 1, GTK_FILL|GTK_EXPAND, 0, 0, 0);
+    for (i = 0; i < data->UF->colors; ++i) {
+       button = gtk_toggle_button_new();
+       gtk_container_add(GTK_CONTAINER(button), gtk_image_new_from_stock(
+               i==0 ? "channel-red" : i==1 ? "channel-green" : "channel-blue",
+               GTK_ICON_SIZE_BUTTON));
+       data->ChannelSelectButton[i] = GTK_TOGGLE_BUTTON(button);
+       g_signal_connect(G_OBJECT(button), "toggled",
+               G_CALLBACK(toggle_button_update), data->ChannelSelectButton);
+       gtk_table_attach(table, button, 6 + i, 6 + i + 1, 0, 1, 0, 0, 0, 0);
+    }
+
+    /* Parameters */
+    label = gtk_label_new(_("Window size:"));
+    gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5);
+    gtk_table_attach(table, label, 0, 6, 1, 2, GTK_FILL|GTK_EXPAND, 0, 0, 0);
+    for (i = 0; i < data->UF->colors; ++i) {
+       data->DespeckleWindowAdj[i] = GTK_ADJUSTMENT(
+               gtk_adjustment_new(CFG->despeckleWindow[i],
+               0.0, 999.0, 1.0, 1.0, 0));
+       g_object_set_data(G_OBJECT(data->DespeckleWindowAdj[i]),
+               "Adjustment-Accuracy", (gpointer)0);
+       button = gtk_spin_button_new(data->DespeckleWindowAdj[i], 1.0, 0);
+       g_object_set_data(G_OBJECT(data->DespeckleWindowAdj[i]),
+               "Parent-Widget", button);
+       g_signal_connect(G_OBJECT(data->DespeckleWindowAdj[i]), "value-changed",
+               G_CALLBACK(adjustment_update), &CFG->despeckleWindow[i]);
+       gtk_table_attach(table, button, 6 + i, 6 + i + 1, 1, 2, GTK_FILL, 0, 0, 
0);
+    }
+    label = gtk_label_new(_("Color decay:"));
+    gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5);
+    gtk_table_attach(table, label, 0, 6, 2, 3, GTK_FILL|GTK_EXPAND, 0, 0, 0);
+    for (i = 0; i < data->UF->colors; ++i) {
+       data->DespeckleDecayAdj[i] = GTK_ADJUSTMENT(
+               gtk_adjustment_new(CFG->despeckleDecay[i],
+               0.0, 1.0, 0.1, 0.1, 0));
+       g_object_set_data(G_OBJECT(data->DespeckleDecayAdj[i]),
+               "Adjustment-Accuracy", (gpointer)2);
+       button = gtk_spin_button_new(data->DespeckleDecayAdj[i], 1.0, 2);
+       g_object_set_data(G_OBJECT(data->DespeckleDecayAdj[i]),
+               "Parent-Widget", button);
+       g_signal_connect(G_OBJECT(data->DespeckleDecayAdj[i]), "value-changed",
+               G_CALLBACK(adjustment_update), &CFG->despeckleDecay[i]);
+       gtk_table_attach(table, button, 6 + i, 6 + i + 1, 2, 3, GTK_FILL, 0, 0, 
0);
+    }
+    label = gtk_label_new(_("Passes:"));
+    gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5);
+    gtk_table_attach(table, label, 0, 6, 3, 4, GTK_FILL|GTK_EXPAND, 0, 0, 0);
+    for (i = 0; i < data->UF->colors; ++i) {
+       data->DespecklePassesAdj[i] = GTK_ADJUSTMENT(
+               gtk_adjustment_new(CFG->despecklePasses[i],
+               0.0, 99.0, 1.0, 1.0, 0));
+       g_object_set_data(G_OBJECT(data->DespecklePassesAdj[i]),
+               "Adjustment-Accuracy", (gpointer)0);
+       button = gtk_spin_button_new(data->DespecklePassesAdj[i], 1.0, 0);
+       g_object_set_data(G_OBJECT(data->DespecklePassesAdj[i]),
+               "Parent-Widget", button);
+       g_signal_connect(G_OBJECT(data->DespecklePassesAdj[i]), "value-changed",
+               G_CALLBACK(adjustment_update), &CFG->despecklePasses[i]);
+       gtk_table_attach(table, button, 6 + i, 6 + i + 1, 3, 4, GTK_FILL, 0, 0, 
0);
+    }
+}
+
 static void basecurve_fill_interface(preview_data *data, GtkWidget *page,
        int curveeditorHeight)
 {
@@ -5254,6 +5484,9 @@
     data->PageNumGray = gtk_notebook_page_num(notebook, page);
     grayscale_fill_interface(data, page);
 
+    // page = notebook_page_new(notebook, _("Denoising"), "denoise");
+    denoise_fill_interface(data, page);
+
 #ifdef HAVE_LENSFUN
     /* Lens correction page */
     page = notebook_page_new(notebook, _("Lens correction"), "lens");


------------------------------------------------------------------------------
Let Crystal Reports handle the reporting - Free Crystal Reports 2008 30-Day 
trial. Simplify your report design, integration and deployment - and focus on 
what you do best, core application coding. Discover what's new with
Crystal Reports now.  http://p.sf.net/sfu/bobj-july
_______________________________________________
ufraw-cvs mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/ufraw-cvs

Reply via email to