Author: post
Date: 2010-12-29 04:23:57 +0100 (Wed, 29 Dec 2010)
New Revision: 3708

Modified:
   trunk/plugins/lensfun/lensfun-sse2.c
   trunk/plugins/lensfun/lensfun.c
Log:
Add function to lensfun that output proposed crop position for automatic 
cropping of areas that are unusable due to lens correction.

Modified: trunk/plugins/lensfun/lensfun-sse2.c
===================================================================
--- trunk/plugins/lensfun/lensfun-sse2.c        2010-12-29 03:13:56 UTC (rev 
3707)
+++ trunk/plugins/lensfun/lensfun-sse2.c        2010-12-29 03:23:57 UTC (rev 
3708)
@@ -28,6 +28,7 @@
 
 static gfloat twofiftytwo_ps[4] __attribute__ ((aligned (16))) = {256.0f, 
256.0f, 256.0f, 0.0f};
 static gint _zero12[4] __attribute__ ((aligned (16))) = {0,1,2,0};
+static gint _max_coord[4] __attribute__ ((aligned (16))) = 
{65536,65536,65536,65536};
 
 gboolean is_sse2_compiled()
 {
@@ -35,7 +36,7 @@
 }
 
 void
-rs_image16_bilinear_full_sse2(RS_IMAGE16 *in, gushort *out, gfloat *pos)
+rs_image16_bilinear_full_sse2(RS_IMAGE16 *in, gushort *out, gfloat *pos, const 
gint *current_xy, const gint* min_max_xy)
 {
        const gint m_w = (in->w-1);
        const gint m_h = (in->h-1);
@@ -67,8 +68,6 @@
        
        __m128i x_gt, y_gt;
 
-#if 1
-       /* If positions from lensfun is properly clamped this should not be 
needed */
        /* Clamping */
        x_gt = _mm_cmpgt_epi32(x, _m_w);
        y_gt = _mm_cmpgt_epi32(y, _m_h);
@@ -76,12 +75,36 @@
        x = _mm_or_si128(_mm_andnot_si128(x_gt, x), _mm_and_si128(_m_w, x_gt));
        y = _mm_or_si128(_mm_andnot_si128(y_gt, y), _mm_and_si128(_m_h, y_gt));
 
+       __m128i current_pos = _mm_loadl_epi64((__m128i*)current_xy);
+       __m128i current_x = _mm_shuffle_epi32(current_pos,_MM_SHUFFLE(0,0,0,0));
+       __m128i current_y = _mm_shuffle_epi32(current_pos,_MM_SHUFFLE(1,1,1,1));
+       __m128i max_x = _mm_load_si128((__m128i*)&min_max_xy[8]);
+       __m128i max_y = _mm_load_si128((__m128i*)&min_max_xy[12]);
+       __m128i max_coord = _mm_load_si128((__m128i*)_max_coord);
+       __m128i eq_max_x = _mm_cmpeq_epi32(max_coord, max_x);
+       __m128i eq_max_y = _mm_cmpeq_epi32(max_coord, max_y);
+       x_gt = _mm_and_si128(x_gt, eq_max_x);
+       y_gt = _mm_and_si128(y_gt, eq_max_y);
+       __m128i insert_x = _mm_and_si128(x_gt, current_x);
+       __m128i insert_y = _mm_and_si128(y_gt, current_y);
+       max_x = _mm_or_si128(insert_x, _mm_andnot_si128(x_gt, max_x));
+       max_y = _mm_or_si128(insert_y, _mm_andnot_si128(y_gt, max_y));
+       _mm_store_si128((__m128i*)&min_max_xy[8], max_x);
+       _mm_store_si128((__m128i*)&min_max_xy[12], max_y);
+
        __m128i zero = _mm_setzero_si128();
        __m128i x_lt = _mm_cmplt_epi32(x, zero);
        __m128i y_lt = _mm_cmplt_epi32(y, zero);
        x = _mm_andnot_si128(x_lt, x);
        y = _mm_andnot_si128(y_lt, y);
-#endif
+       __m128i min_x = _mm_load_si128((__m128i*)&min_max_xy[0]);
+       __m128i min_y = _mm_load_si128((__m128i*)&min_max_xy[4]);
+       insert_x = _mm_and_si128(x_lt, current_x);
+       insert_y = _mm_and_si128(y_lt, current_y);
+       min_x = _mm_or_si128(insert_x, _mm_andnot_si128(x_lt, min_x));
+       min_y = _mm_or_si128(insert_y, _mm_andnot_si128(y_lt, min_y));
+       _mm_store_si128((__m128i*)&min_max_xy[0], min_x);
+       _mm_store_si128((__m128i*)&min_max_xy[4], min_y);
        
        __m128i one = _mm_set1_epi32(1);
        __m128i nx = _mm_add_epi32(one, _mm_srai_epi32(x, 8));
@@ -188,7 +211,7 @@
 }
 
 void
