Author: post
Date: 2009-07-05 19:37:58 +0200 (Sun, 05 Jul 2009)
New Revision: 2553

Modified:
   trunk/plugins/rotate/rotate.c
Log:
Multithreaded rotate.

Modified: trunk/plugins/rotate/rotate.c
===================================================================
--- trunk/plugins/rotate/rotate.c       2009-07-05 15:41:58 UTC (rev 2552)
+++ trunk/plugins/rotate/rotate.c       2009-07-05 17:37:58 UTC (rev 2553)
@@ -57,15 +57,27 @@
        PROP_ORIENTATION
 };
 
+typedef struct {
+       RS_IMAGE16 *input;                      /* Input Image */
+       RS_IMAGE16 *output;                     /* Output Image*/
+       gint start_y;
+       gint end_y;
+       GThread *threadid;
+       gboolean use_straight;
+       RSRotate* rotate;
+} ThreadInfo;
+
+
 static void get_property (GObject *object, guint property_id, GValue *value, 
GParamSpec *pspec);
 static void set_property (GObject *object, guint property_id, const GValue 
*value, GParamSpec *pspec);
 static void previous_changed(RSFilter *filter, RSFilter *parent, 
RSFilterChangedMask mask);
 static RS_IMAGE16 *get_image(RSFilter *filter, RS_FILTER_PARAM *param);
-static RS_IMAGE16 *turn_right_angle(RS_IMAGE16 *in, const int direction);
+static void turn_right_angle(RS_IMAGE16 *in, RS_IMAGE16 *out, gint start_y, 
gint end_y, const int direction);
 static gint get_width(RSFilter *filter);
 static gint get_height(RSFilter *filter);
 static void inline bilinear(RS_IMAGE16 *in, gushort *out, gint x, gint y);
 static void recalculate(RSRotate *rotate);
+gpointer start_rotate_thread(gpointer _thread_info);
 
 static RSFilterClass *rs_rotate_parent_class = NULL;
 
@@ -181,9 +193,6 @@
        RSRotate *rotate = RS_ROTATE(filter);
        RS_IMAGE16 *input;
        RS_IMAGE16 *output = NULL;
-       gint x, y;
-       gint row, col;
-       gint destoffset;
 
        input = rs_filter_get_image(filter->previous, param);
 
@@ -193,20 +202,75 @@
        if ((rotate->angle < 0.001) && (rotate->orientation==0))
                return input;
 
+       gboolean straight = FALSE;
+
        if ((rotate->angle < 0.001) && (rotate->orientation < 4)) 
        {
-               output = turn_right_angle(input, rotate->orientation);
-               g_object_unref(input);
-               return output;
+               if (rotate->orientation == 2)
+                       output = rs_image16_new(input->w, input->h, 3, 
input->pixelsize);
+               else 
+                       output = rs_image16_new(input->h, input->w, 3, 
input->pixelsize);
+               straight = TRUE;
+       } else {
+               output = rs_image16_new(rotate->new_width, rotate->new_height, 
3, 4);
+               recalculate(rotate);
        }
 
-       recalculate(rotate);
+       /* Prepare threads */
+       guint i, y_offset, y_per_thread, threaded_h;
+       const guint threads = rs_get_number_of_processor_cores();
+       ThreadInfo *t = g_new(ThreadInfo, threads);
 
-       output = rs_image16_new(rotate->new_width, rotate->new_height, 3, 4);
+       threaded_h = straight ? input->h : output->h;
+       y_per_thread = (threaded_h + threads-1)/threads;
+       y_offset = 0;
 
