Author: post
Date: 2009-12-29 18:09:17 +0100 (Tue, 29 Dec 2009)
New Revision: 2879
Modified:
branches/rawstudio-ng-color/plugins/lensfun/lensfun.c
branches/rawstudio-ng-color/plugins/lensfun/rs-lensfun-select.c
Log:
Lensfun: Added SSE2 optimized distortion modifier. Fixed lens update and
allocation.
Modified: branches/rawstudio-ng-color/plugins/lensfun/lensfun.c
===================================================================
--- branches/rawstudio-ng-color/plugins/lensfun/lensfun.c 2009-12-29
16:37:45 UTC (rev 2878)
+++ branches/rawstudio-ng-color/plugins/lensfun/lensfun.c 2009-12-29
17:09:17 UTC (rev 2879)
@@ -21,6 +21,9 @@
#include <rawstudio.h>
#include <lensfun.h>
+#if defined (__SSE2__)
+#include <emmintrin.h>
+#endif /* __SSE2__ */
#include <rs-lens.h>
#include "rs-lensfun-select.h"
@@ -50,7 +53,7 @@
gfloat vignetting_k2;
gfloat vignetting_k3;
- const lfLens *selected_lens;
+ lfLens *selected_lens;
const lfCamera *selected_camera;
gboolean DIRTY;
@@ -84,7 +87,9 @@
static RSFilterResponse *get_image(RSFilter *filter, const RSFilterRequest
*request);
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);
-
+#if defined (__SSE2__)
+static void inline rs_image16_bilinear_full_sse2(RS_IMAGE16 *in, gushort *out,
gfloat *pos);
+#endif
static RSFilterClass *rs_lensfun_parent_class = NULL;
G_MODULE_EXPORT void
@@ -280,6 +285,7 @@
rs_filter_changed(RS_FILTER(lensfun),
RS_FILTER_CHANGED_PIXELDATA);
break;
case PROP_VIGNETTING_K2:
+ /* FIXME: only have one vignetting input */
lensfun->vignetting_k1 = g_value_get_float(value);
lensfun->vignetting_k2 = g_value_get_float(value);
rs_filter_changed(RS_FILTER(lensfun),
RS_FILTER_CHANGED_PIXELDATA);
@@ -338,7 +344,11 @@
for(x = 0; x < t->roi->width ; x++)
{
+#if defined (__SSE2__)
+ rs_image16_bilinear_full_sse2(t->input, target,
l_pos);
+#else
rs_image16_bilinear_full(t->input, target,
l_pos);
+#endif
target += pixelsize;
l_pos += 6;
}
@@ -392,6 +402,8 @@
if(lensfun->DIRTY)
{
+ if (lensfun->selected_lens)
+ lf_free(lensfun->selected_lens);
const lfCamera **cameras = NULL;
const lfLens **lenses = NULL;
@@ -428,8 +440,9 @@
lenses = lf_db_find_lenses_hd(lensfun->ldb,
lensfun->selected_camera, make, model, 0);
if (lenses)
{
- /* FIXME: selecting first lens */
- lensfun->selected_lens = lenses [0];
+ lensfun->selected_lens = lf_lens_new();
+ /* FIXME: selecting first lens */
+ lf_lens_copy(lensfun->selected_lens,
lenses [0]);
lf_free (lenses);
}
}
@@ -458,7 +471,6 @@
g_object_unref(input);
return response;
}
- /* FIXME: It can be safely assumed that we leak this */
lfLens* lens = lf_lens_new ();
lens->Model = lensfun->model;
lens->MinFocal = 10.0;
@@ -490,30 +502,43 @@
{
gint effective_flags;
- /*FIXME: TCA and Vignetting should default to the values in
lensfun db */
+ printf("CA(R): %f, CA(B):%f, VIGN(K1): %f\n", lensfun->tca_kr,
lensfun->tca_kb, lensfun->vignetting_k1);
+
/* Set TCA */
- lfLensCalibTCA tca;
- tca.Model = LF_TCA_MODEL_LINEAR;
- const char *details = NULL;
- const lfParameter **params = NULL;
- lf_get_tca_model_desc (tca.Model, &details, ¶ms);
- tca.Terms[0] = (lensfun->tca_kr/100)+1;
- tca.Terms[1] = (lensfun->tca_kb/100)+1;
- lf_lens_add_calib_tca((lfLens *) lensfun->selected_lens,
(lfLensCalibTCA *) &tca);
+ if (ABS(lensfun->tca_kr) > 0.01f || ABS(lensfun->tca_kb) >
0.01f)
+ {
+ lfLensCalibTCA tca;
+ tca.Model = LF_TCA_MODEL_LINEAR;
+ const char *details = NULL;
+ const lfParameter **params = NULL;
+ lf_get_tca_model_desc (tca.Model, &details, ¶ms);
+ tca.Terms[0] = (lensfun->tca_kr/100)+1;
+ tca.Terms[1] = (lensfun->tca_kb/100)+1;
+ lf_lens_add_calib_tca((lfLens *)
lensfun->selected_lens, (lfLensCalibTCA *) &tca);
+ } else
+ {
+ lf_lens_remove_calib_tca(lensfun->selected_lens, 0);
+ lf_lens_remove_calib_tca(lensfun->selected_lens, 1);
+ }
/* Set vignetting */
- lfLensCalibVignetting vignetting;
- vignetting.Model = LF_VIGNETTING_MODEL_PA;
-// const char *details;
-// const lfParameter **params;
-// lf_get_vignetting_model_desc(vignetting.Model,
&details, ¶ms);
- vignetting.Distance = 1.0;
- vignetting.Focal = lensfun->focal;
- vignetting.Aperture = lensfun->aperture;
- vignetting.Terms[0] = -lensfun->vignetting_k1 * 0.5;
- vignetting.Terms[1] = -lensfun->vignetting_k2 * -0.125;
- vignetting.Terms[2] = lensfun->vignetting_k3;
- lf_lens_add_calib_vignetting((lfLens *) lensfun->selected_lens,
&vignetting);
+ if (ABS(lensfun->vignetting_k1) > 0.01f ||
ABS(lensfun->vignetting_k2) > 0.01f)
+ {
+ lfLensCalibVignetting vignetting;
+ vignetting.Model = LF_VIGNETTING_MODEL_PA;
+ vignetting.Distance = 1.0;
+ vignetting.Focal = lensfun->focal;
+ vignetting.Aperture = lensfun->aperture;
+ vignetting.Terms[0] = -lensfun->vignetting_k1 * 0.5;
+ vignetting.Terms[1] = -lensfun->vignetting_k2 * -0.125;
+ vignetting.Terms[2] = lensfun->vignetting_k3;
+ lf_lens_add_calib_vignetting((lfLens *)
lensfun->selected_lens, &vignetting);
+ } else
+ {
+ lf_lens_remove_calib_vignetting(lensfun->selected_lens,
0);
+ lf_lens_remove_calib_vignetting(lensfun->selected_lens,
1);
+ lf_lens_remove_calib_vignetting(lensfun->selected_lens,
2);
+ }
lfModifier *mod = lf_modifier_new (lensfun->selected_lens,
lensfun->selected_camera->CropFactor, input->w, input->h);
effective_flags = lf_modifier_initialize (mod,
lensfun->selected_lens,
@@ -678,3 +703,121 @@
out[i] = (gushort) ((a[i]*aw + b[i]*bw + c[i]*cw + d[i]*dw
+ 16384) >> 15 );
}
}
+
+
+#if defined (__SSE2__)
+static gfloat twofiftytwo_ps[4] __attribute__ ((aligned (16))) = {256.0f,
256.0f, 256.0f, 0.0f};
+
+static void inline
+rs_image16_bilinear_full_sse2(RS_IMAGE16 *in, gushort *out, gfloat *pos)
+{
+ const gint m_w = (in->w-1);
+ const gint m_h = (in->h-1);
+
+ __m128 p0, p1;
+ if ((uintptr_t)pos & 15)
+ {
+ p0 = _mm_loadu_ps(pos); // y1x1 y0x0
+ p1 = _mm_loadu_ps(pos+4); // ---- y2x2
+ } else
+ {
+ p0 = _mm_load_ps(pos); // y1x1 y0x0
+ p1 = _mm_load_ps(pos+4); // ---- y2x2
+ }
+
+ __m128 xf = _mm_shuffle_ps(p1, p0, _MM_SHUFFLE(0,2,2,0));
+ __m128 yf = _mm_shuffle_ps(p1, p0, _MM_SHUFFLE(1,3,1,1));
+
+ __m128 fl256 = _mm_load_ps(twofiftytwo_ps);
+ xf = _mm_mul_ps(xf, fl256);
+ yf = _mm_mul_ps(yf, fl256);
+ __m128i x = _mm_cvttps_epi32(xf);
+ __m128i y = _mm_cvttps_epi32(yf);
+
+ __m128i _m_w = _mm_slli_epi32(_mm_set1_epi32(m_w), 8);
+ __m128i _m_h = _mm_slli_epi32(_mm_set1_epi32(m_h), 8);
+
+ __m128i x_gt, y_gt;
+
+ /* If positions from lensfun is properly clamped this should not be
needed */
+ /* Enable, if crashes begin occuring here here */
+#if 0
+ x_gt = _mm_cmpgt_epi32(x, _m_w);
+ y_gt = _mm_cmpgt_epi32(y, _m_h);
+
+ 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 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 one = _mm_set1_epi32(1);
+ __m128i nx = _mm_add_epi32(one, _mm_srai_epi32(x, 8));
+ __m128i ny = _mm_add_epi32(one, _mm_srai_epi32(y, 8));
+
+ _m_w = _mm_srai_epi32(_m_w, 8);
+ _m_h = _mm_srai_epi32(_m_h, 8);
+
+ x_gt = _mm_cmpgt_epi32(nx, _m_w);
+ y_gt = _mm_cmpgt_epi32(ny, _m_h);
+
+ nx = _mm_or_si128(_mm_andnot_si128(x_gt, nx), _mm_and_si128(_m_w,
x_gt));
+ ny = _mm_or_si128(_mm_andnot_si128(y_gt, ny), _mm_and_si128(_m_h,
y_gt));
+
+ int xfer[16] __attribute__ ((aligned (16)));
+
+ _mm_store_si128((__m128i*)xfer, _mm_srai_epi32(x, 8));
+ _mm_store_si128((__m128i*)&xfer[4], _mm_srai_epi32(y, 8));
+ _mm_store_si128((__m128i*)&xfer[8], nx);
+ _mm_store_si128((__m128i*)&xfer[12], ny);
+
+ gushort* pixels[12];
+
+ /* Loop unrolled, allows agressive instruction reordering */
+ /* Red, then G & B */
+ pixels[0] = GET_PIXEL(in, xfer[0], xfer[4]); // a
+ pixels[1] = GET_PIXEL(in, xfer[8], xfer[4]); // b
+ pixels[2] = GET_PIXEL(in, xfer[0], xfer[12]); // c
+ pixels[3] = GET_PIXEL(in, xfer[8], xfer[12]); // d
+
+ pixels[4] = GET_PIXEL(in, xfer[1], xfer[1+4]) + 1; // a
+ pixels[4+1] = GET_PIXEL(in, xfer[1+8], xfer[1+4]) + 1; // b
+ pixels[4+2] = GET_PIXEL(in, xfer[1], xfer[1+12]) + 1; // c
+ pixels[4+3] = GET_PIXEL(in, xfer[1+8], xfer[1+12]) + 1; // d
+
+ pixels[2*4] = GET_PIXEL(in, xfer[2], xfer[2+4]) + 2; // a
+ pixels[2*4+1] = GET_PIXEL(in, xfer[2+8], xfer[2+4]) + 2; // b
+ pixels[2*4+2] = GET_PIXEL(in, xfer[2], xfer[2+12]) + 2; // c
+ pixels[2*4+3] = GET_PIXEL(in, xfer[2+8], xfer[2+12]) + 2; // d
+
+ /* Calculate distances */
+ __m128i twofiftyfive = _mm_set1_epi32(255);
+ __m128i diffx = _mm_and_si128(x, twofiftyfive);
+ __m128i diffy = _mm_and_si128(y, twofiftyfive);
+ __m128i inv_diffx = _mm_andnot_si128(diffx, twofiftyfive);
+ __m128i inv_diffy = _mm_andnot_si128(diffy, twofiftyfive);
+
+ /* Calculate weights */
+ __m128i aw = _mm_srai_epi32(_mm_mullo_epi16(inv_diffx, inv_diffy),1);
+ __m128i bw = _mm_srai_epi32(_mm_mullo_epi16(diffx, inv_diffy),1);
+ __m128i cw = _mm_srai_epi32(_mm_mullo_epi16(inv_diffx, diffy),1);
+ __m128i dw = _mm_srai_epi32(_mm_mullo_epi16(diffx, diffy),1);
+
+ _mm_store_si128((__m128i*)xfer, aw);
+ _mm_store_si128((__m128i*)&xfer[4], bw);
+ _mm_store_si128((__m128i*)&xfer[8], cw);
+ _mm_store_si128((__m128i*)&xfer[12], dw);
+
+ gushort** p = pixels;
+ /* Loop unrolled */
+ out[0] = (gushort) ((xfer[0] * *p[0] + xfer[4] * *p[1] + xfer[8] *
*p[2] + xfer[12] * *p[3] + 16384) >> 15 );
+ p+=4;
+ out[1] = (gushort) ((xfer[1] * *p[0] + xfer[1+4] * *p[1] + xfer[1+8] *
*p[2] + xfer[1+12] * *p[3] + 16384) >> 15 );
+ p+=4;
+ out[2] = (gushort) ((xfer[2] * *p[0] + xfer[2+4] * *p[1] + xfer[2+8] *
*p[2] + xfer[2+12] * *p[3] + 16384) >> 15 );
+}
+
+#endif // defined (__SSE2__)
Modified: branches/rawstudio-ng-color/plugins/lensfun/rs-lensfun-select.c
===================================================================
--- branches/rawstudio-ng-color/plugins/lensfun/rs-lensfun-select.c
2009-12-29 16:37:45 UTC (rev 2878)
+++ branches/rawstudio-ng-color/plugins/lensfun/rs-lensfun-select.c
2009-12-29 17:09:17 UTC (rev 2879)
@@ -31,8 +31,8 @@
#include "rs-lensfun-select.h"
void lensfun_editor_load_database(GtkTreeModel *list);
-GtkWidget *gui_dialog_make_from_widget(const gchar *stock_id, gchar
*primary_text, GtkWidget *widget); /* FIXME */
+
/* BEGIN BLOCK - mostly grabbed from UFRaw */
typedef struct {
/* The GtkEntry with camera maker/model name */
@@ -47,6 +47,61 @@
RSLens *lens;
} lens_data;
+
+GtkWidget *
+gui_dialog_make_from_widget(const gchar *stock_id, gchar *primary_text,
GtkWidget *widget)
+{
+ GtkWidget *dialog, *image, *hhbox, *vvbox;
+ GtkWidget *primary_label;
+ gchar *str;
+
+ image = gtk_image_new_from_stock(stock_id, GTK_ICON_SIZE_DIALOG);
+ gtk_misc_set_alignment (GTK_MISC (image), 0.5, 0.0);
+ dialog = gtk_dialog_new();
+ gtk_container_set_border_width (GTK_CONTAINER (dialog), 5);
+ gtk_box_set_spacing (GTK_BOX (GTK_DIALOG (dialog)->vbox), 14);
+ gtk_window_set_resizable (GTK_WINDOW (dialog), FALSE);
+ gtk_dialog_set_has_separator (GTK_DIALOG (dialog), FALSE);
+ gtk_window_set_title (GTK_WINDOW (dialog), "");
+ gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
+ gtk_window_set_destroy_with_parent (GTK_WINDOW (dialog), TRUE);
+
+ primary_label = gtk_label_new (NULL);
+ gtk_label_set_line_wrap (GTK_LABEL (primary_label), TRUE);
+ gtk_label_set_use_markup (GTK_LABEL (primary_label), TRUE);
+ gtk_misc_set_alignment (GTK_MISC (primary_label), 0.0, 0.5);
+ gtk_label_set_selectable (GTK_LABEL (primary_label), TRUE);
+ str = g_strconcat("<span weight=\"bold\" size=\"larger\">",
primary_text, "</span>", NULL);
+ gtk_label_set_markup (GTK_LABEL (primary_label), str);
+ g_free(str);
+
+ hhbox = gtk_hbox_new (FALSE, 12);
+ gtk_container_set_border_width (GTK_CONTAINER (hhbox), 5);
+ gtk_box_pack_start (GTK_BOX (hhbox), image, FALSE, FALSE, 0);
+ vvbox = gtk_vbox_new (FALSE, 12);
+ gtk_box_pack_start (GTK_BOX (hhbox), vvbox, FALSE, FALSE, 0);
+ gtk_box_pack_start (GTK_BOX (vvbox), primary_label, FALSE, FALSE, 0);
+ gtk_box_pack_start (GTK_BOX (vvbox), widget, FALSE, FALSE, 0);
+ gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox), hhbox, FALSE,
FALSE, 0);
+
+ return(dialog);
+}
+
+GtkWidget *
+gui_dialog_make_from_text(const gchar *stock_id, gchar *primary_text, gchar
*secondary_text)
+{
+ GtkWidget *secondary_label;
+
+ secondary_label = gtk_label_new (NULL);
+ gtk_label_set_line_wrap (GTK_LABEL (secondary_label), TRUE);
+ gtk_label_set_use_markup (GTK_LABEL (secondary_label), TRUE);
+ gtk_misc_set_alignment (GTK_MISC (secondary_label), 0.0, 0.5);
+ gtk_label_set_selectable (GTK_LABEL (secondary_label), TRUE);
+ gtk_label_set_markup (GTK_LABEL (secondary_label), secondary_text);
+
+ return(gui_dialog_make_from_widget(stock_id, primary_text,
secondary_label));
+}
+
static void lens_set (lens_data *data, const lfLens *lens)
{
g_print ("Lens: %s / %s\n",
_______________________________________________
Rawstudio-commit mailing list
[email protected]
http://rawstudio.org/cgi-bin/mailman/listinfo/rawstudio-commit