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

2016-01-03 Thread spitzak
From: 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 (, reconstruct_x, sample_x, sx, subsample_x);
-vert = create_1d_filter (, 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.9.1

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


[Pixman] [PATCH 07/13] pixman-filter: Corrections to the integral() function

2016-01-03 Thread spitzak
From: Bill Spitzak 

The IMPULSE special-cases did not sample the center of the of the region.
This caused it to sample the filters outside their range, and produce
assymetric filters and other errors. Fixing this required changing the
arguments to integral() so the correct point could be determined.

I fixed the nice filter and the integration to directly produce normalized
values. Re-normalization is still needed for impulse.box or impulse.triangle
so I did not remove it.

Distribute fixed error over all filter samples, to remove a high-frequency
bit of noise in the center of some filters (lancoz at large scale value).

I removed the recursion where it splits at zero. This would only be necessary
if the curve was not smooth at this point, but it is for all integrations
(even linear.linear is smooth). Plots show that removing this makes no 
difference.

box.box, which I expect will be very common as it is the proposed "good" filter,
was made a lot faster and more accurate. This is easy as the caller already
intersected the two boxes, so the width is the integral.
---
 pixman/pixman-filter.c | 126 +
 1 file changed, 55 insertions(+), 71 deletions(-)

diff --git a/pixman/pixman-filter.c b/pixman/pixman-filter.c
index 5677431..0749e51 100644
--- a/pixman/pixman-filter.c
+++ b/pixman/pixman-filter.c
@@ -79,7 +79,7 @@ sinc (double x)
 }
 
 static double
-lanczos (double x, int n)
+lanczos (double x, double n)
 {
 return sinc (x) * sinc (x * (1.0 / n));
 }
@@ -99,7 +99,7 @@ lanczos3_kernel (double x)
 static double
 nice_kernel (double x)
 {
-return lanczos3_kernel (x * 0.75);
+return lanczos3_kernel (x * 0.75) * 0.75;
 }
 
 static double
@@ -147,45 +147,34 @@ static const filter_info_t filters[] =
 { PIXMAN_KERNEL_LANCZOS3_STRETCHED, nice_kernel,  8.0 },
 };
 
-/* This function scales @sample by @scale, then
- * aligns @x1 in @reconstruct with @x2 in @sample and
- * and integrates the product of the kernels across @width.
+/* This function scales @sample by @scale, shifts it by @pos,
+ * and then integrates the product of the kernels across low..high
  *
  * This function assumes that the intervals are within
  * the kernels in question. E.g., the caller must not
  * try to integrate a linear kernel ouside of [-1:1]
  */
 static double
