[Pixman] [PATCH pixman 14/15] pixman-filter: Gaussian fixes

2014-12-23 Thread Bill Spitzak
The SIGMA term drops out on simplification.

Expanded the size slightly (from ~4.25 to 5) to make the cutoff less noticable.
The filter is truncated at a value of .001 instead of .006, this new
value is less than 1/2 of 1/255, rather than greater than it.
---
 pixman/pixman-filter.c |7 ++-
 1 file changed, 2 insertions(+), 5 deletions(-)

diff --git a/pixman/pixman-filter.c b/pixman/pixman-filter.c
index bf9dce3..7d7b381 100644
--- a/pixman/pixman-filter.c
+++ b/pixman/pixman-filter.c
@@ -63,10 +63,7 @@ linear_kernel (double x)
 static double
 gaussian_kernel (double x)
 {
-#define SQRT2 (1.4142135623730950488016887242096980785696718753769480)
-#define SIGMA (SQRT2 / 2.0)
-
-return exp (- x * x / (2 * SIGMA * SIGMA)) / (SIGMA * sqrt (2.0 * M_PI));
+return exp (- x * x) / sqrt (M_PI);
 }
 
 static double
@@ -139,7 +136,7 @@ static const filter_info_t filters[] =
 { PIXMAN_KERNEL_BOX,   box_kernel,   1.0 },
 { PIXMAN_KERNEL_LINEAR,linear_kernel,2.0 },
 { PIXMAN_KERNEL_CUBIC, cubic_kernel, 4.0 },
-{ PIXMAN_KERNEL_GAUSSIAN,  gaussian_kernel,  6 * SIGMA },
+{ PIXMAN_KERNEL_GAUSSIAN,  gaussian_kernel,  5.0 },
 { PIXMAN_KERNEL_LANCZOS2,  lanczos2_kernel,  4.0 },
 { PIXMAN_KERNEL_LANCZOS3,  lanczos3_kernel,  6.0 },
 { PIXMAN_KERNEL_LANCZOS3_STRETCHED, nice_kernel,  8.0 },
-- 
1.7.9.5

___
Pixman mailing list
Pixman@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/pixman


[Pixman] [PATCH pixman 07/15] pixman-filter: Speed up the BOX+BOX filter

2014-12-23 Thread Bill Spitzak
This is easy as the caller already intersected the two boxes, so
the width is the integral.
---
 pixman/pixman-filter.c |5 +
 1 file changed, 5 insertions(+)

diff --git a/pixman/pixman-filter.c b/pixman/pixman-filter.c
index 4aafa51..782f73d 100644
--- a/pixman/pixman-filter.c
+++ b/pixman/pixman-filter.c
@@ -182,6 +182,11 @@ integral (pixman_kernel_t reconstruct, double x1,
assert (width == 0.0);
return filters[sample].func (x2 / scale);
 }
