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