-rs_image16_bilinear_full_sse2(RS_IMAGE16 *in, gushort *out, gfloat *pos)
+rs_image16_bilinear_full_sse2(RS_IMAGE16 *in, gushort *out, gfloat *pos,const 
gint *current_xy, const gint* min_max_xy)
 {
 }
 #endif // defined (__SSE2__)

Modified: trunk/plugins/lensfun/lensfun.c
===================================================================
--- trunk/plugins/lensfun/lensfun.c     2010-12-29 03:13:56 UTC (rev 3707)
+++ trunk/plugins/lensfun/lensfun.c     2010-12-29 03:23:57 UTC (rev 3708)
@@ -87,7 +87,7 @@
 static void inline rs_image16_nearest_full(RS_IMAGE16 *in, gushort *out, 
gfloat *pos);
 static void inline rs_image16_bilinear_full(RS_IMAGE16 *in, gushort *out, 
gfloat *pos);
 extern gboolean is_sse2_compiled();
-extern void rs_image16_bilinear_full_sse2(RS_IMAGE16 *in, gushort *out, gfloat 
*pos);
+extern void rs_image16_bilinear_full_sse2(RS_IMAGE16 *in, gushort *out, gfloat 
*pos, const gint *current_xy, const gint* min_max_xy);
 static RSFilterClass *rs_lensfun_parent_class = NULL;
 
 G_MODULE_EXPORT void
@@ -294,13 +294,14 @@
        GThread *threadid;
        gint effective_flags;
        GdkRectangle *roi;
-       gint stage;     
+       gint stage;
+       gint min_max_xy[4];
 } ThreadInfo;
 
 static gpointer
 thread_func(gpointer _thread_info)
 {
-       gint x, y;
+       gint x, y, i;
        ThreadInfo* t = _thread_info;
 
        if (t->stage == 2) 
@@ -313,13 +314,33 @@
                                LF_CR_4 (RED, GREEN, BLUE, UNKNOWN),
                                t->input->rowstride*2);
                }
+               return NULL;
        }
 
        gboolean sse2_available = !!(rs_detect_cpu_features() & 
RS_CPU_FLAG_SSE2) && is_sse2_compiled();
+       gint min_max_xy[16] __attribute__ ((aligned (16)));
+       gint current_xy[2] __attribute__ ((aligned (16))) = {0,0};
 
        if (t->input->pixelsize != 4)
                sse2_available = FALSE;
 
+       if (sse2_available)
+       {
+               for (i = 0; i < 8; i++)
+               {
+                       min_max_xy[i] = 0;
+                       min_max_xy[i+8] = 65536;
+               }
+       } 
+       else
+       {
+               min_max_xy[0] = min_max_xy[1] = 0;
+               min_max_xy[2] = min_max_xy[3] = 65536;
+       }
+
+       gfloat max_w = (float)t->input->w-1;
+       gfloat max_h = (float)t->input->h-1;
+
        if (t->stage == 3) 
        {
                /* Do TCA and distortion */
@@ -335,10 +356,12 @@
 
                        if (sse2_available)
                        {
+                               current_xy[1] = y;
                                for(x = 0; x < t->roi->width ; x++)
                                {
-                                       rs_image16_bilinear_full_sse2(t->input, 
target, l_pos);
-                                       target += pixelsize;
+                                       current_xy[0] = x;
+                                       rs_image16_bilinear_full_sse2(t->input, 
target, l_pos, current_xy, min_max_xy);
+                                       target += 4;
                                        l_pos += 6;
                                }
                        } else 
@@ -346,12 +369,41 @@
                                for(x = 0; x < t->roi->width ; x++)
                                {
                                        rs_image16_bilinear_full(t->input, 
target, l_pos);
+
+                                       /* Set minimum and maximum values */
+                                       if (l_pos[0] < 0.0001 || l_pos[2] < 
0.0001 || l_pos[4] < 0.0001)
+                                               min_max_xy[0] = x;
+                                       if (l_pos[1] < 0.0001 || l_pos[3] < 
0.0001 || l_pos[5] < 0.0001)
+                                               min_max_xy[1] = y;
+                                       if ((l_pos[0] > max_w || l_pos[2] > 
max_w || l_pos[4] > max_w) && min_max_xy[2] > 65535)
+                                               min_max_xy[2] = x;
+                                       if ((l_pos[1] > max_h || l_pos[3] > 
max_h || l_pos[5] > max_h) && min_max_xy[3] > 65535)
+                                               min_max_xy[3] = y;
+                                       
                                        target += pixelsize;
                                        l_pos += 6;
                                }
                        }
                }
                g_free(pos);
