The patch below shows image rotation (not just flipping) in the preview
window of ufraw. The only way to specify a rotation is still to modify the
ID file but at least the preview window is now showing it correctly. There
are a couple of ways to make this accessible from within the GUI, for
example let the user draw a line on the horizon in the image but I'll
leave that for someone else.

The preview code contains lots of references to the initial width,height
instead of the rotated width,height but in order to keep the patch more
readable _for_now_ this has been fixed by a #define instead of fixing
it by search-and-replace.

A cropping bug for rotated images has been fixed in the writer too.


diff --git a/ufraw.h b/ufraw.h
index a8b35fb..32cfa72 100644
--- a/ufraw.h
+++ b/ufraw.h
@@ -315,6 +315,7 @@ void ufraw_auto_black(ufraw_data *uf);
 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_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 a686275..4666a20 100644
--- a/ufraw_preview.c
+++ b/ufraw_preview.c
@@ -35,6 +35,11 @@
 #include <gtkimageview/gtkimagescrollwin.h>
 #include <gtkimageview/gtkimageview.h>
 #endif
+
+/* Temporary kludge -- need s/initial\([HW]\)/rotated\1/g */
+#define initialWidth rotatedWidth
+#define initialHeight rotatedHeight
+
 #if GTK_CHECK_VERSION(2,6,0)
 void ufraw_chooser_toggle(GtkToggleButton *button, GtkFileChooser 
*filechooser);
 #endif
@@ -1760,6 +1765,7 @@ static void create_base_image(preview_data *data)
     preview_invalidate_layer (data, ufraw_denoise_phase);
     ufraw_convert_image_init(data->UF);
     ufraw_convert_image_first_phase(data->UF, FALSE);
+    ufraw_rotate_image_buffer(&data->UF->Images[ufraw_first_phase], 
data->UF->conf->rotationAngle);
     CFG->shrink = shrinkSave;
     CFG->size = sizeSave;
 }
@@ -2008,9 +2014,6 @@ static void flip_image(GtkWidget *widget, int flip)
        temp = data->UF->initialWidth;
        data->UF->initialWidth = data->UF->initialHeight;
        data->UF->initialHeight = temp;
-       temp = data->UF->rotatedWidth;
-       data->UF->rotatedWidth = data->UF->rotatedHeight;
-       data->UF->rotatedHeight = temp;
        temp = CFG->CropX1;
        CFG->CropX1 = CFG->CropY1;
        CFG->CropY1 = temp;
diff --git a/ufraw_ufraw.c b/ufraw_ufraw.c
index 441972d..120e6a1 100644
--- a/ufraw_ufraw.c
+++ b/ufraw_ufraw.c
@@ -638,7 +638,7 @@ void ufraw_close(ufraw_data *uf)
     g_free(uf->outputExifBuf);
     g_free(uf->image.image);
     int i;
-    for (i=ufraw_first_phase+1; i<ufraw_phases_num; i++)
+    for (i=ufraw_first_phase; i<ufraw_phases_num; i++)
        g_free(uf->Images[i].buffer);
     g_free(uf->thumb.buffer);
     developer_destroy(uf->developer);
@@ -1011,7 +1011,7 @@ int ufraw_convert_image_first_phase(ufraw_data *uf, 
gboolean lensfix)
     FirstImage->width = uf->image.width;
     FirstImage->depth = sizeof(dcraw_image_type);
     FirstImage->rowstride = FirstImage->width * FirstImage->depth;
-    FirstImage->buffer = (guint8 *)uf->image.image;
+    FirstImage->buffer = g_memdup(uf->image.image, FirstImage->height * 
FirstImage->rowstride);
     FirstImage->valid = 0xffffffff;
 
     return UFRAW_SUCCESS;
@@ -1771,3 +1771,71 @@ void ufraw_rotate_row(image_data *image, void *pixbuf, 
double angle,
        }
     }
 }