-integral (pixman_kernel_t reconstruct, double x1,
- pixman_kernel_t sample, double scale, double x2,
- double width)
+integral (pixman_kernel_t reconstruct,
+ pixman_kernel_t sample, double scale, double pos,
+ double low, double high)
 {
-/* 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)
+if (high < low)
 {
-   return
-   integral (reconstruct, x1, sample, scale, x2, - x1) +
-   integral (reconstruct, 0, sample, scale, x2 - x1, width + x1);
+   return 0.0;
 }
-else if (x2 < 0 && x2 + width > 0)
+else if (sample == PIXMAN_KERNEL_IMPULSE)
 {
-   return
-   integral (reconstruct, x1, sample, scale, x2, - x2) +
-   integral (reconstruct, x1 - x2, sample, scale, 0, width + x2);
+   return filters[reconstruct].func (-pos);
 }
 else if (reconstruct == PIXMAN_KERNEL_IMPULSE)
 {
-   assert (width == 0.0);
-   return filters[sample].func (x2 / scale);
+   return filters[sample].func (-pos / scale) / scale;
 }
-else if (sample == PIXMAN_KERNEL_IMPULSE)
+else if (reconstruct == PIXMAN_KERNEL_BOX && sample == PIXMAN_KERNEL_BOX)
 {
-   assert (width == 0.0);
-   return filters[reconstruct].func (x1);
+   assert (high <= low + 1.0);
+   return (high - low) / scale;
 }
 else
 {
@@ -193,32 +182,30 @@ integral (pixman_kernel_t reconstruct, double x1,
 * See http://www.intmath.com/integration/6-simpsons-rule.php
 */
 #define N_SEGMENTS 16
-#define SAMPLE(a1, a2) \
-   (filters[reconstruct].func ((a1)) * filters[sample].func ((a2) / scale))
+#define SAMPLE(a)  \
+   (filters[reconstruct].func ((a)) * filters[sample].func (((a) - pos) / 
scale))

double s = 0.0;
-   double h = width / (double)N_SEGMENTS;
+   double h = (high - low) / (double)N_SEGMENTS;
int i;
 
-   s = SAMPLE (x1, x2);
+   s = SAMPLE (low);
 
for (i = 1; i < N_SEGMENTS; i += 2)
{
-   double a1 = x1 + h * i;
-   double a2 = x2 + h * i;
-   s += 4 * SAMPLE(a1, a2);
+   double a1 = low + h * i;
+   s += 4 * SAMPLE(a1);
}
 
for (i = 2; i < N_SEGMENTS; i += 2)
{
-   double a1 = x1 + h * i;
-   double a2 = x2 + h * i;
- 

[Pixman] [PATCH 12/13] pixman-filter: Made reconstruct==impulse and scale < 1 set scale to 1

2016-01-03 Thread spitzak
From: Bill Spitzak 

This replaces settings that don't work (because the filter cannot be normalized)
with something that produces an image.
---
 pixman/pixman-filter.c | 4 
 1 file changed, 4 insertions(+)

diff --git a/pixman/pixman-filter.c b/pixman/pixman-filter.c
index dba5c74..77fdf01 100644
--- a/pixman/pixman-filter.c
+++ b/pixman/pixman-filter.c
@@ -299,6 +299,8 @@ pixman_filter_create_separable_convolution (int 
*n_values,
 int subsample_x, subsample_y;
 int width, height;
 
+if (reconstruct_x == PIXMAN_KERNEL_IMPULSE && sx < 1.0)
+   sx = 1.0;
 width = filter_width (reconstruct_x, sample_x, sx);
 if (width <= 1)
 {
@@ -307,6 +309,8 @@ pixman_filter_create_separable_convolution (int 
*n_values,
 }
 subsample_x = (1 << subsample_bits_x);
 
+if (reconstruct_y == PIXMAN_KERNEL_IMPULSE && sy < 1.0)
+   sy = 1.0;
 height = filter_width (reconstruct_y, sample_y, sy);
 if (height <= 1)
 {
-- 
1.9.1

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


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

2016-01-03 Thread spitzak
From: 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 0995ad0..06821e3 100644
--- a/demos/scale.c
+++ b/demos/scale.c
@@ -127,6 +127,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 },
@@ -260,7 +269,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"));
@@ -402,6 +413,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 @@
 8
 6
 
+  
+True
+1
+bFilter:/b
+True
+  
+
+
   
 True
 1
 bReconstruct X:/b
 True
   
+  
+1
+  
 
 
   
@@ -206,7 +217,7 @@
 True
   
   
-1
+2
   
 
 
@@ -217,7 +228,7 @@
 True
   
   
-2
+3
   
 
 
@@ -228,7 +239,7 @@
 True
   
   
-3
+4
   
 
 
@@ -239,7 +250,7 @@
 True
   
   
-4
+5
   
 
 
@@ -250,7 +261,15 @@
 True
   
   
-5
+6
+  
+
+
+  
+True
+  
+  
+1
   
 
 
@@ -259,6 +278,7 @@
   
   
 1
+1
   
 
 
@@ -267,7 +287,7 @@
   
   
 1
-1
+2
   
 
 
@@ -276,7 +296,7 @@
   
   
 1
-2
+3
   
 
 
@@ -285,7 +305,7 @@
   
   
 1
-3
+4
   
 
 
@@ -294,7 +314,7 @@
   
   
 1
-4
+5
   
  

[Pixman] [PATCH 10/13] pixman-filter: Gaussian fixes

2016-01-03 Thread spitzak
From: 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 c020208..35bd603 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.9.1

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


[Pixman] [PATCH 06/13] pixman-filter: Correct Simpsons integration

2016-01-03 Thread spitzak
From: Bill Spitzak 

Simpsons uses cubic curve fitting, with 3 samples defining each cubic. This
makes the weights of the samples be in a pattern of 1,4,2,4,2...4,1, and then
dividing the result by 3.

The previous code was using weights of 1,2,6,6...6,2,1. Since it divided by
3 this produced about 2x the desired value (the normalization fixed this).
Also this is effectively a linear interpolation, not Simpsons integration.

With this fix the integration is accurate enough that the number of samples
could be reduced a lot. Likely even 16 samples is too many.
---
 pixman/pixman-filter.c | 17 +++--
 1 file changed, 11 insertions(+), 6 deletions(-)

diff --git a/pixman/pixman-filter.c b/pixman/pixman-filter.c
index 15f9069..5677431 100644
--- a/pixman/pixman-filter.c
+++ b/pixman/pixman-filter.c
@@ -189,8 +189,10 @@ integral (pixman_kernel_t reconstruct, double x1,
 }
 else
 {
-   /* Integration via Simpson's rule */
-#define N_SEGMENTS 128
+   /* Integration via Simpson's rule
+* See http://www.intmath.com/integration/6-simpsons-rule.php
+*/
+#define N_SEGMENTS 16
 #define SAMPLE(a1, a2) \
(filters[reconstruct].func ((a1)) * filters[sample].func ((a2) / scale))

@@ -204,11 +206,14 @@ integral (pixman_kernel_t reconstruct, double x1,
{
double a1 = x1 + h * i;
double a2 = x2 + h * i;
+   s += 4 * SAMPLE(a1, a2);
+   }
 
-   s += 2 * SAMPLE (a1, a2);
-
-   if (i >= 2 && i < N_SEGMENTS - 1)
-   s += 4 * SAMPLE (a1, a2);
+   for (i = 2; i < N_SEGMENTS; i += 2)
+   {
+   double a1 = x1 + h * i;
+   double a2 = x2 + h * i;
+   s += 2 * SAMPLE(a1, a2);
}
 
s += SAMPLE (x1 + width, x2 + width);
-- 
1.9.1

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


[Pixman] [PATCH 11/13] pixman-filter: Turn off subsampling for width=1 filters

2016-01-03 Thread spitzak
From: Bill Spitzak 

Due to normalization these filters must all be identical (a single 1.0).

Also make IMPULSE.IMPULSE produce a width=1 filter, rather than zero
(which did not work).
---
 pixman/pixman-filter.c | 14 --
 1 file changed, 12 insertions(+), 2 deletions(-)

diff --git a/pixman/pixman-filter.c b/pixman/pixman-filter.c
index 35bd603..dba5c74 100644
--- a/pixman/pixman-filter.c
+++ b/pixman/pixman-filter.c
@@ -299,11 +299,21 @@ pixman_filter_create_separable_convolution (int   
  *n_values,
 int subsample_x, subsample_y;
 int width, height;
 
+width = filter_width (reconstruct_x, sample_x, sx);
+if (width <= 1)
+{
+   width = 1;
+   subsample_bits_x = 0;
+}
 subsample_x = (1 << subsample_bits_x);
-subsample_y = (1 << subsample_bits_y);
 
-width = filter_width (reconstruct_x, sample_x, sx);
 height = filter_width (reconstruct_y, sample_y, sy);
+if (height <= 1)
+{
+   height = 1;
+   subsample_bits_y = 0;
+}
+subsample_y = (1 << subsample_bits_y);
 
 *n_values = 4 + width * subsample_x + height * subsample_y;
 
-- 
1.9.1

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


[Pixman] [PATCH 08/13] pixman-filter: don't range-check impulse filter

2016-01-03 Thread spitzak
From: 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 0749e51..2298235 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.9.1

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


[Pixman] [PATCH 13/13] pixman-image: Implement PIXMAN_FILTER_GOOD/BEST as separable convolutions

2016-01-03 Thread spitzak
From: Bill Spitzak 

Detects and uses PIXMAN_FILTER_NEAREST for all 8 90-degree rotations and
reflections when the scale is 1.0 and integer translation.

GOOD uses:

 scale < 1/16 : BOX.BOX at size 16
 scale < 3/4 : BOX.BOX at size 1/scale
 larger : BOX.BOX at size 1

 If both directions have a scale >= 3/4 or a scale of 1/2 and an integer
 translation, the faster PIXMAN_FILTER_BILINEAR code is used.

BEST uses:

 scale < 1/24 : BOX.BOX at size 24
 scale < 1/16 : BOX.BOX at size 1/scale
 scale < 1 : IMPULSE.LANCZOS2 at size 1/scale
 scale < 2 : IMPULSE.LANCZOS2 at size 1
 scale < 128 : BOX.LANCZOS2 at size 1/(scale-1) (antialiased square pixels)
 larger : BOX.LANCZOS2 at size 1/127 (antialias blur gets thicker)
---
 pixman/pixman-image.c | 299 +-
 1 file changed, 220 insertions(+), 79 deletions(-)

diff --git a/pixman/pixman-image.c b/pixman/pixman-image.c
index 69743c4..4ef3dab 100644
--- a/pixman/pixman-image.c
+++ b/pixman/pixman-image.c
@@ -28,6 +28,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #include "pixman-private.h"
 
@@ -274,112 +275,252 @@ compute_image_info (pixman_image_t *image)
  FAST_PATH_X_UNIT_POSITIVE |
  FAST_PATH_Y_UNIT_ZERO |
  FAST_PATH_AFFINE_TRANSFORM);
+   switch (image->common.filter)
+   {
+   case PIXMAN_FILTER_CONVOLUTION:
+   break;
+   case PIXMAN_FILTER_SEPARABLE_CONVOLUTION:
+   flags |= FAST_PATH_SEPARABLE_CONVOLUTION_FILTER;
+   break;
+   default:
+   flags |= (FAST_PATH_NEAREST_FILTER | 
FAST_PATH_NO_CONVOLUTION_FILTER);
+   break;
+   }
 }
 else
 {
+   pixman_fixed_t (*m)[3] = image->common.transform->matrix;
+   double dx, dy;
+   int xsubsample, ysubsample;
+   int nearest_ok, bilinear_ok;
+
flags |= FAST_PATH_HAS_TRANSFORM;
 
-   if (image->common.transform->matrix[2][0] == 0  &&
-   image->common.transform->matrix[2][1] == 0  &&
-   image->common.transform->matrix[2][2] == pixman_fixed_1)
+   nearest_ok = FALSE;
+bilinear_ok = FALSE;
+
+   if (m[2][0] == 0&&
+   m[2][1] == 0&&
+   m[2][2] == pixman_fixed_1)
{
flags |= FAST_PATH_AFFINE_TRANSFORM;
 
-   if (image->common.transform->matrix[0][1] == 0 &&
-   image->common.transform->matrix[1][0] == 0)
+   if (m[0][1] == 0 && m[1][0] == 0)
{
-   if (image->common.transform->matrix[0][0] == -pixman_fixed_1 &&
-   image->common.transform->matrix[1][1] == -pixman_fixed_1)
+   flags |= FAST_PATH_SCALE_TRANSFORM;
+   if (abs(m[0][0]) == pixman_fixed_1 &&
+   abs(m[1][1]) == pixman_fixed_1)
{
-   flags |= FAST_PATH_ROTATE_180_TRANSFORM;
+   nearest_ok = TRUE;
+   if (m[0][0] < 0 && m[1][1] < 0)
+   flags |= FAST_PATH_ROTATE_180_TRANSFORM;
}
-   flags |= FAST_PATH_SCALE_TRANSFORM;
}
-   else if (image->common.transform->matrix[0][0] == 0 &&
-image->common.transform->matrix[1][1] == 0)
+   else if (m[0][0] == 0 && m[1][1] == 0)
{
-   pixman_fixed_t m01 = image->common.transform->matrix[0][1];
-   pixman_fixed_t m10 = image->common.transform->matrix[1][0];
-
-   if (m01 == -pixman_fixed_1 && m10 == pixman_fixed_1)
-   flags |= FAST_PATH_ROTATE_90_TRANSFORM;
-   else if (m01 == pixman_fixed_1 && m10 == -pixman_fixed_1)
-   flags |= FAST_PATH_ROTATE_270_TRANSFORM;
+   if (abs(m[0][1]) == pixman_fixed_1 &&
+   abs(m[1][0]) == pixman_fixed_1)
+   {
+   nearest_ok = TRUE;
+   if (m[0][1] < 0 && m[1][0] > 0)
+   flags |= FAST_PATH_ROTATE_90_TRANSFORM;
+   else if (m[0][1] > 0 && m[1][0] < 0)
+   flags |= FAST_PATH_ROTATE_270_TRANSFORM;
+   }
}
}
 
-   if (image->common.transform->matrix[0][0] > 0)
+   if (nearest_ok)
+   {
+   /* reject non-integer translation: */
+   if (pixman_fixed_frac (m[0][2] | m[1][2]))
+   nearest_ok = FALSE;
+   /* FIXME: there are some affine-test failures, showing
+* that handling of BILINEAR and NEAREST filter is not
+* quite equivalent when getting close to 32K for the
+* translation components of the matrix. That's likely
+* some bug, but for now just skip BILINEAR->NEAREST
+* optimization in this case.
+*/
+   else if (abs(m[0][2] | m[1][2]) > pixman_int_to_fixed (3))
+   

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

2016-01-03 Thread spitzak
From: 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 2298235..c020208 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.9.1

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


[Pixman] [PATCH 04/13] pixman-filter: Consistency in arg names to integral ()

2016-01-03 Thread spitzak
From: Bill Spitzak 

Rename kernel1/2 to reconstruct/sample and use 1/scale as the
scale argument, thus matching the names in other functions.
---
 pixman/pixman-filter.c | 28 ++--
 1 file changed, 14 insertions(+), 14 deletions(-)

diff --git a/pixman/pixman-filter.c b/pixman/pixman-filter.c
index b2bf53f..05bc345 100644
--- a/pixman/pixman-filter.c
+++ b/pixman/pixman-filter.c
@@ -147,8 +147,8 @@ static const filter_info_t filters[] =
 { PIXMAN_KERNEL_LANCZOS3_STRETCHED, nice_kernel,  8.0 },
 };
 
-/* This function scales @kernel2 by @scale, then
- * aligns @x1 in @kernel1 with @x2 in @kernel2 and
+/* This function scales @sample by @scale, then
+ * aligns @x1 in @reconstruct with @x2 in @sample and
  * and integrates the product of the kernels across @width.
  *
  * This function assumes that the intervals are within
@@ -156,8 +156,8 @@ static const filter_info_t filters[] =
  * try to integrate a linear kernel ouside of [-1:1]
  */
 static double
-integral (pixman_kernel_t kernel1, double x1,
- pixman_kernel_t kernel2, double scale, double x2,
+integral (pixman_kernel_t reconstruct, double x1,
+ pixman_kernel_t sample, double scale, double x2,
  double width)
 {
 /* If the integration interval crosses zero, break it into
@@ -168,31 +168,31 @@ integral (pixman_kernel_t kernel1, double x1,
 if (x1 < 0 && x1 + width > 0)
 {
return
-   integral (kernel1, x1, kernel2, scale, x2, - x1) +
-   integral (kernel1, 0, kernel2, scale, x2 - x1, width + x1);
+   integral (reconstruct, x1, sample, scale, x2, - x1) +
+   integral (reconstruct, 0, sample, scale, x2 - x1, width + x1);
 }
 else if (x2 < 0 && x2 + width > 0)
 {
return
-   integral (kernel1, x1, kernel2, scale, x2, - x2) +
-   integral (kernel1, x1 - x2, kernel2, scale, 0, width + x2);
+   integral (reconstruct, x1, sample, scale, x2, - x2) +
+   integral (reconstruct, x1 - x2, sample, scale, 0, width + x2);
 }
-else if (kernel1 == PIXMAN_KERNEL_IMPULSE)
+else if (reconstruct == PIXMAN_KERNEL_IMPULSE)
 {
assert (width == 0.0);
-   return filters[kernel2].func (x2 * scale);
+   return filters[sample].func (x2 / scale);
 }
-else if (kernel2 == PIXMAN_KERNEL_IMPULSE)
+else if (sample == PIXMAN_KERNEL_IMPULSE)
 {
assert (width == 0.0);
-   return filters[kernel1].func (x1);
+   return filters[reconstruct].func (x1);
 }
 else
 {
/* Integration via Simpson's rule */
 #define N_SEGMENTS 128
 #define SAMPLE(a1, a2) \
-   (filters[kernel1].func ((a1)) * filters[kernel2].func ((a2) * scale))
+   (filters[reconstruct].func ((a1)) * filters[sample].func ((a2) / scale))

double s = 0.0;
double h = width / (double)N_SEGMENTS;
@@ -270,7 +270,7 @@ create_1d_filter (int *width,
ihigh = MIN (shigh, rhigh);
 
c = integral (reconstruct, ilow,
- sample, 1.0 / scale, ilow - pos,
+ sample, scale, ilow - pos,
  ihigh - ilow);
}
 
-- 
1.9.1

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


[Pixman] [PATCH 03/13] pixman-image: Added GNUPLOT_OUTPUT compile-time option to view filters in gnuplot

2016-01-03 Thread spitzak
From: Bill Spitzak 

If GNUPLOT_OUTPUT is set, then you can pipe the output of a pixman-using program
to gnuplot and get a continuously-updated plot of the horizontal filter. This
works well with demos/scale to test the filter generation.

The plot is all the different subposition filters shuffled together. This is
misleading in a few cases:

  IMPULSE.BOX - goes up and down as the subfilters have different numbers of 
non-zero samples
  IMPULSE.TRIANGLE - somewhat crooked for the same reason
  1-wide filters - looks triangular, but a 1-wide box would be more accurate
---
 pixman/pixman-image.c | 40 
 1 file changed, 40 insertions(+)

diff --git a/pixman/pixman-image.c b/pixman/pixman-image.c
index 1ff1a49..69743c4 100644
--- a/pixman/pixman-image.c
+++ b/pixman/pixman-image.c
@@ -531,6 +531,46 @@ compute_image_info (pixman_image_t *image)
 
 image->common.flags = flags;
 image->common.extended_format_code = code;
+/* If GNUPLOT_OUTPUT is set, then you can pipe the output of a pixman-using 
program
+ * to gnuplot and get a continuously-updated plot of the horizontal filter. 
This
+ * works well with demos/scale to test the filter generation.
+ *
+ * The plot is all the different subposition filters shuffled together. This is
+ * misleading in a few cases:
+ *
+ *  IMPULSE.BOX - goes up and down as the subfilters have different numbers of 
non-zero samples
+ *  IMPULSE.TRIANGLE - somewhat crooked for the same reason
+ *  1-wide filters - looks triangular, but a 1-wide box would be more accurate
+ */
+/* #define GNUPLOT_OUTPUT 1 */
+#if GNUPLOT_OUTPUT
+if ((flags & FAST_PATH_SEPARABLE_CONVOLUTION_FILTER) && 
image->common.filter_params) {
+   const pixman_fixed_t* p = image->common.filter_params;
+   int width = pixman_fixed_to_int(p[0]);
+   int samples = 1 << pixman_fixed_to_int(p[2]);
+   int x,y;
+   p += 4;
+   printf("plot '-' with linespoints\n");
+   printf("%g 0\n", - width * .5);
+   for (x = 0; x < width; ++x) {
+   for (y = 0; y < samples; ++y) {
+   int yy;
+   if (width & 1)
+   yy = y;
+   else if (y >= samples / 2)
+   yy = y - samples / 2;
+   else
+   yy = samples / 2 + y;
+   printf("%g %g\n",
+  x - width * .5 + (y + .5) * (1.0 / samples),
+  pixman_fixed_to_double(p[(yy + 1) * width - x - 1]));
+   }
+   }
+   printf("%g 0\n", width * .5);
+   printf("e\n");
+   fflush(stdout);
+}
+#endif
 }
 
 void
-- 
1.9.1

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


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

2016-01-03 Thread Bill Spitzak
Indeed, further tests reveal there was a bug if one of the filters is 
IMPULSE. It was not sampling at the center of the filter, but instead 
offset by the width. I have a patch to fix this that will be in the next 
set.


On 12/26/2015 08:05 PM, Bill Spitzak wrote:

Sounds like I better look at this more carefully, it is quite possible
it is producing bad filters but with small enough error that the images
look OK.

On Dec 23, 2015 5:25 AM, "Oded Gabbay" > wrote:

On Tue, Dec 22, 2015 at 9:01 PM, Bill Spitzak > wrote:
 >
 >
 > On Tue, Dec 22, 2015 at 4:38 AM, Oded Gabbay
> wrote:
 >>
 >> On Sat, Dec 12, 2015 at 8:06 PM,  > wrote:
 >> > From: Bill Spitzak >
 >> >
 >> > The other filters do not check for x being in range, so there is
 >> > no reason for cubic to do so.
 >>
 >> This argument is a bit problematic.
 >> We could also argue that this filter was actually implemented
 >> correctly/more robust and we should add checks for x to the other
 >> filters.
 >>
 >> I fail to see how this saves us much except from removing a
condition
 >> in a very specific path.
 >>
 >> Do you argue that ax will never ever be >=2 ?
 >
 >
 > Yes, because if that could happen, then out-of-range x could also
be sent to
 > the other filter functions that are not doing the range check.
 >
I run the scale demo, and added a printf everytime ax is >=2.
I got a LOT of prints...
So I don't think your argument is correct.

 > Adding range checks to all the other filters (especially the ones
that
 > return constants) would add a bunch of conditions that are never
used.

Maybe, but it might be necessary to produce more accurate results ?

Oded


 >
 >>
 >>
 >>Oded
 >>
 >> > ---
 >> >  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.9.1
 >> >
 >> > ___
 >> > Pixman mailing list
 >> > Pixman@lists.freedesktop.org 
 >> > http://lists.freedesktop.org/mailman/listinfo/pixman
 >
 >



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