+               if (sse2_available)
+               {
+                       for (i = 1; i < 4; i++)
+                       {
+                               min_max_xy[0] = MAX(min_max_xy[0], 
min_max_xy[i]);
+                               min_max_xy[4] = MAX(min_max_xy[4], 
min_max_xy[4+i]);
+                               min_max_xy[8] = MIN(min_max_xy[8], 
min_max_xy[8+i]);
+                               min_max_xy[12] = MIN(min_max_xy[12], 
min_max_xy[12+i]);
+                       }
+                       for (i = 0; i < 4; i++)
+                               t->min_max_xy[i] = min_max_xy[i*4];
+                       //g_debug("x1:%d, y1:%d, x2:%d, y2:%d", 
t->min_max_xy[0],t->min_max_xy[1],t->min_max_xy[2],t->min_max_xy[3]);
+               }
+               else
+               {
+                       for (i = 0; i < 4; i++)
+                               t->min_max_xy[i] = min_max_xy[i];
+               }
        }
        return NULL;
 }
@@ -368,7 +420,9 @@
        const gchar *make = NULL;
        const gchar *model = NULL;
        GdkRectangle *roi, *vign_roi;
+       RS_RECT *proposed_crop;
 
+
        previous_response = rs_filter_get_image(filter->previous, request);
        input = rs_filter_response_get_image(previous_response);
        response = rs_filter_response_clone(previous_response);
@@ -569,6 +623,7 @@
                        
                if (effective_flags > 0)
                {
+                       proposed_crop = g_new(RS_RECT, 1);
                        const guint threads = 
rs_get_number_of_processor_cores();
                        ThreadInfo *t = g_new(ThreadInfo, threads);
 
@@ -637,7 +692,27 @@
                        else
                        {
                                output = rs_image16_copy(input, TRUE);
-                       }                       
+                       }
+                       proposed_crop->x1 = proposed_crop->y1 = 0;
+                       proposed_crop->x2 = output->w-1;
+                       proposed_crop->y2 = output->h-1;
+                       for(i = 0; i < threads; i++)
+                       {
+                               proposed_crop->x1 = MIN(output->w-100, 
MAX(proposed_crop->x1, t[i].min_max_xy[0]));
+                               proposed_crop->y1 = MIN(output->h-100, 
MAX(proposed_crop->y1, t[i].min_max_xy[1]));
+                               proposed_crop->x2 = MAX(proposed_crop->x1+10, 
MIN(proposed_crop->x2, t[i].min_max_xy[2]));
+                               proposed_crop->y2 = MAX(proposed_crop->y1+10, 
MIN(proposed_crop->y2, t[i].min_max_xy[3]));
+                       }
+                       if (proposed_crop->x1 != 0 || proposed_crop->y1 != 0 || 
proposed_crop->x2 != output->w-1 || proposed_crop->y2 != output->h-1)
+                       {
+                               
rs_filter_param_set_integer(RS_FILTER_PARAM(response), "proposed-crop-x1", 
proposed_crop->x1);
+                               
rs_filter_param_set_integer(RS_FILTER_PARAM(response), "proposed-crop-y1", 
proposed_crop->y1);
+                               
rs_filter_param_set_integer(RS_FILTER_PARAM(response), "proposed-crop-x2", 
proposed_crop->x2);
+                               
rs_filter_param_set_integer(RS_FILTER_PARAM(response), "proposed-crop-y2", 
proposed_crop->y2);
+//                             g_debug("x1:%d, y1:%d, x2:%d, y2:%d", 
proposed_crop->x1, proposed_crop->y1, proposed_crop->x2, proposed_crop->y2);
+                       }
+                       else 
+                               g_free(proposed_crop);
                        g_free(t);
                        rs_filter_response_set_image(response, output);
                        g_object_unref(output);


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

Reply via email to