+else if (reconstruct == PIXMAN_KERNEL_BOX  sample == PIXMAN_KERNEL_BOX)
+{
+   assert (width = 1.0);
+   return width;
+}
 else if (sample == PIXMAN_KERNEL_IMPULSE)
 {
assert (width == 0.0);
-- 
1.7.9.5

___
Pixman mailing list
Pixman@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/pixman


[Pixman] [PATCH pixman 12/15] pixman-filter: Turn off subsampling when not necessary

2014-12-23 Thread Bill Spitzak
If sample is IMPULSE and reconstruct is BOX or IMPULSE the sub-pixel
position of the sample is not relevant, so only one subsample is needed.
---
 pixman/pixman-filter.c |   12 +++-
 1 file changed, 7 insertions(+), 5 deletions(-)

diff --git a/pixman/pixman-filter.c b/pixman/pixman-filter.c
index 64981cd..7e10108 100644
--- a/pixman/pixman-filter.c
+++ b/pixman/pixman-filter.c
@@ -230,6 +230,8 @@ filter_width (pixman_kernel_t reconstruct,
  pixman_kernel_t sample,
  double scale)
 {
+if (reconstruct == PIXMAN_KERNEL_BOX  sample == PIXMAN_KERNEL_IMPULSE)
+   return 0;
 return ceil (scale * filters[sample].width + filters[reconstruct].width);
 }
 
@@ -323,13 +325,13 @@ pixman_filter_create_separable_convolution (int   
  *n_values,
 int subsample_x, subsample_y;
 int width, height;
 
-subsample_x = (1  subsample_bits_x);
-subsample_y = (1  subsample_bits_y);
-
 width = filter_width (reconstruct_x, sample_x, sx);
-if (width  1) width = 1;
+if (width  1) { width = 1; subsample_bits_x = 0; }
 height = filter_width (reconstruct_y, sample_y, sy);
-if (height  1) height = 1;
+if (height  1) { height = 1; subsample_bits_y = 0; }
+
+subsample_x = (1  subsample_bits_x);
+subsample_y = (1  subsample_bits_y);
 
 *n_values = 4 + width * subsample_x + height * subsample_y;
 
-- 
1.7.9.5

___
Pixman mailing list
Pixman@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/pixman


[Pixman] [PATCH pixman 10/15] pixman-filter: don't range-check impulse filter

2014-12-23 Thread Bill Spitzak
The other filters don't range-check, so there is no need for this
one to either. It is only called with x==0.
---
 pixman/pixman-filter.c |2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/pixman/pixman-filter.c b/pixman/pixman-filter.c
index fbc657d..00126cd 100644
--- a/pixman/pixman-filter.c
+++ b/pixman/pixman-filter.c
@@ -45,7 +45,7 @@ typedef struct
 static double
 impulse_kernel (double x)
 {
-return (x == 0.0)? 1.0 : 0.0;
+return 1;
 }
 
 static double
-- 
1.7.9.5

___
Pixman mailing list
Pixman@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/pixman


[Pixman] [PATCH pixman 06/15] pixman-filter: reduced number of samples in Simpson's integration

2014-12-23 Thread Bill Spitzak
With the cubic fix this is plenty accurate enough, far in excess of the pixman
fixed-point error limit. Likely even 16 samples is too many.
---
 pixman/pixman-filter.c |2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/pixman/pixman-filter.c b/pixman/pixman-filter.c
index 7c1da0d..4aafa51 100644
--- a/pixman/pixman-filter.c
+++ b/pixman/pixman-filter.c
@@ -190,7 +190,7 @@ integral (pixman_kernel_t reconstruct, double x1,
 else
 {
/* Integration via Simpson's rule */
-#define N_SEGMENTS 128
+#define N_SEGMENTS 16
 #define SAMPLE(a1, a2) \
(filters[reconstruct].func ((a1)) * filters[sample].func ((a2) / scale))

-- 
1.7.9.5

___
Pixman mailing list
Pixman@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/pixman


[Pixman] [PATCH pixman 02/15] demos/scale: Added pulldown to choose PIXMAN_FILTER_* value

2014-12-23 Thread Bill Spitzak
This allows testing of GOOD/BEST and to do comparisons between
the basic filters and PIXMAN_FILTER_SEPARABLE_CONVOLUTION settings.
---
 demos/scale.c  |   14 +-
 demos/scale.ui |   40 ++--
 2 files changed, 43 insertions(+), 11 deletions(-)

diff --git a/demos/scale.c b/demos/scale.c
index 71c7791..203168f 100644
--- a/demos/scale.c
+++ b/demos/scale.c
@@ -68,6 +68,15 @@ typedef struct
 intvalue;
 } named_int_t;
 
+static const named_int_t filter_types[] =
+{
+{ Separable, PIXMAN_FILTER_SEPARABLE_CONVOLUTION },
+{ Nearest,   PIXMAN_FILTER_NEAREST },
+{ Bilinear,  PIXMAN_FILTER_BILINEAR },
+{ Good,  PIXMAN_FILTER_GOOD },
+{ Best,  PIXMAN_FILTER_BEST },
+};
+
 static const named_int_t filters[] =
 {
 { Box,   PIXMAN_KERNEL_BOX },
@@ -201,7 +210,9 @@ rescale (GtkWidget *may_be_null, app_t *app)
gtk_adjustment_get_value (app-subsample_adjustment),
gtk_adjustment_get_value (app-subsample_adjustment));
 
-pixman_image_set_filter (app-original, 
PIXMAN_FILTER_SEPARABLE_CONVOLUTION, params, n_params);
+pixman_image_set_filter (app-original,
+   get_value (app, filter_types, filter_combo_box),
+   params, n_params);
 
 pixman_image_set_repeat (
 app-original, get_value (app, repeats, repeat_combo_box));
@@ -343,6 +354,7 @@ app_new (pixman_image_t *original)
 widget = get_widget (app, drawing_area);
 g_signal_connect (widget, expose_event, G_CALLBACK (on_expose), app);
 
+set_up_combo_box (app, filter_combo_box, G_N_ELEMENTS (filter_types), 
filter_types);
 set_up_filter_box (app, reconstruct_x_combo_box);
 set_up_filter_box (app, reconstruct_y_combo_box);
 set_up_filter_box (app, sample_x_combo_box);
diff --git a/demos/scale.ui b/demos/scale.ui
index ee985dd..b62cbfb 100644
--- a/demos/scale.ui
+++ b/demos/scale.ui
@@ -191,12 +191,23 @@
 property name=column_spacing8/property
 property name=row_spacing6/property
 child
+  object class=GtkLabel id=labelF
+property name=visibleTrue/property
+property name=xalign1/property
+property name=label 
translatable=yeslt;bgt;Filter:lt;/bgt;/property
+property name=use_markupTrue/property
+  /object
+/child
+child
   object class=GtkLabel id=label4
 property name=visibleTrue/property
 property name=xalign1/property
 property name=label 
translatable=yeslt;bgt;Reconstruct X:lt;/bgt;/property
 property name=use_markupTrue/property
   /object
+  packing
+property name=top_attach1/property
+  /packing
 /child
 child
   object class=GtkLabel id=label5
@@ -206,7 +217,7 @@
 property name=use_markupTrue/property
   /object
   packing
-property name=top_attach1/property
+property name=top_attach2/property
   /packing
 /child
 child
@@ -217,7 +228,7 @@
 property name=use_markupTrue/property
   /object
   packing
-property name=top_attach2/property
+property name=top_attach3/property
   /packing
 /child
 child
@@ -228,7 +239,7 @@
 property name=use_markupTrue/property
   /object
   packing
-property name=top_attach3/property
+property name=top_attach4/property
   /packing
 /child
 child
@@ -239,7 +250,7 @@
 property name=use_markupTrue/property
   /object
   packing
-property name=top_attach4/property
+property name=top_attach5/property
   /packing
 /child
 child
@@ -250,7 +261,15 @@
 property name=use_markupTrue/property
   /object
   packing
-property name=top_attach5/property
+property name=top_attach6/property
+  /packing
+/child
+child
+  object class=GtkComboBox id=filter_combo_box
+  

[Pixman] [PATCH pixman] V4 Implement PIXMAN_FILTER_GOOD/BEST

2014-12-23 Thread Bill Spitzak
This supersedes my previous set of patches. Changes are to fix some
rebase errors so that it compiles after each patch applies, and some
further rebasing to rearrange the patches and split them into a more
logical order.

___
Pixman mailing list
Pixman@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/pixman


[Pixman] [PATCH pixman 04/15] pixman-filter: reduce amount of malloc/free/memcpy to generate filter

2014-12-23 Thread Bill Spitzak
Rearranged so that the entire block of memory for the filter pair
is allocated first, and then filled in. Previous version allocated
and freed two temporary buffers for each filter and did an extra
memcpy.
---
 pixman/pixman-filter.c |   59 
 1 file changed, 25 insertions(+), 34 deletions(-)

diff --git a/pixman/pixman-filter.c b/pixman/pixman-filter.c
index 05bc345..15f9069 100644
--- a/pixman/pixman-filter.c
+++ b/pixman/pixman-filter.c
@@ -217,25 +217,25 @@ integral (pixman_kernel_t reconstruct, double x1,
 }
 }
 
-static pixman_fixed_t *
-create_1d_filter (int *width,
+static int
+filter_width (pixman_kernel_t reconstruct,
+ pixman_kernel_t sample,
+ double scale)
+{
+return ceil (scale * filters[sample].width + filters[reconstruct].width);
+}
+
+static void
+create_1d_filter (int  width,
  pixman_kernel_t  reconstruct,
  pixman_kernel_t  sample,
  double   scale,
- int  n_phases)
+ int  n_phases,
+ pixman_fixed_t *p)
 {
-pixman_fixed_t *params, *p;
 double step;
-double size;
 int i;
 
-size = scale * filters[sample].width + filters[reconstruct].width;
-*width = ceil (size);
-
-p = params = malloc (*width * n_phases * sizeof (pixman_fixed_t));
-if (!params)
-return NULL;
-
 step = 1.0 / n_phases;
 
 for (i = 0; i  n_phases; ++i)
@@ -250,8 +250,8 @@ create_1d_filter (int *width,
 * and sample positions.
 */
 
-   x1 = ceil (frac - *width / 2.0 - 0.5);
-x2 = x1 + *width;
+   x1 = ceil (frac - width / 2.0 - 0.5);
+x2 = x1 + width;
 
total = 0;
 for (x = x1; x  x2; ++x)
@@ -279,7 +279,7 @@ create_1d_filter (int *width,
 }
 
/* Normalize */
-   p -= *width;
+   p -= width;
 total = 1 / total;
 new_total = 0;
for (x = x1; x  x2; ++x)
@@ -291,10 +291,8 @@ create_1d_filter (int *width,
}
 
if (new_total != pixman_fixed_1)
-   *(p - *width / 2) += (pixman_fixed_1 - new_total);
+   *(p - width / 2) += (pixman_fixed_1 - new_total);
 }
-
-return params;
 }
 
 /* Create the parameter list for a SEPARABLE_CONVOLUTION filter
@@ -313,38 +311,31 @@ pixman_filter_create_separable_convolution (int   
  *n_values,
 {
 double sx = fabs (pixman_fixed_to_double (scale_x));
 double sy = fabs (pixman_fixed_to_double (scale_y));
-pixman_fixed_t *horz = NULL, *vert = NULL, *params = NULL;
+pixman_fixed_t *params;
 int subsample_x, subsample_y;
 int width, height;
 
 subsample_x = (1  subsample_bits_x);
 subsample_y = (1  subsample_bits_y);
 
-horz = create_1d_filter (width, reconstruct_x, sample_x, sx, subsample_x);
-vert = create_1d_filter (height, reconstruct_y, sample_y, sy, 
subsample_y);
+width = filter_width (reconstruct_x, sample_x, sx);
+height = filter_width (reconstruct_y, sample_y, sy);
 
-if (!horz || !vert)
-goto out;
-
 *n_values = 4 + width * subsample_x + height * subsample_y;
-
+
 params = malloc (*n_values * sizeof (pixman_fixed_t));
 if (!params)
-goto out;
+return NULL;
 
 params[0] = pixman_int_to_fixed (width);
 params[1] = pixman_int_to_fixed (height);
 params[2] = pixman_int_to_fixed (subsample_bits_x);
 params[3] = pixman_int_to_fixed (subsample_bits_y);
 
-memcpy (params + 4, horz,
-   width * subsample_x * sizeof (pixman_fixed_t));
-memcpy (params + 4 + width * subsample_x, vert,
-   height * subsample_y * sizeof (pixman_fixed_t));
-
-out:
-free (horz);
-free (vert);
+create_1d_filter (width, reconstruct_x, sample_x, sx, subsample_x,
+ params + 4);
+create_1d_filter (height, reconstruct_y, sample_y, sy, subsample_y,
+ params + 4 + width * subsample_x);
 
 return params;
 }
-- 
1.7.9.5

___
Pixman mailing list
Pixman@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/pixman


[Pixman] [PATCH pixman 08/15] pixman-filter: Don't recurse unnecessarily.

2014-12-23 Thread Bill Spitzak
Only LINEAR is not differentiable at zero, so only do the recursive
split of the integral for it.
---
 pixman/pixman-filter.c |   34 +-
 1 file changed, 17 insertions(+), 17 deletions(-)

diff --git a/pixman/pixman-filter.c b/pixman/pixman-filter.c
index 782f73d..0cd4a68 100644
--- a/pixman/pixman-filter.c
+++ b/pixman/pixman-filter.c
@@ -160,38 +160,38 @@ integral (pixman_kernel_t reconstruct, double x1,
  pixman_kernel_t sample, double scale, double x2,
  double width)
 {
+if (reconstruct == PIXMAN_KERNEL_IMPULSE)
+{
+   assert (width == 0.0);
+   return filters[sample].func (x2 / scale);
+}
+else if (reconstruct == PIXMAN_KERNEL_BOX  sample == PIXMAN_KERNEL_BOX)
+{
+   assert (width = 1.0);
+   return width;
+}
+else if (sample == PIXMAN_KERNEL_IMPULSE)
+{
+   assert (width == 0.0);
+   return filters[reconstruct].func (x1);
+}
 /* If the integration interval crosses zero, break it into
  * two separate integrals. This ensures that filters such
  * as LINEAR that are not differentiable at 0 will still
  * integrate properly.
  */
-if (x1  0  x1 + width  0)
+else if (reconstruct == PIXMAN_KERNEL_LINEAR  x1  0  x1 + width  0)
 {
return
integral (reconstruct, x1, sample, scale, x2, - x1) +
integral (reconstruct, 0, sample, scale, x2 - x1, width + x1);
 }
-else if (x2  0  x2 + width  0)
+else if (sample == PIXMAN_KERNEL_LINEAR  x2  0  x2 + width  0)
 {
return
integral (reconstruct, x1, sample, scale, x2, - x2) +
integral (reconstruct, x1 - x2, sample, scale, 0, width + x2);
 }
-else if (reconstruct == PIXMAN_KERNEL_IMPULSE)
-{
-   assert (width == 0.0);
-   return filters[sample].func (x2 / scale);
-}
-else if (reconstruct == PIXMAN_KERNEL_BOX  sample == PIXMAN_KERNEL_BOX)
-{
-   assert (width = 1.0);
-   return width;
-}
-else if (sample == PIXMAN_KERNEL_IMPULSE)
-{
-   assert (width == 0.0);
-   return filters[reconstruct].func (x1);
-}
 else
 {
/* Integration via Simpson's rule */
-- 
1.7.9.5

___
Pixman mailing list
Pixman@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/pixman


[Pixman] [PATCH pixman 13/15] pixman-filter: refactor cubic polynominal and don't range check

2014-12-23 Thread Bill Spitzak
The other filters do not check for x being in range, so there is
no reason for cubic to do so.
---
 pixman/pixman-filter.c |   16 +++-
 1 file changed, 7 insertions(+), 9 deletions(-)

diff --git a/pixman/pixman-filter.c b/pixman/pixman-filter.c
index 7e10108..bf9dce3 100644
--- a/pixman/pixman-filter.c
+++ b/pixman/pixman-filter.c
@@ -109,18 +109,16 @@ general_cubic (double x, double B, double C)
 
 if (ax  1)
 {
-   return ((12 - 9 * B - 6 * C) * ax * ax * ax +
-   (-18 + 12 * B + 6 * C) * ax * ax + (6 - 2 * B)) / 6;
-}
-else if (ax = 1  ax  2)
-{
-   return ((-B - 6 * C) * ax * ax * ax +
-   (6 * B + 30 * C) * ax * ax + (-12 * B - 48 * C) *
-   ax + (8 * B + 24 * C)) / 6;
+   return (((12 - 9 * B - 6 * C) * ax +
+(-18 + 12 * B + 6 * C)) * ax * ax +
+   (6 - 2 * B)) / 6;
 }
 else
 {
-   return 0;
+   return -B - 6 * C) * ax +
+(6 * B + 30 * C)) * ax +
+   (-12 * B - 48 * C)) * ax +
+   (8 * B + 24 * C)) / 6;
 }
 }
 