+       for (i = 0; i < threads; i++)
+       {
+               t[i].use_straight = straight;
+               t[i].input = input;
+               t[i].output = output;
+               t[i].start_y = y_offset;
+               y_offset += y_per_thread;
+               y_offset = MIN(threaded_h, y_offset);
+               t[i].end_y = y_offset;
+               t[i].rotate = rotate;
+
+               t[i].threadid = g_thread_create(start_rotate_thread, &t[i], 
TRUE, NULL);
+       }
+
+       /* Wait for threads to finish */
+       for(i = 0; i < threads; i++)
+               g_thread_join(t[i].threadid);
+
+       g_free(t);
+       g_object_unref(input);
+
+       return output;
+}
+
+gpointer
+start_rotate_thread(gpointer _thread_info)
+{
+       ThreadInfo* t = _thread_info;
+
+       RS_IMAGE16 *input = t->input;
+       RS_IMAGE16 *output = t->output;
+       RSRotate *rotate = t->rotate;
+
+       if (t->use_straight) {
+               turn_right_angle(input, output, t->start_y, t->end_y, 
rotate->orientation);
+               g_thread_exit(NULL);
+               return NULL;
+       }
+
+       gint x, y;
+       gint row, col;
+       gint destoffset;
+
        gint crapx = (gint) (rotate->affine.coeff[0][0]*65536.0);
        gint crapy = (gint) (rotate->affine.coeff[0][1]*65536.0);
-       for(row=0;row<output->h;row++)
+       for(row=t->start_y;row<t->end_y;row++)
        {
                gint foox = (gint) ((((gdouble)row) * 
rotate->affine.coeff[1][0] + rotate->affine.coeff[2][0])*65536.0);
                gint fooy = (gint) ((((gdouble)row) * 
rotate->affine.coeff[1][1] + rotate->affine.coeff[2][1])*65536.0);
@@ -219,11 +283,12 @@
                }
        }
 
-       g_object_unref(input);
+       g_thread_exit(NULL);
 
-       return output;
+       return NULL; /* Make the compiler shut up - we'll never return */
 }
 
+
 static gint
 get_width(RSFilter *filter)
 {
@@ -353,17 +418,14 @@
        rotate->dirty = FALSE;
 }
 
-static RS_IMAGE16 * turn_right_angle(RS_IMAGE16 *in, const int direction)
+static void turn_right_angle(RS_IMAGE16 *in, RS_IMAGE16 *out, gint start_y, 
gint end_y, const int direction)
 {
-       RS_IMAGE16 *out = NULL;
        int dstp_offset, x, y, p;
-
        if (direction == 1) /* Rotate Left */
        { 
-               out = rs_image16_new(in->h, in->w, 3, in->pixelsize);
                p = out->pitch * out->pixelsize;
                gushort *dstp = GET_PIXEL(out, 0, 0);
-               for (y = 0; y < in->h; y++) 
+               for (y = start_y; y < end_y; y++) 
                {
                        gushort *srcp = GET_PIXEL(in, 0, y);
                        dstp_offset = (in->h - 1 - y) * in->pixelsize;
@@ -379,10 +441,9 @@
 
        if (direction == 3) /* Rotate Right */
        { 
-               out = rs_image16_new(in->h, in->w, 3, in->pixelsize);
                p = out->pitch * out->pixelsize;
                gushort *dstp = GET_PIXEL(out, 0, in->w - 1);
-               for (y = 0; y < in->h; y++) 
+               for (y = start_y; y < end_y; y++) 
                {
                        gushort *srcp = GET_PIXEL(in, 0, y);
                        dstp_offset = y * in->pixelsize;
@@ -398,8 +459,7 @@
 
        if (direction == 2) /* Rotate 180 */
        {
-               out = rs_image16_new(in->w, in->h, 3, in->pixelsize);
-               for (y = 0; y < in->h; y++) 
+               for (y = start_y; y < end_y; y++) 
                {
                        gushort *srcp = GET_PIXEL(in, 0, y);
                        gushort *dstp = GET_PIXEL(out, in->w - 1, in->h - 1 - 
y);


_______________________________________________
Rawstudio-commit mailing list
[email protected]
http://rawstudio.org/cgi-bin/mailman/listinfo/rawstudio-commit

Reply via email to