The patch below has been tested and it seems to behave well. Occasionally
there are rendering artefacts in the preview image (e.g. at crop area
boundaries). I've seen similar issues in rendering before and the rotate
control operates at a higher level so I think it's unrelated.
diff --git a/ufraw.h b/ufraw.h
index aeed445..03150a5 100644
--- a/ufraw.h
+++ b/ufraw.h
@@ -19,6 +19,7 @@
#include "nikon_curve.h"
#include <time.h> // for time_t
+#include "dcraw_api.h"
/* macro to clamp a number between two values */
#ifndef LIM
@@ -320,6 +321,8 @@ void ufraw_auto_curve(ufraw_data *uf);
void ufraw_rotate_row(image_data *image, void *pixbuf, double angle,
int bitDepth, int row, int offset, int width);
void ufraw_rotate_image_buffer(ufraw_image_data *img, double angle);
+void ufraw_normalize_rotation(ufraw_data *uf);
+void ufraw_get_image_dimensions(dcraw_data *raw, ufraw_data *uf);
void ufraw_img_get_subarea_coord (ufraw_image_data *img, unsigned saidx,
int *x, int *y, int *w, int *h);
diff --git a/ufraw_preview.c b/ufraw_preview.c
index 2a89ac9..f093487 100644
--- a/ufraw_preview.c
+++ b/ufraw_preview.c
@@ -2022,6 +2022,21 @@ static void flip_image(GtkWidget *widget, int flip)
data->SpotY2 = temp;
}
}
+ ++data->FreezeDialog;
+ switch (flip) {
+ case 6:
+ gtk_adjustment_set_value(data->RotationAdjustment,
data->unnormalized_angle + 90);
+ break;
+ case 5:
+ gtk_adjustment_set_value(data->RotationAdjustment,
data->unnormalized_angle - 90);
+ break;
+ case 1:
+ case 2:
+ data->reference_orientation ^= flip;
+ gtk_adjustment_set_value(data->RotationAdjustment,
-data->unnormalized_angle);
+ break;
+ }
+ --data->FreezeDialog;
render_init(data);
if ( data->RenderSubArea >= 0 ) {
/* We are in the middle or a rendering scan,
@@ -2732,6 +2747,63 @@ static void adjustment_update(GtkAdjustment *adj, double
*valuep)
update_scales (data);
}
+/*
+ * Crop and spot area cannot be rotated but we make sure their coordinates
+ * are valid. Try to preserve them over a rotate forth and back and try to
+ * preserve their geometry.
+ */
+static void adjustment_update_rotation(GtkAdjustment *adj, gpointer user_data)
+{
+ preview_data *data = get_preview_data(adj);
+ int d;
+
+ (void)user_data;
+ data->unnormalized_angle = gtk_adjustment_get_value(adj);
+ if (data->FreezeDialog)
+ return;
+ CFG->rotationAngle = data->unnormalized_angle;
+ CFG->orientation = data->reference_orientation;
+ ufraw_normalize_rotation(data->UF);
+ ufraw_get_image_dimensions(data->UF->raw, data->UF);
+ d = MIN(CFG->CropX1, CFG->CropX2 - data->UF->rotatedWidth);
+ if (d > 0) {
+ CFG->CropX1 -= d;
+ CFG->CropX2 -= d;
+ }
+ d = MIN(CFG->CropY1, CFG->CropY2 - data->UF->rotatedHeight);
+ if (d > 0) {
+ CFG->CropY1 -= d;
+ CFG->CropY2 -= d;
+ }
+ d = MIN(data->SpotX1, data->SpotX2 - data->UF->rotatedWidth);
+ if (d > 0) {
+ data->SpotX1 -= d;
+ data->SpotX2 -= d;
+ }
+ d = MIN(data->SpotY1, data->SpotY2 - data->UF->rotatedHeight);
+ if (d > 0) {
+ data->SpotY1 -= d;
+ data->SpotY2 -= d;
+ }
+ if (data->SpotX2 > data->UF->rotatedWidth ||
+ data->SpotY2 > data->UF->rotatedHeight) {
+ data->SpotDraw = FALSE;
+ data->SpotX1 = -1;
+ data->SpotX2 = -1;
+ data->SpotY1 = -1;
+ data->SpotY2 = -1;
+ }
+ create_base_image(data);
+ if (CFG->CropX2 > data->UF->rotatedWidth)
+ fix_crop_aspect(data, top_right_cursor);
+ else if (CFG->CropY2 > data->UF->rotatedHeight)
+ fix_crop_aspect(data, bottom_left_cursor);
+ update_crop_ranges(data);
+ if (!CFG->LockAspect)
+ refresh_aspect(data);
+ update_scales(data);
+}
+
GtkWidget *reset_button(const char *tip, GCallback callback, void *data)
{
GtkWidget *button;
@@ -4613,6 +4685,24 @@ static void transformations_fill_interface(preview_data
*data,
gtk_table_attach(table, button, 4, 5, 0, 1, 0, 0, 0, 0);
g_signal_connect(G_OBJECT(button), "clicked",
G_CALLBACK(flip_image), (gpointer)2);
+
+ /* Rotation controls */
+ data->unnormalized_angle = CFG->rotationAngle;
+ data->reference_orientation = CFG->orientation;
+ table = GTK_TABLE(table_with_frame(page, NULL, TRUE));
+ label = gtk_label_new(_("Rotation"));
+ gtk_table_attach(GTK_TABLE(table), label, 0, 1, 0, 1, 0, 0, 0, 0);
+ data->RotationAdjustment = GTK_ADJUSTMENT(gtk_adjustment_new(
+ data->unnormalized_angle, -1e100, 1e100, 0.5, 5, 0));
+ data->RotationSpin = GTK_SPIN_BUTTON(gtk_spin_button_new(
+ data->RotationAdjustment, 0.5, 3));
+ g_object_set_data(G_OBJECT(data->RotationAdjustment), "Parent-Widget",
+ data->RotationSpin);
+ g_signal_connect(G_OBJECT(data->RotationAdjustment), "value-changed",
+ G_CALLBACK(adjustment_update_rotation), NULL);
+ gtk_table_attach(GTK_TABLE(table), GTK_WIDGET(data->RotationSpin),
+ 1, 2, 0, 1, 0, 0, 0, 0);
+
/* End of transformation page */
}
diff --git a/ufraw_ufraw.c b/ufraw_ufraw.c
index c3fb7bf..c4f406c 100644
--- a/ufraw_ufraw.c
+++ b/ufraw_ufraw.c
@@ -312,6 +312,26 @@ int ufraw_load_darkframe(ufraw_data *uf)
return UFRAW_SUCCESS;
}
+/*
+ * Normalize arbitrary rotations into a 0..90 degree range.
+ */
+void ufraw_normalize_rotation(ufraw_data *uf)
+{
+ int angle, flip = 0;
+
+ uf->conf->rotationAngle = fmod(uf->conf->rotationAngle, 360.0);
+ if (uf->conf->rotationAngle < 0.0)
+ uf->conf->rotationAngle += 360.0;
+ angle = floor(uf->conf->rotationAngle / 90) * 90;
+ switch (angle) {
+ case 90: flip = 6; break;
+ case 180: flip = 3; break;
+ case 270: flip = 5; break;
+ }
+ ufraw_flip_orientation(uf, flip);
+ uf->conf->rotationAngle -= angle;
+}
+
void ufraw_update_rotated_dimensions(ufraw_data *uf)
{
double rotationRadians = (uf->conf->rotationAngle * 2 * M_PI) / 360;
@@ -451,19 +471,7 @@ int ufraw_config(ufraw_data *uf, conf_data *rc, conf_data
*conf, conf_data *cmd)
} else {
if ( !uf->LoadingID || uf->conf->orientation<0 )
uf->conf->orientation = raw->flip;
-
- // Normalise rotations to a flip, then rotation of 0 < a < 90 degrees.
- uf->conf->rotationAngle = fmod(uf->conf->rotationAngle, 360.0);
- if (uf->conf->rotationAngle < 0.0) uf->conf->rotationAngle += 360.0;
- int angle, flip = 0;
- angle = floor(uf->conf->rotationAngle/90)*90;
- switch (angle) {
- case 90: flip = 6; break;
- case 180: flip = 3; break;
- case 270: flip = 5; break;
- }
- ufraw_flip_orientation(uf, flip);
- uf->conf->rotationAngle -= angle;
+ ufraw_normalize_rotation(uf);
}
if (uf->inputExifBuf==NULL) {
diff --git a/ufraw_ui.h b/ufraw_ui.h
index 1d4b65b..9aadd2e 100644
--- a/ufraw_ui.h
+++ b/ufraw_ui.h
@@ -83,6 +83,7 @@ typedef struct {
GtkSpinButton *ShrinkSpin;
GtkSpinButton *HeightSpin;
GtkSpinButton *WidthSpin;
+ GtkSpinButton *RotationSpin;
/* We need the adjustments for update_scale() */
GtkAdjustment *WBTuningAdjustment;
GtkAdjustment *TemperatureAdjustment;
@@ -107,6 +108,7 @@ typedef struct {
GtkAdjustment *ShrinkAdjustment;
GtkAdjustment *HeightAdjustment;
GtkAdjustment *WidthAdjustment;
+ GtkAdjustment *RotationAdjustment;
GtkAdjustment *GrayscaleMixers[3];
#ifdef HAVE_LENSFUN
/* The GtkEntry with camera maker/model name */
@@ -156,6 +158,8 @@ typedef struct {
double SpotHue;
CursorType CropMotionType;
int DrawnCropX1, DrawnCropX2, DrawnCropY1, DrawnCropY2;
+ double unnormalized_angle;
+ int reference_orientation;
double shrink, height, width;
gboolean OptionsChanged;
int PageNum;
--
Frank
------------------------------------------------------------------------------
Enter the BlackBerry Developer Challenge
This is your chance to win up to $100,000 in prizes! For a limited time,
vendors submitting new applications to BlackBerry App World(TM) will have
the opportunity to enter the BlackBerry Developer Challenge. See full prize
details at: http://p.sf.net/sfu/Challenge
_______________________________________________
ufraw-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/ufraw-devel