-- 
1.7.9.5

___
Pixman mailing list
Pixman@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/pixman


[Pixman] [PATCH pixman 01/15] demos/scale: Compute filter size using boundary of xformed ellipse, not rectangle

2014-12-23 Thread Bill Spitzak
This is much more accurate and less blurry. In particular the filtering does
not change as the image is rotated.
---
 demos/scale.c |   43 ++-
 1 file changed, 2 insertions(+), 41 deletions(-)

diff --git a/demos/scale.c b/demos/scale.c
index d00307e..71c7791 100644
--- a/demos/scale.c
+++ b/demos/scale.c
@@ -55,50 +55,11 @@ get_widget (app_t *app, const char *name)
 return widget;
 }
 
-static double
-min4 (double a, double b, double c, double d)
-{
-double m1, m2;
-
-m1 = MIN (a, b);
-m2 = MIN (c, d);
-return MIN (m1, m2);
-}
-
-static double
-max4 (double a, double b, double c, double d)
-{
-double m1, m2;
-
-m1 = MAX (a, b);
-m2 = MAX (c, d);
-return MAX (m1, m2);
-}
-
 static void
 compute_extents (pixman_f_transform_t *trans, double *sx, double *sy)
 {
-double min_x, max_x, min_y, max_y;
-pixman_f_vector_t v[4] =
-{
-   { { 1, 1, 1 } },
-   { { -1, 1, 1 } },
-   { { -1, -1, 1 } },
-   { { 1, -1, 1 } },
-};
-
-pixman_f_transform_point (trans, v[0]);
-pixman_f_transform_point (trans, v[1]);
-pixman_f_transform_point (trans, v[2]);
-pixman_f_transform_point (trans, v[3]);
-
-min_x = min4 (v[0].v[0], v[1].v[0], v[2].v[0], v[3].v[0]);
-max_x = max4 (v[0].v[0], v[1].v[0], v[2].v[0], v[3].v[0]);
-min_y = min4 (v[0].v[1], v[1].v[1], v[2].v[1], v[3].v[1]);
-max_y = max4 (v[0].v[1], v[1].v[1], v[2].v[1], v[3].v[1]);
-
-*sx = (max_x - min_x) / 2.0;
-*sy = (max_y - min_y) / 2.0;
+*sx = hypot (trans-m[0][0], trans-m[0][1]) / trans-m[2][2];
+*sy = hypot (trans-m[1][0], trans-m[1][1]) / trans-m[2][2];
 }
 
 typedef struct
-- 
1.7.9.5

___
Pixman mailing list
Pixman@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/pixman