+
+/*
+ * Rotate an 8 or 16 bits per color image 0-90 degrees. The output pixel is
+ * calculated as a weighted average of the 4 nearest input pixels.
+ */
+void ufraw_rotate_image_buffer(ufraw_image_data *img, double angle)
+{
+    double sine, cosine, movecol, moverow;
+    int oldwidth, oldheight, oldrowstride;
+    int width, height, depth, rowstride;
+    int col, row, uc, ur, i;
+    float c, r, fc, fr;
+    guint8 *in, *in_00, *in_01, *in_10, *in_11, *out;
+
+    if (!angle)
+       return;
+    sine = sin(angle * 2 * M_PI / 360);
+    cosine = cos(angle * 2 * M_PI / 360);
+    depth = img->depth;
+    oldwidth = img->width;
+    oldheight = img->height;
+    oldrowstride = img->rowstride;
+    width = ceil((oldheight * sine) + (oldwidth * cosine));
+    height = ceil((oldwidth * sine) + (oldheight * cosine));
+    rowstride = width * depth;
+    in = img->buffer;
+    out = g_new0(guint8, height * rowstride);
+    img->buffer = out;
+    img->width = width;
+    img->height = height;
+    img->rowstride = rowstride;
+    movecol = -oldheight * sine * cosine;
+    moverow = oldheight * sine * sine;
+    for (row = 0; row < height; ++row) {
+       for (col = 0; col < width; col++) {
+           // (c,r) are the float input subpixel coordinates. fc,fr are the
+           // weighting factors for integer coordinates (uc,ur)..(uc+1,ur+1)
+           // around (c,r)
+           c = (col * cosine) + (row * sine) + movecol;
+           r = (row * cosine) - (col * sine) + moverow;
+           uc = (int)floor(c);
+           ur = (int)floor(r);
+           if (uc >= 0 && uc + 1 < oldwidth && ur >= 0 && ur + 1 < oldheight) {
+               fc = c - uc;
+               fr = r - ur;
+               in_00 = in + ((ur * oldwidth) + uc) * depth;    // (uc,ur)
+               in_01 = in_00 + depth;                          // (uc+1,ur)
+               in_10 = in_00 + oldrowstride;                   // (uc,ur+1)
+               in_11 = in_10 + depth;                          // (uc+1,ur+1)
+               if (depth > 4) {
+                   for (i = 0; i < 3; ++i) {
+                       ((guint16 *)out)[i] =
+                           (((guint16 *)in_00)[i] * (1 - fc) + ((guint16 
*)in_01)[i] * fc) * (1 - fr) +
+                           (((guint16 *)in_10)[i] * (1 - fc) + ((guint16 
*)in_11)[i] * fc) * fr;
+                   }
+               } else {
+                   for (i = 0; i < 3; ++i) {
+                       out[i] =
+                           (in_00[i] * (1 - fc) + in_01[i] * fc) * (1 - fr) +
+                           (in_10[i] * (1 - fc) + in_11[i] * fc) * fr;
+                   }
+               }
+           }
+           out += depth;
+       }
+    }
+    g_free(in);
+}
diff --git a/ufraw_writer.c b/ufraw_writer.c
index 0ea2bc2..8b84d7c 100644
--- a/ufraw_writer.c
+++ b/ufraw_writer.c
@@ -391,8 +391,8 @@ int ufraw_write_image(ufraw_data *uf)
     }
     // TODO: error handling
     ufraw_convert_image(uf);
-    left = uf->conf->CropX1 * uf->image.width / uf->rotatedWidth;
-    top = uf->conf->CropY1 * uf->image.height / uf->rotatedHeight;
+    left = uf->conf->CropX1 * uf->image.width / uf->initialWidth;
+    top = uf->conf->CropY1 * uf->image.height / uf->initialHeight;
     volatile int BitDepth = uf->conf->profile[out_profile]
                        [uf->conf->profileIndex[out_profile]].BitDepth;
     if ( BitDepth!=16 ) BitDepth = 8;

-- 
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

Reply via email to