Update of /cvsroot/ufraw/ufraw
In directory vz-cvs-3.sog:/tmp/cvs-serv7720
Modified Files:
ufraw.h ufraw_conf.c ufraw_preview.c ufraw_ufraw.c ufraw_ui.h
ufraw_writer.c
Log Message:
Fix various lensfun scale and crop problems. Add --auto-crop and --aspect-ratio
command line options. Patches by Vladimir Nadvornik
Index: ufraw_writer.c
===================================================================
RCS file: /cvsroot/ufraw/ufraw/ufraw_writer.c,v
retrieving revision 1.77
retrieving revision 1.78
diff -u -d -r1.77 -r1.78
--- ufraw_writer.c 27 Aug 2011 09:05:47 -0000 1.77
+++ ufraw_writer.c 19 Nov 2011 05:30:48 -0000 1.78
@@ -254,6 +254,13 @@
}
}
if (uf->conf->createID == only_id) {
+ if (uf->conf->autoCrop && !uf->LoadingID) {
+ ufraw_get_image_dimensions(uf);
+ uf->conf->CropX1 = (uf->rotatedWidth - uf->autoCropWidth) / 2;
+ uf->conf->CropX2 = uf->conf->CropX1 + uf->autoCropWidth;
+ uf->conf->CropY1 = (uf->rotatedHeight - uf->autoCropHeight) / 2;
+ uf->conf->CropY2 = uf->conf->CropY1 + uf->autoCropHeight;
+ }
int status = conf_save(uf->conf, confFilename, NULL);
g_free(confFilename);
return status;
Index: ufraw_preview.c
===================================================================
RCS file: /cvsroot/ufraw/ufraw/ufraw_preview.c,v
retrieving revision 1.358
retrieving revision 1.359
diff -u -d -r1.358 -r1.359
--- ufraw_preview.c 6 Nov 2011 03:30:55 -0000 1.358
+++ ufraw_preview.c 19 Nov 2011 05:30:48 -0000 1.359
@@ -932,9 +932,9 @@
ufraw_invalidate_layer(data->UF, ufraw_transform_phase);
ufraw_get_image_dimensions(data->UF);
CFG->CropX1 = (data->UF->rotatedWidth - data->UF->autoCropWidth) / 2;
- CFG->CropX2 = (data->UF->rotatedWidth + data->UF->autoCropWidth) / 2;
+ CFG->CropX2 = CFG->CropX1 + data->UF->autoCropWidth;
CFG->CropY1 = (data->UF->rotatedHeight - data->UF->autoCropHeight) / 2;
- CFG->CropY2 = (data->UF->rotatedHeight + data->UF->autoCropHeight) / 2;
+ CFG->CropY2 = CFG->CropY1 + data->UF->autoCropHeight;
update_crop_ranges(data, FALSE);
CFG->autoCrop = enabled_state;
}
@@ -1578,9 +1578,17 @@
static void auto_button_toggle(GtkToggleButton *button, gboolean *valuep)
{
if (gtk_toggle_button_get_active(button)) {
+ /* the button is inactive most of the time,
+ clicking on it activates it, but
+ we immediately deactivate it here
+ so this function is called again recursively
+ via callback from gtk_toggle_button_set_active */
*valuep = !*valuep;
gtk_toggle_button_set_active(button, FALSE);
}
+ /* if this function is called directly,
+ the condition above is false and we only
+ update the button image */
if (*valuep)
gtk_button_set_image(GTK_BUTTON(button), gtk_image_new_from_stock(
"object-automatic", GTK_ICON_SIZE_BUTTON));
@@ -2071,8 +2079,8 @@
CFG->CropY1 = 0;
CFG->CropX2 = data->UF->rotatedWidth;
CFG->CropY2 = data->UF->rotatedHeight;
- data->AspectRatio = ((float)data->UF->rotatedWidth) /
- data->UF->rotatedHeight;
+ CFG->aspectRatio = ((float)data->UF->rotatedWidth) /
+ data->UF->rotatedHeight;
refresh_aspect(data);
set_new_aspect(data);
@@ -2221,20 +2229,17 @@
static void refresh_aspect(preview_data *data)
{
- int dy = CFG->CropY2 - CFG->CropY1;
- data->AspectRatio = dy ? ((CFG->CropX2 - CFG->CropX1) / (float)dy) : 1.0;
-
// Look through a predefined list of aspect ratios
size_t i;
for (i = 0; i < sizeof(predef_aspects) / sizeof(predef_aspects[0]); i++)
- if (data->AspectRatio >= predef_aspects[i].val * 0.999 &&
- data->AspectRatio <= predef_aspects[i].val * 1.001) {
+ if (CFG->aspectRatio >= predef_aspects[i].val * 0.999 &&
+ CFG->aspectRatio <= predef_aspects[i].val * 1.001) {
data->FreezeDialog++;
gtk_entry_set_text(data->AspectEntry, predef_aspects[i].text);
data->FreezeDialog--;
return;
}
- char *text = g_strdup_printf("%.4g", data->AspectRatio);
+ char *text = g_strdup_printf("%.4g", CFG->aspectRatio);
data->FreezeDialog++;
gtk_entry_set_text(data->AspectEntry, text);
data->FreezeDialog--;
@@ -2262,13 +2267,16 @@
if (!CFG->LockAspect) {
update_crop_ranges(data, render);
+
+ int dy = CFG->CropY2 - CFG->CropY1;
+ CFG->aspectRatio = dy ? ((CFG->CropX2 - CFG->CropX1) / (float)dy) :
1.0;
refresh_aspect(data);
return;
}
- if (data->AspectRatio == 0)
+ if (CFG->aspectRatio == 0)
aspect = ((double)data->UF->rotatedWidth) / data->UF->rotatedHeight;
else
- aspect = data->AspectRatio;
+ aspect = CFG->aspectRatio;
switch (cursor) {
case left_cursor:
@@ -2391,27 +2399,27 @@
*/
dx = CFG->CropX2 - cx;
dy = CFG->CropY2 - cy;
- if (dx / dy > data->AspectRatio)
- dy = dx / data->AspectRatio;
+ if (dx / dy > CFG->aspectRatio)
+ dy = dx / CFG->aspectRatio;
else
- dx = dy * data->AspectRatio;
+ dx = dy * CFG->aspectRatio;
if (dx > cx) {
dx = cx;
- dy = dx / data->AspectRatio;
+ dy = dx / CFG->aspectRatio;
}
if (cx + dx > data->UF->rotatedWidth) {
dx = data->UF->rotatedWidth - cx;
- dy = dx / data->AspectRatio;
+ dy = dx / CFG->aspectRatio;
}
if (dy > cy) {
dy = cy;
- dx = dy * data->AspectRatio;
+ dx = dy * CFG->aspectRatio;
}
if (cy + dy > data->UF->rotatedHeight) {
dy = data->UF->rotatedHeight - cy;
- dx = dy * data->AspectRatio;
+ dx = dy * CFG->aspectRatio;
}
CFG->CropX1 = floor(cx - dx + 0.5);
@@ -2456,7 +2464,7 @@
sscanf(text, "%g", &aspect);
}
if (aspect >= 0.1 && aspect <= 10.0)
- data->AspectRatio = aspect;
+ CFG->aspectRatio = aspect;
}
set_new_aspect(data);
CFG->LockAspect = TRUE;
@@ -2959,14 +2967,16 @@
if ((int *)valuep == &CFG->CropX1 || (int *)valuep == &CFG->CropX2 ||
(int *)valuep == &CFG->CropY1 || (int *)valuep == &CFG->CropY2) {
- *((int *)valuep) = (int) gtk_adjustment_get_value(adj);
- CursorType cursor = left_cursor;
- if ((int *)valuep == &CFG->CropX1) cursor = left_cursor;
- if ((int *)valuep == &CFG->CropX2) cursor = right_cursor;
- if ((int *)valuep == &CFG->CropY1) cursor = top_cursor;
- if ((int *)valuep == &CFG->CropY2) cursor = bottom_cursor;
- fix_crop_aspect(data, cursor, TRUE);
+ /* values set by update_crop_ranges are ok and
+ do not have to be fixed */
if (!data->FreezeDialog) {
+ *((int *)valuep) = (int) gtk_adjustment_get_value(adj);
+ CursorType cursor = left_cursor;
+ if ((int *)valuep == &CFG->CropX1) cursor = left_cursor;
+ if ((int *)valuep == &CFG->CropX2) cursor = right_cursor;
+ if ((int *)valuep == &CFG->CropY1) cursor = top_cursor;
+ if ((int *)valuep == &CFG->CropY2) cursor = bottom_cursor;
+ fix_crop_aspect(data, cursor, TRUE);
CFG->autoCrop = disabled_state;
auto_button_toggle(data->AutoCropButton, &CFG->autoCrop);
}
@@ -3056,9 +3066,10 @@
double newAspect = (double)data->UF->rotatedWidth /
data->UF->rotatedHeight;
// Allow 1/aspect switch even if aspect is locked.
- if (fabs(data->AspectRatio - 1 / newAspect) < 0.0001) {
+ if (fabs(CFG->aspectRatio - 1 / newAspect) < 0.0001) {
CFG->CropX2 = data->UF->rotatedWidth;
CFG->CropY2 = data->UF->rotatedHeight;
+ CFG->aspectRatio = newAspect;
refresh_aspect(data);
}
} else { // Keep full crop
@@ -5002,13 +5013,12 @@
gtk_widget_set_tooltip_text(GTK_WIDGET(data->AutoCropButton),
_("Auto fit crop area"));
auto_button_toggle(data->AutoCropButton, &CFG->autoCrop);
- gtk_toggle_button_set_active(data->AutoCropButton, CFG->autoCrop);
g_signal_connect(G_OBJECT(data->AutoCropButton), "toggled",
G_CALLBACK(auto_button_toggled), &CFG->autoCrop);
// Crop reset button:
button = reset_button(
- _("Reset the crop region"), G_CALLBACK(crop_reset), NULL);
+ _("Reset the crop area"), G_CALLBACK(crop_reset), NULL);
gtk_table_attach(table, button, 5, 6, 1, 2, 0, 0, 0, 0);
/* Aspect ratio controls */
@@ -5045,6 +5055,12 @@
lock_aspect(data->LockAspectButton, &CFG->LockAspect);
/* Get initial aspect ratio */
+ if (CFG->aspectRatio != 0.0)
+ set_new_aspect(data);
+ else {
+ int dy = CFG->CropY2 - CFG->CropY1;
+ CFG->aspectRatio = dy ? ((CFG->CropX2 - CFG->CropX1) / (float)dy) :
1.0;
+ }
refresh_aspect(data);
/* Size/shrink controls */
@@ -5433,7 +5449,6 @@
data->DrawnCropY1 = 0;
data->DrawnCropY2 = 99999;
- data->AspectRatio = 0.0;
data->BlinkTimer = 0;
data->DrawCropID = 0;
for (i = 0; i < num_buttons; i++) {
Index: ufraw.h
===================================================================
RCS file: /cvsroot/ufraw/ufraw/ufraw.h,v
retrieving revision 1.164
retrieving revision 1.165
diff -u -d -r1.164 -r1.165
--- ufraw.h 6 Nov 2011 03:30:55 -0000 1.164
+++ ufraw.h 19 Nov 2011 05:30:48 -0000 1.165
@@ -252,6 +252,7 @@
char darkframeFile[max_path];
struct ufraw_struct *darkframe;
int CropX1, CropY1, CropX2, CropY2;
+ double aspectRatio;
int orientation;
double rotationAngle;
int lightnessAdjustmentCount;
Index: ufraw_conf.c
===================================================================
RCS file: /cvsroot/ufraw/ufraw/ufraw_conf.c,v
retrieving revision 1.180
retrieving revision 1.181
diff -u -d -r1.180 -r1.181
--- ufraw_conf.c 4 Sep 2011 03:14:04 -0000 1.180
+++ ufraw_conf.c 19 Nov 2011 05:30:48 -0000 1.181
@@ -89,6 +89,7 @@
ahd_interpolation, 0, /* interpolation, smoothing */
"", NULL, /* darkframeFile, darkframe */
-1, -1, -1, -1, /* Crop X1,Y1,X2,Y2 */
+ 0.0, /* aspectRatio */
-1, /* orientation */
0, /* rotationAngle */
0, /* lightness adjustment count */
@@ -746,6 +747,7 @@
if (!strcmp("Orientation", element)) sscanf(temp, "%d", &c->orientation);
if (!strcmp("Crop", element)) sscanf(temp, "%d %d %d %d",
&c->CropX1, &c->CropY1, &c->CropX2, &c->CropY2);
+ if (!strcmp("AspectRatio", element)) sscanf(temp, "%lf", &c->aspectRatio);
if (!strcmp("Rotation", element)) sscanf(temp, "%lf", &c->rotationAngle);
if (!strcmp("Shrink", element)) sscanf(temp, "%d", &c->shrink);
if (!strcmp("Size", element)) sscanf(temp, "%d", &c->size);
@@ -1259,6 +1261,8 @@
c->exifSource);
buf = uf_markup_buf(buf, "<Crop>%d %d %d %d</Crop>\n",
c->CropX1, c->CropY1, c->CropX2, c->CropY2);
+ if (c->aspectRatio != 0.0)
+ buf = uf_markup_buf(buf, "<AspectRatio>%lf</AspectRatio>\n",
c->aspectRatio);
buf = uf_markup_buf(buf, "<Rotation>%lf</Rotation>\n",
c->rotationAngle);
char *log = ufraw_message(UFRAW_GET_LOG, NULL);
if (log != NULL) {
@@ -1431,6 +1435,7 @@
dst->CropY1 = src->CropY1;
dst->CropX2 = src->CropX2;
dst->CropY2 = src->CropY2;
+ dst->aspectRatio = src->aspectRatio;
dst->rotationAngle = src->rotationAngle;
}
@@ -1474,6 +1479,7 @@
if (cmd->embeddedImage != -1) conf->embeddedImage = cmd->embeddedImage;
if (cmd->rotate != -1) conf->rotate = cmd->rotate;
if (cmd->rotationAngle != NULLF) conf->rotationAngle = cmd->rotationAngle;
+ if (cmd->autoCrop != -1) conf->autoCrop = cmd->autoCrop;
if (cmd->CropX1 != -1 || cmd->CropX2 != -1 ||
cmd->CropY1 != -1 || cmd->CropY2 != -1)
conf->autoCrop = disabled_state;
@@ -1481,6 +1487,7 @@
if (cmd->CropY1 != -1) conf->CropY1 = cmd->CropY1;
if (cmd->CropX2 != -1) conf->CropX2 = cmd->CropX2;
if (cmd->CropY2 != -1) conf->CropY2 = cmd->CropY2;
+ if (cmd->aspectRatio != 0.0) conf->aspectRatio = cmd->aspectRatio;
if (cmd->silent != -1) conf->silent = cmd->silent;
if (cmd->compression != NULLF) conf->compression = cmd->compression;
if (cmd->autoExposure) {
@@ -1655,6 +1662,8 @@
N_("--crop-(left|right|top|bottom)=PIXELS\n"
" Crop the output to the given pixel range, relative
to the\n"
" raw image after rotation but before any
scaling.\n"),
+ N_("--auto-crop Crop the output automatically.\n"),
+ N_("--aspect-ratio X:Y Set crop area aspect ratio.\n"),
#ifdef HAVE_LENSFUN
N_("--lensfun=none|auto Do not apply lens correction or try to apply\n"
" correction by auto-detecting the lens (default
none).\n"),
@@ -1781,6 +1790,7 @@
{ "crop-top", 1, 0, '2'},
{ "crop-right", 1, 0, '3'},
{ "crop-bottom", 1, 0, '4'},
+ { "aspect-ratio", 1, 0, 'P'},
/* Binary flags that don't have a value are here at the end */
{ "zip", 0, 0, 'z'},
{ "nozip", 0, 0, 'Z'},
@@ -1794,6 +1804,7 @@
{ "help", 0, 0, 'h'},
{ "version", 0, 0, 'v'},
{ "batch", 0, 0, 'b'},
+ { "auto-crop", 0, 0, '0'},
{ 0, 0, 0, 0}
};
UFObject *tmpImage = ufraw_image_new();
@@ -1818,7 +1829,8 @@
&outTypeName, &cmd->profile[1][0].BitDepth, &rotateName,
&createIDName, &outPath, &output, &darkframeFile,
&restoreName, &clipName, &conf,
- &cmd->CropX1, &cmd->CropY1, &cmd->CropX2, &cmd->CropY2
+ &cmd->CropX1, &cmd->CropY1, &cmd->CropX2, &cmd->CropY2,
+ &cmd->aspectRatio
};
cmd->autoExposure = disabled_state;
cmd->autoBlack = disabled_state;
@@ -1847,6 +1859,8 @@
cmd->CropY1 = -1;
cmd->CropX2 = -1;
cmd->CropY2 = -1;
+ cmd->autoCrop = -1;
+ cmd->aspectRatio = 0.0;
cmd->rotate = -1;
cmd->smoothing = -1;
@@ -1982,6 +1996,25 @@
ufraw_message(UFRAW_ERROR,
_("--batch is obsolete. Use ufraw-batch
instead."));
return -1;
+ case '0':
+ cmd->autoCrop = enabled_state;
+ break;
+ case 'P': {
+ double num = 0.0, denom = 1.0;
+ locale = uf_set_locale_C();
+ if (sscanf(optarg, "%lf:%lf", &num, &denom) < 2 &&
+ sscanf(optarg, "%lf/%lf", &num, &denom) < 2 &&
+ sscanf(optarg, "%lf", &num) == 0) {
+ ufraw_message(UFRAW_ERROR,
+ _("'%s' is not a valid value for the --%s
option."),
+ optarg, options[index].name);
+ uf_reset_locale(locale);
+ return -1;
+ }
+ *(double *)optPointer[index] = num / denom;
+ uf_reset_locale(locale);
+ }
+ break;
case '?': /* invalid option. Warning printed by getopt() */
return -1;
default:
Index: ufraw_ufraw.c
===================================================================
RCS file: /cvsroot/ufraw/ufraw/ufraw_ufraw.c,v
retrieving revision 1.268
retrieving revision 1.269
diff -u -d -r1.268 -r1.269
--- ufraw_ufraw.c 6 Nov 2011 03:30:55 -0000 1.268
+++ ufraw_ufraw.c 19 Nov 2011 05:30:48 -0000 1.269
@@ -363,6 +363,35 @@
if (uf->conf->CropY1 < 0) uf->conf->CropY1 = 0;
if (uf->conf->CropX2 < 0) uf->conf->CropX2 = uf->rotatedWidth;
if (uf->conf->CropY2 < 0) uf->conf->CropY2 = uf->rotatedHeight;
+
+ if (uf->conf->aspectRatio <= 0) {
+ if (uf->conf->autoCrop)
+ /* preserve the initial aspect ratio - this should be consistent
+ with ufraw_convert_prepare_transform */
+ uf->conf->aspectRatio = ((double)uf->initialWidth) /
uf->initialHeight;
+ else
+ /* full rotated image / manually entered crop */
+ uf->conf->aspectRatio = ((double)uf->conf->CropX2 -
uf->conf->CropX1)
+ / (uf->conf->CropY2 - uf->conf->CropY1);
+ } else {
+ /* given aspectRatio */
+ int cropWidth = uf->conf->CropX2 - uf->conf->CropX1;
+ int cropHeight = uf->conf->CropY2 - uf->conf->CropY1;
+
+ if (cropWidth != (int)(cropHeight * uf->conf->aspectRatio + 0.5)) {
+ /* aspectRatio does not match the crop area - shrink the area */
+
+ if ((double)cropWidth / cropHeight > uf->conf->aspectRatio) {
+ cropWidth = cropHeight * uf->conf->aspectRatio + 0.5;
+ uf->conf->CropX1 = (uf->conf->CropX1 + uf->conf->CropX2 -
cropWidth) / 2;
+ uf->conf->CropX2 = uf->conf->CropX1 + cropWidth;
+ } else {
+ cropHeight = cropWidth / uf->conf->aspectRatio + 0.5;
+ uf->conf->CropY1 = (uf->conf->CropY1 + uf->conf->CropY2 -
cropHeight) / 2;
+ uf->conf->CropY2 = uf->conf->CropY1 + cropHeight;
+ }
+ }
+ }
}
/* Get scaled crop coordinates in final image coordinates */
@@ -815,9 +844,9 @@
if (uf->conf->autoCrop && !uf->LoadingID) {
ufraw_get_image_dimensions(uf);
uf->conf->CropX1 = (uf->rotatedWidth - uf->autoCropWidth) / 2;
- uf->conf->CropX2 = (uf->rotatedWidth + uf->autoCropWidth) / 2;
+ uf->conf->CropX2 = uf->conf->CropX1 + uf->autoCropWidth;
uf->conf->CropY1 = (uf->rotatedHeight - uf->autoCropHeight) / 2;
- uf->conf->CropY2 = (uf->rotatedHeight + uf->autoCropHeight) / 2;
+ uf->conf->CropY2 = uf->conf->CropY1 + uf->autoCropHeight;
}
return UFRAW_SUCCESS;
}
@@ -1393,6 +1422,12 @@
{
const int iWidth = uf->initialWidth;
const int iHeight = uf->initialHeight;
+
+ double aspectRatio = uf->conf->aspectRatio;
+
+ if (aspectRatio == 0)
+ aspectRatio = ((double)iWidth) / iHeight;
+
#ifdef HAVE_LENSFUN
ufraw_convert_prepare_transform(uf, iWidth, iHeight, TRUE, 1.0);
if (uf->conf->rotationAngle == 0 &&
@@ -1412,12 +1447,16 @@
uf->rotatedHeight = iHeight;
uf->autoCropWidth = iWidth;
uf->autoCropHeight = iHeight;
+ if ((double)uf->autoCropWidth / uf->autoCropHeight > aspectRatio)
+ uf->autoCropWidth = uf->autoCropHeight * aspectRatio + 0.5;
+ else
+ uf->autoCropHeight = uf->autoCropWidth / aspectRatio + 0.5;
+
return;
}
const double sine = sin(uf->conf->rotationAngle * 2 * M_PI / 360);
const double cosine = cos(uf->conf->rotationAngle * 2 * M_PI / 360);
- const float aspectRatio = (float)(uf->conf->CropX2 - uf->conf->CropX1) /
- (uf->conf->CropY2 - uf->conf->CropY1);
+
const float midX = iWidth / 2.0 - 0.5;
const float midY = iHeight / 2.0 - 0.5;
#ifdef HAVE_LENSFUN
@@ -1464,14 +1503,17 @@
}
float scale = sqrt((iWidth - 1) * (iHeight - 1) / area);
// Do not allow increasing canvas size by more than a factor of 2
- uf->rotatedWidth = MIN(ceil(2 * maxX) * scale, 2 * iWidth);
- uf->rotatedHeight = MIN(ceil(2 * maxY) * scale, 2 * iHeight);
- if (minX / minY > aspectRatio)
- minX = minY * aspectRatio;
- else
- minY = minX / aspectRatio;
+ uf->rotatedWidth = MIN(ceil(2 * maxX + 1.0) * scale, 2 * iWidth);
+ uf->rotatedHeight = MIN(ceil(2 * maxY + 1.0) * scale, 2 * iHeight);
+
uf->autoCropWidth = MIN(floor(2 * minX) * scale, 2 * iWidth);
uf->autoCropHeight = MIN(floor(2 * minY) * scale, 2 * iHeight);
+
+ if ((double)uf->autoCropWidth / uf->autoCropHeight > aspectRatio)
+ uf->autoCropWidth = uf->autoCropHeight * aspectRatio + 0.5;
+ else
+ uf->autoCropHeight = uf->autoCropWidth / aspectRatio + 0.5;
+
int newWidth = uf->rotatedWidth * width / iWidth;
int newHeight = uf->rotatedHeight * height / iHeight;
ufraw_image_init(img, newWidth, newHeight, 8);
Index: ufraw_ui.h
===================================================================
RCS file: /cvsroot/ufraw/ufraw/ufraw_ui.h,v
retrieving revision 1.46
retrieving revision 1.47
diff -u -d -r1.46 -r1.47
--- ufraw_ui.h 20 Feb 2011 06:15:20 -0000 1.46
+++ ufraw_ui.h 19 Nov 2011 05:30:48 -0000 1.47
@@ -159,7 +159,6 @@
int HisMinHeight;
int UnnormalizedOrientation;
/* Original aspect ratio (0) or actual aspect ratio */
- float AspectRatio;
/* The aspect ratio entry field */
GtkEntry *AspectEntry;
/* Output base filename (without the path) */
------------------------------------------------------------------------------
All the data continuously generated in your IT infrastructure
contains a definitive record of customers, application performance,
security threats, fraudulent activity, and more. Splunk takes this
data and makes sense of it. IT sense. And common sense.
http://p.sf.net/sfu/splunk-novd2d
_______________________________________________
ufraw-cvs mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/ufraw-cvs